@dezycro-ai/agent-plugin 2.2.0 → 2.3.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.
@@ -1,39 +1,41 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var pe=Object.create;var H=Object.defineProperty;var ue=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var me=Object.getPrototypeOf,he=Object.prototype.hasOwnProperty;var fe=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of de(e))!he.call(r,o)&&o!==t&&H(r,o,{get:()=>e[o],enumerable:!(n=ue(e,o))||n.enumerable});return r};var a=(r,e,t)=>(t=r!=null?pe(me(r)):{},fe(e||!r||!r.__esModule?H(t,"default",{value:r,enumerable:!0}):t,r));var V=a(require("node:http")),v=a(require("node:path")),w=a(require("node:fs")),q=a(require("node:os")),_=require("node:child_process");var d={MessageStart:"message_start",ContentBlockStart:"content_block_start",ContentBlockDelta:"content_block_delta",ContentBlockStop:"content_block_stop",MessageDelta:"message_delta",MessageStop:"message_stop"};var Z={UpdateTask:"update_task"},G={Status:"status"},B={Done:"DONE",Pushed:"PUSHED"};var m={SpecPublished:"specPublished",VerifiedRecently:"verifiedRecently"};var U={Claude:"claude",Codex:"codex"},O={Health:"/__dz/health",Stop:"/__dz/stop"};var W=a(require("node:fs")),h=a(require("node:path")),b=class r{static MAX_DEPTH=6;static dir(){let e=__dirname;for(let t=0;t<r.MAX_DEPTH;t+=1){if(W.existsSync(h.join(e,"package.json")))return e;e=h.dirname(e)}return h.resolve(__dirname,"..","..")}static file(...e){return h.join(r.dir(),...e)}};var x=class r{static DEFAULT_SHIM_CMDS=["npm","pnpm","yarn","pip","pip3","poetry","apt-get","apt","brew","gem","bundle","mvn","gradle","make"];port=Number(process.env.DZ_PORT||13579);proxyPath=b.file("dist","gateway","proxy.js");compactPath=b.file("dist","gateway","compact-cli.js");async run(e){let t=this.applyPortFlag(e),n=t[0];if(n==="--stop"){console.error(await this.control(O.Stop)?"dezycro: stopped":"dezycro: not running");return}if(n==="--status"){console.error(await this.health()?"dezycro: up":"dezycro: down");return}let o=n||U.Claude,s=t.slice(1),i=await this.ensureDaemon();console.error(i?`dezycro: gateway on :${this.port} \u2014 launching ${o}`:`dezycro: gateway unavailable \u2014 launching ${o} DIRECTLY (fail-open)`);let c=this.setupShims(),l={...process.env,...i?this.gatewayUrlEnv(o):{},...c?.env??{}},y=()=>{if(c)try{w.default.rmSync(c.dir,{recursive:!0,force:!0})}catch{}},M=(0,_.spawn)(o,s,{env:l,stdio:"inherit"});M.on("exit",T=>{y(),process.exit(T??0)}),M.on("error",T=>{y(),console.error(`dezycro: failed to launch ${o}: ${T.message}`),process.exit(127)})}applyPortFlag(e){let t=[];for(let n=0;n<e.length;n+=1){let o=e[n];if(o==="--port"){let s=Number(e[n+1]);e[n+1]!==void 0&&Number.isInteger(s)&&s>0&&(this.port=s,n+=1);continue}if(o.startsWith("--port=")){let s=Number(o.slice(7));Number.isInteger(s)&&s>0&&(this.port=s);continue}t.push(o)}return t}gatewayUrlEnv(e){let t=`http://127.0.0.1:${this.port}`;return e===U.Codex?{OPENAI_BASE_URL:`${t}/v1`}:{ANTHROPIC_BASE_URL:t}}async ensureDaemon(){if(await this.health())return!0;let e={...process.env,PORT:String(this.port),INJECT:process.env.INJECT||"1",GATE:process.env.GATE||"0",CAPTURE:process.env.CAPTURE||"0",DZ_STATE_FILE:process.env.DZ_STATE_FILE||v.default.join(process.cwd(),".dezycro","companion-state.json")};(0,_.spawn)(process.execPath,[this.proxyPath],{env:e,detached:!0,stdio:"ignore"}).unref();for(let n=0;n<30;n+=1){if(await this.health())return!0;await r.sleep(100)}return!1}setupShims(){if(process.env.DZ_NO_SHIM==="1"||process.env.DZ_SHIMS==="0")return null;let e=(process.env.DZ_SHIM_CMDS||r.DEFAULT_SHIM_CMDS.join(",")).split(",").map(t=>t.trim()).filter(Boolean);if(!e.length)return null;try{let t=w.default.mkdtempSync(v.default.join(q.default.tmpdir(),"dz-shims-")),n=process.env.PATH||"";for(let o of e){let s=`#!/usr/bin/env bash
3
- real="$(PATH="$DZ_REAL_PATH" command -v ${o} 2>/dev/null)"
4
- if [ -z "$real" ] || [ "\${DZ_NO_SHIM:-0}" = "1" ]; then exec "${o}" "$@"; fi
2
+ "use strict";var Te=Object.create;var C=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var we=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var xe=(o,e)=>{for(var t in e)C(o,t,{get:e[t],enumerable:!0})},X=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of be(e))!Se.call(o,r)&&r!==t&&C(o,r,{get:()=>e[r],enumerable:!(n=ve(e,r))||n.enumerable});return o};var l=(o,e,t)=>(t=o!=null?Te(we(o)):{},X(e||!o||!o.__esModule?C(t,"default",{value:o,enumerable:!0}):t,o)),Ce=o=>X(C({},"__esModule",{value:!0}),o);var Me={};xe(Me,{Command:()=>ke});module.exports=Ce(Me);var ne=l(require("node:http")),w=l(require("node:path")),E=l(require("node:fs")),re=l(require("node:os")),F=require("node:child_process");var d={MessageStart:"message_start",ContentBlockStart:"content_block_start",ContentBlockDelta:"content_block_delta",ContentBlockStop:"content_block_stop",MessageDelta:"message_delta",MessageStop:"message_stop"};var Q={UpdateTask:"update_task"},ee={Status:"status"},_={Done:"DONE",Pushed:"PUSHED"};var m={SpecPublished:"specPublished",VerifiedRecently:"verifiedRecently"};var N={Claude:"claude",Codex:"codex"},j={Health:"/__dz/health",Stop:"/__dz/stop"};var te=l(require("node:fs")),h=l(require("node:path")),b=class o{static MAX_DEPTH=6;static dir(){let e=__dirname;for(let t=0;t<o.MAX_DEPTH;t+=1){if(te.existsSync(h.join(e,"package.json")))return e;e=h.dirname(e)}return h.resolve(__dirname,"..","..")}static file(...e){return h.join(o.dir(),...e)}};var R=class o{static DEFAULT_SHIM_CMDS=["npm","pnpm","yarn","pip","pip3","poetry","apt-get","apt","brew","gem","bundle","mvn","gradle","make"];port=Number(process.env.DZ_PORT||13579);proxyPath=b.file("dist","gateway","proxy.js");compactPath=b.file("dist","gateway","compact-cli.js");async run(e){let t=this.applyPortFlag(e),n=t[0];if(n==="--stop"){console.error(await this.control(j.Stop)?"dezycro: stopped":"dezycro: not running");return}if(n==="--status"){console.error(await this.health()?"dezycro: up":"dezycro: down");return}let r=n||N.Claude,i=t.slice(1),s=await this.ensureDaemon();console.error(s?`dezycro: gateway on :${this.port} \u2014 launching ${r}`:`dezycro: gateway unavailable \u2014 launching ${r} DIRECTLY (fail-open)`);let a=this.setupShims(),c={...process.env,...s?this.gatewayUrlEnv(r):{},...a?.env??{}},k=()=>{if(a)try{E.default.rmSync(a.dir,{recursive:!0,force:!0})}catch{}},B=(0,F.spawn)(r,i,{env:c,stdio:"inherit"});B.on("exit",T=>{k(),process.exit(T??0)}),B.on("error",T=>{k(),console.error(`dezycro: failed to launch ${r}: ${T.message}`),process.exit(127)})}applyPortFlag(e){let t=[];for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="--port"){let i=Number(e[n+1]);e[n+1]!==void 0&&Number.isInteger(i)&&i>0&&(this.port=i,n+=1);continue}if(r.startsWith("--port=")){let i=Number(r.slice(7));Number.isInteger(i)&&i>0&&(this.port=i);continue}t.push(r)}return t}gatewayUrlEnv(e){let t=`http://127.0.0.1:${this.port}`;return e===N.Codex?{OPENAI_BASE_URL:`${t}/v1`}:{ANTHROPIC_BASE_URL:t}}async ensureDaemon(){if(await this.health())return!0;let e={...process.env,PORT:String(this.port),INJECT:process.env.INJECT||"1",GATE:process.env.GATE||"0",CAPTURE:process.env.CAPTURE||"0",DZ_STATE_FILE:process.env.DZ_STATE_FILE||w.default.join(process.cwd(),".dezycro","companion-state.json")};(0,F.spawn)(process.execPath,[this.proxyPath],{env:e,detached:!0,stdio:"ignore"}).unref();for(let n=0;n<30;n+=1){if(await this.health())return!0;await o.sleep(100)}return!1}setupShims(){if(process.env.DZ_NO_SHIM==="1"||process.env.DZ_SHIMS==="0")return null;let e=(process.env.DZ_SHIM_CMDS||o.DEFAULT_SHIM_CMDS.join(",")).split(",").map(t=>t.trim()).filter(Boolean);if(!e.length)return null;try{let t=E.default.mkdtempSync(w.default.join(re.default.tmpdir(),"dz-shims-")),n=process.env.PATH||"";for(let r of e){let i=`#!/usr/bin/env bash
3
+ real="$(PATH="$DZ_REAL_PATH" command -v ${r} 2>/dev/null)"
4
+ if [ -z "$real" ] || [ "\${DZ_NO_SHIM:-0}" = "1" ]; then exec "${r}" "$@"; fi
5
5
  out="$("$real" "$@" 2>&1)"; rc=$?
6
- printf '%s\\n' "$out" | DZ_CMD=${o} node "$DZ_COMPACT_PATH"
6
+ printf '%s\\n' "$out" | DZ_CMD=${r} node "$DZ_COMPACT_PATH"
7
7
  exit $rc
8
- `;w.default.writeFileSync(v.default.join(t,o),s,{mode:493})}return{dir:t,env:{PATH:`${t}${v.default.delimiter}${n}`,DZ_REAL_PATH:n,DZ_COMPACT_PATH:this.compactPath}}}catch{return null}}health(){return this.get(O.Health)}control(e){return this.get(e,()=>!0)}get(e,t=n=>n.statusCode===200){return new Promise(n=>{let o=V.default.get({host:"127.0.0.1",port:this.port,path:e,timeout:800},s=>{s.resume(),n(t(s))});o.on("error",()=>n(!1)),o.on("timeout",()=>{o.destroy(),n(!1)})})}static sleep(e){return new Promise(t=>setTimeout(t,e))}};var Y=require("child_process"),N=a(require("fs")),K=a(require("os")),F=a(require("path")),X=a(require("readline")),R=class r{static MCP_URL="https://mcp.dezycro.ai";run(){console.log(`
8
+ `;E.default.writeFileSync(w.default.join(t,r),i,{mode:493})}return{dir:t,env:{PATH:`${t}${w.default.delimiter}${n}`,DZ_REAL_PATH:n,DZ_COMPACT_PATH:this.compactPath}}}catch{return null}}health(){return this.get(j.Health)}control(e){return this.get(e,()=>!0)}get(e,t=n=>n.statusCode===200){return new Promise(n=>{let r=ne.default.get({host:"127.0.0.1",port:this.port,path:e,timeout:800},i=>{i.resume(),n(t(i))});r.on("error",()=>n(!1)),r.on("timeout",()=>{r.destroy(),n(!1)})})}static sleep(e){return new Promise(t=>setTimeout(t,e))}};var oe=require("child_process"),L=l(require("fs")),se=l(require("os")),J=l(require("path")),ie=l(require("readline")),I=class o{static MCP_URL="https://mcp.dezycro.ai";run(){console.log(`
9
9
  Dezycro Setup`),console.log(` Get your API key from Dezycro \u2192 Settings \u2192 API Keys
10
- `);let e=X.default.createInterface({input:process.stdin,output:process.stdout});e.question(" API key (dzy_...): ",t=>{let n=(t||"").trim();(!n||!n.startsWith("dzy_"))&&(console.log(`
10
+ `);let e=ie.default.createInterface({input:process.stdin,output:process.stdout});e.question(" API key (dzy_...): ",t=>{let n=(t||"").trim();(!n||!n.startsWith("dzy_"))&&(console.log(`
11
11
  Invalid key. Must start with dzy_
12
12
  `),e.close(),process.exit(1)),this.configureMcp(n),this.saveToken(n),console.log(`
13
13
  You're all set! In Claude Code run: /dezycro:import-features
14
- `),e.close()})}configureMcp(e){let t=`claude mcp add --transport http dezycro "${r.MCP_URL}/mcp" --header "Authorization: Bearer ${e}"`;try{(0,Y.execSync)(t,{stdio:"inherit"}),console.log(`
14
+ `),e.close()})}configureMcp(e){let t=`claude mcp add --transport http dezycro "${o.MCP_URL}/mcp" --header "Authorization: Bearer ${e}"`;try{(0,oe.execSync)(t,{stdio:"inherit"}),console.log(`
15
15
  \u2713 Dezycro MCP configured`)}catch{console.error(`
16
16
  Failed to configure MCP. Run manually:`),console.error(` ${t}
17
- `)}}saveToken(e){try{let t=F.default.join(K.default.homedir(),".dezycro"),n=F.default.join(t,"token.json");N.default.mkdirSync(t,{recursive:!0,mode:448}),N.default.writeFileSync(n,JSON.stringify({token:e},null,2),{mode:384}),console.log(` \u2713 Companion token saved to ${n}`)}catch(t){console.error(` Failed to save companion token: ${t.message}`),console.error(` Drop it manually at ~/.dezycro/token.json: {"token": "${e}"}
18
- `)}}};var E=a(require("fs")),Q=a(require("os")),ee=require("child_process"),D=class r{static DEFAULT_PATH=".dezycro/auth.local.json";static PLACEHOLDER=/\$\{([A-Z0-9_]+)\}/g;run(e=r.DEFAULT_PATH){if(!E.default.existsSync(e)){this.warn(`no auth file at ${e}; emitting nothing`);return}let t;try{t=JSON.parse(E.default.readFileSync(e,"utf8"))}catch(s){this.warn(`parse error in ${e}: ${s.message}`),process.exit(1)}let n=this.resolveSecrets(t.secrets||{}),o=this.personaExports(t.personas||{},n);o.length&&process.stdout.write(o.join(`
17
+ `)}}saveToken(e){try{let t=J.default.join(se.default.homedir(),".dezycro"),n=J.default.join(t,"token.json");L.default.mkdirSync(t,{recursive:!0,mode:448}),L.default.writeFileSync(n,JSON.stringify({token:e},null,2),{mode:384}),console.log(` \u2713 Companion token saved to ${n}`)}catch(t){console.error(` Failed to save companion token: ${t.message}`),console.error(` Drop it manually at ~/.dezycro/token.json: {"token": "${e}"}
18
+ `)}}};var D=l(require("fs")),ae=l(require("os")),ce=require("child_process"),A=class o{static DEFAULT_PATH=".dezycro/auth.local.json";static PLACEHOLDER=/\$\{([A-Z0-9_]+)\}/g;run(e=o.DEFAULT_PATH){if(!D.default.existsSync(e)){this.warn(`no auth file at ${e}; emitting nothing`);return}let t;try{t=JSON.parse(D.default.readFileSync(e,"utf8"))}catch(i){this.warn(`parse error in ${e}: ${i.message}`),process.exit(1)}let n=this.resolveSecrets(t.secrets||{}),r=this.personaExports(t.personas||{},n);r.length&&process.stdout.write(r.join(`
19
19
  `)+`
20
- `)}resolveSecrets(e){let t={};for(let[n,o]of Object.entries(e))try{t[n]=this.resolveSecret(o)}catch(s){this.warn(`secret ${n}: ${s.message}`)}return t}personaExports(e,t){let n=[];for(let[o,s]of Object.entries(e))if(!(!s||!s.envVar))try{let i=this.substitute(s.config||{},t);n.push(`export ${s.envVar}=${r.shQuote(JSON.stringify(i))}`)}catch(i){this.warn(`persona '${o}' skipped: ${i.message}`)}return n}resolveSecret(e){if(typeof e!="string")return e;if(e.startsWith("!file:")){let t=e.slice(6);return(t==="~"||t.startsWith("~/"))&&(t=Q.default.homedir()+t.slice(1)),E.default.readFileSync(t,"utf8").trimEnd()}if(e.startsWith("!env:")){let t=e.slice(5);if(!(t in process.env))throw new Error(`env var not set: ${t}`);return process.env[t]}if(e.startsWith("!cmd:")){let t=e.slice(5),o=(0,ee.execSync)(t,{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trimEnd();if(!o)throw new Error(`empty stdout from: ${t}`);return o}return e}substitute(e,t){if(typeof e=="string")return e.replace(r.PLACEHOLDER,(n,o)=>{if(!(o in t))throw new Error(`\${${o}} not in secrets`);return String(t[o])});if(Array.isArray(e))return e.map(n=>this.substitute(n,t));if(e&&typeof e=="object"){let n={};for(let[o,s]of Object.entries(e))n[o]=this.substitute(s,t);return n}return e}warn(e){process.stderr.write(`[dezycro resolve-auth] ${e}
21
- `)}static shQuote(e){return"'"+String(e).replaceAll("'","'\\''")+"'"}};var $=class r{run(e){let t=e[0],n=r.scriptFor(t);n===null&&(process.stderr.write(`Usage: dezycro completion <bash|zsh|fish>
20
+ `)}resolveSecrets(e){let t={};for(let[n,r]of Object.entries(e))try{t[n]=this.resolveSecret(r)}catch(i){this.warn(`secret ${n}: ${i.message}`)}return t}personaExports(e,t){let n=[];for(let[r,i]of Object.entries(e))if(!(!i||!i.envVar))try{let s=this.substitute(i.config||{},t);n.push(`export ${i.envVar}=${o.shQuote(JSON.stringify(s))}`)}catch(s){this.warn(`persona '${r}' skipped: ${s.message}`)}return n}resolveSecret(e){if(typeof e!="string")return e;if(e.startsWith("!file:")){let t=e.slice(6);return(t==="~"||t.startsWith("~/"))&&(t=ae.default.homedir()+t.slice(1)),D.default.readFileSync(t,"utf8").trimEnd()}if(e.startsWith("!env:")){let t=e.slice(5);if(!(t in process.env))throw new Error(`env var not set: ${t}`);return process.env[t]}if(e.startsWith("!cmd:")){let t=e.slice(5),r=(0,ce.execSync)(t,{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trimEnd();if(!r)throw new Error(`empty stdout from: ${t}`);return r}return e}substitute(e,t){if(typeof e=="string")return e.replace(o.PLACEHOLDER,(n,r)=>{if(!(r in t))throw new Error(`\${${r}} not in secrets`);return String(t[r])});if(Array.isArray(e))return e.map(n=>this.substitute(n,t));if(e&&typeof e=="object"){let n={};for(let[r,i]of Object.entries(e))n[r]=this.substitute(i,t);return n}return e}warn(e){process.stderr.write(`[dezycro resolve-auth] ${e}
21
+ `)}static shQuote(e){return"'"+String(e).replaceAll("'","'\\''")+"'"}};var $=class o{run(e){let t=e[0],n=o.scriptFor(t);n===null&&(process.stderr.write(`Usage: dezycro completion <bash|zsh|fish>
22
22
  `),process.stderr.write(`Then load it in your shell, e.g.: eval "$(dezycro completion zsh)"
23
- `),process.exit(2)),process.stdout.write(n)}static scriptFor(e){switch(e){case"bash":return r.bash();case"zsh":return r.zsh();case"fish":return r.fish();default:return null}}static bash(){return["_dezycro() {"," local cur prev cmd",' cur="${COMP_WORDS[COMP_CWORD]}"',' prev="${COMP_WORDS[COMP_CWORD-1]}"',' if [ "$COMP_CWORD" -eq 1 ]; then',' COMPREPLY=( $(compgen -W "run setup resolve-auth completion help --help" -- "$cur") )'," return 0"," fi",' cmd="${COMP_WORDS[1]}"',' case "$cmd" in'," run)",' if [ "$prev" = "--port" ]; then return 0; fi',' COMPREPLY=( $(compgen -W "claude --status --stop --port" -- "$cur") ) ;;'," completion)",' COMPREPLY=( $(compgen -W "bash zsh fish" -- "$cur") ) ;;'," resolve-auth)",' COMPREPLY=( $(compgen -f -- "$cur") ) ;;'," esac"," return 0","}","complete -F _dezycro dezycro",""].join(`
23
+ `),process.exit(2)),process.stdout.write(n)}static scriptFor(e){switch(e){case"bash":return o.bash();case"zsh":return o.zsh();case"fish":return o.fish();default:return null}}static bash(){return["_dezycro() {"," local cur prev cmd",' cur="${COMP_WORDS[COMP_CWORD]}"',' prev="${COMP_WORDS[COMP_CWORD-1]}"',' if [ "$COMP_CWORD" -eq 1 ]; then',' COMPREPLY=( $(compgen -W "run setup resolve-auth completion help --help" -- "$cur") )'," return 0"," fi",' cmd="${COMP_WORDS[1]}"',' case "$cmd" in'," run)",' if [ "$prev" = "--port" ]; then return 0; fi',' COMPREPLY=( $(compgen -W "claude --status --stop --port" -- "$cur") ) ;;'," completion)",' COMPREPLY=( $(compgen -W "bash zsh fish" -- "$cur") ) ;;'," resolve-auth)",' COMPREPLY=( $(compgen -f -- "$cur") ) ;;'," esac"," return 0","}","complete -F _dezycro dezycro",""].join(`
24
24
  `)}static zsh(){return["_dezycro() {"," local -a commands"," commands=(run setup resolve-auth completion help)"," if (( CURRENT == 2 )); then"," compadd -- $commands"," return"," fi"," case ${words[2]} in"," run)"," if [[ ${words[CURRENT-1]} == --port ]]; then return; fi"," compadd -- claude --status --stop --port ;;"," completion) compadd -- bash zsh fish ;;"," resolve-auth) _files ;;"," esac","}","compdef _dezycro dezycro",""].join(`
25
25
  `)}static fish(){return["complete -c dezycro -f","complete -c dezycro -n __fish_use_subcommand -a run -d 'Run an agent through the gateway'","complete -c dezycro -n __fish_use_subcommand -a setup -d 'Configure the Dezycro MCP connection'","complete -c dezycro -n __fish_use_subcommand -a resolve-auth -d 'Print verifier credential exports'","complete -c dezycro -n __fish_use_subcommand -a completion -d 'Print a shell completion script'","complete -c dezycro -n '__fish_seen_subcommand_from run' -a 'claude --status --stop --port'","complete -c dezycro -n '__fish_seen_subcommand_from completion' -a 'bash zsh fish'",""].join(`
26
- `)}};var ce=a(require("node:path"));var A=a(require("node:fs")),te=a(require("node:os")),f=a(require("node:path")),ge="DZ_METRICS_DIR",ke="DZ_METRICS",g=class r{file;constructor(e="gateway"){this.file=r.prepare(e)}static enabled(){return process.env[ke]!=="0"}static dir(){let e=process.env[ge];if(e)return e;let t=te.homedir();switch(process.platform){case"win32":return f.join(process.env.LOCALAPPDATA||f.join(t,"AppData","Local"),"Dezycro","metrics");case"darwin":return f.join(t,"Library","Application Support","Dezycro","metrics");default:return f.join(process.env.XDG_STATE_HOME||f.join(t,".local","state"),"dezycro","metrics")}}record(e){if(this.file)try{A.appendFileSync(this.file,`${JSON.stringify({ts:new Date().toISOString(),...e})}
27
- `)}catch{}}static prepare(e){if(!r.enabled())return null;try{let t=r.dir();return A.mkdirSync(t,{recursive:!0}),f.join(t,`${e}.jsonl`)}catch{return null}}};var ye={rules:[{nameIncludes:Z.UpdateTask,inputField:G.Status,inputValues:[B.Done,B.Pushed],requireAll:[m.SpecPublished,m.VerifiedRecently],reason:"Cannot mark a task DONE/PUSHED yet."}]},j=class r{constructor(e,t){this.policy=e;this.state=t}policy;state;static STATE_PREDICATES={[m.SpecPublished]:e=>!!e&&e.needsSpecPublish!==!0,[m.VerifiedRecently]:e=>!e||!e.lastVerifyCompletionTs?!1:e.lastEditTs?Date.parse(e.lastVerifyCompletionTs)>=Date.parse(e.lastEditTs):!0};static FAILED_HINT={[m.SpecPublished]:"spec not published (controller/API changed) \u2014 run /dezycro:publish-spec",[m.VerifiedRecently]:"no passing verify since last edit \u2014 run /dezycro:verify"};decide(e,t){for(let n of this.policy?.rules??[]){if(!e||!e.includes(n.nameIncludes))continue;if(n.inputField){let c=t?.[n.inputField],l=(n.inputValues??[]).map(y=>String(y).toUpperCase());if(c==null||!l.includes(String(c).toUpperCase()))continue}let o=n.requireAll??[];if(o.length===0)return this.blocked(e,n.reason);let s=o.filter(c=>!r.STATE_PREDICATES[c]?.(this.state));if(s.length===0)continue;let i=s.map(c=>r.FAILED_HINT[c]||c).join("; ");return this.blocked(e,`${n.reason||"Blocked by Dezycro policy."} ${i}.`)}return null}blocked(e,t){return{toolName:e||"?",detail:t||"Blocked by Dezycro policy."}}};var Je=new Set([d.ContentBlockStart,d.ContentBlockDelta,d.ContentBlockStop]);var oe=a(require("node:fs")),se=a(require("node:path"));var k=class r{static BIG_TOOL_CHARS=4e3;static defaultFile(){return se.join(g.dir(),"gateway.jsonl")}static fromFile(e=r.defaultFile()){let t;try{t=oe.readFileSync(e,"utf8")}catch{return r.empty()}return r.aggregate(t.split(`
28
- `))}static aggregate(e){let t=r.empty();for(let n of e){let o=r.parse(n);o&&(o.type==="turn"?r.addTurn(t,o):o.type==="compaction"&&r.addCompaction(t,o),r.trackTime(t,o.ts))}return t}static addTurn(e,t){e.turns+=1,e.inputTokens+=r.num(t.inputTokens),e.outputTokens+=r.num(t.outputTokens),e.cacheReadTokens+=r.num(t.cacheReadTokens),e.cacheCreationTokens+=r.num(t.cacheCreationTokens),e.totalDurationMs+=r.num(t.durationMs),e.gateBlocks+=r.num(t.blockedToolCalls);let n=r.num(t.freshToolChars);if(e.maxFreshToolChars=Math.max(e.maxFreshToolChars,n),n>r.BIG_TOOL_CHARS&&(e.bigToolTurns+=1),e.maxToolDefChars=Math.max(e.maxToolDefChars,r.num(t.toolDefChars)),e.maxSystemChars=Math.max(e.maxSystemChars,r.num(t.systemChars)),e.tailResultChars+=r.num(t.tailResultChars),e.tailTextChars+=r.num(t.tailTextChars),e.maxCacheCreationTokens=Math.max(e.maxCacheCreationTokens,r.num(t.cacheCreationTokens)),typeof t.status=="number"&&t.status!==200&&(e.errorTurns+=1),r.bump(e.models,typeof t.model=="string"?t.model:"(unknown)"),Array.isArray(t.skillsTriggered))for(let o of t.skillsTriggered)r.bump(e.skillsTriggered,String(o))}static addCompaction(e,t){e.compactions+=1,e.charsSaved+=r.num(t.charsSaved),e.estTokensSaved+=r.num(t.estTokensSaved),e.linesElided+=r.num(t.elidedLines),r.bump(e.commands,typeof t.command=="string"?t.command:"(unknown)")}static trackTime(e,t){typeof t=="string"&&((!e.firstTs||t<e.firstTs)&&(e.firstTs=t),(!e.lastTs||t>e.lastTs)&&(e.lastTs=t))}static parse(e){if(!e.trim())return null;try{return JSON.parse(e)}catch{return null}}static bump(e,t){e[t]=(e[t]??0)+1}static num(e){return typeof e=="number"&&Number.isFinite(e)?e:0}static empty(){return{turns:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,totalDurationMs:0,errorTurns:0,gateBlocks:0,maxFreshToolChars:0,bigToolTurns:0,maxToolDefChars:0,maxSystemChars:0,tailResultChars:0,tailTextChars:0,maxCacheCreationTokens:0,models:{},skillsTriggered:{},compactions:0,charsSaved:0,estTokensSaved:0,linesElided:0,commands:{},firstTs:null,lastTs:null}}};var p=a(require("node:fs")),ie=a(require("node:path")),C=class r{apiUrl;workspaceId;token;metricsFile;cursorFile;batchSize;timeoutMs;fetchImpl;constructor(e){this.apiUrl=e.apiUrl,this.workspaceId=e.workspaceId,this.token=e.token,this.metricsFile=e.metricsFile,this.cursorFile=e.cursorFile,this.batchSize=e.batchSize??1e3,this.timeoutMs=e.timeoutMs??15e3,this.fetchImpl=e.fetchImpl??fetch}async upload({dryRun:e=!1}={}){let{lines:t,newOffset:n}=this.readNewLines(),o=r.toBatch(t),s=o.turns.length+o.compactions.length,i={turns:o.turns.length,compactions:o.compactions.length,newOffset:n,sent:!1,dryRun:e};return e?i:s===0?(n!==this.readCursor()&&this.writeCursor(n),i):(await this.postAll(o),this.writeCursor(n),{...i,sent:!0})}static toBatch(e){let t=[],n=[];for(let o of e){let s;try{s=JSON.parse(o)}catch{continue}typeof s.ts=="string"&&(s.type==="turn"?t.push(r.mapTurn(s)):s.type==="compaction"&&n.push(r.mapCompaction(s)))}return{turns:t,compactions:n}}static mapTurn(e){return{timestamp:e.ts,provider:e.provider??null,model:e.model??null,status:e.status??null,durationMs:e.durationMs??null,inputTokens:e.inputTokens??null,outputTokens:e.outputTokens??null,cacheReadTokens:e.cacheReadTokens??null,cacheCreationTokens:e.cacheCreationTokens??null,toolDefChars:e.toolDefChars??null,systemChars:e.systemChars??null,freshToolChars:e.freshToolChars??null,tailResultChars:e.tailResultChars??null,tailTextChars:e.tailTextChars??null,blockedToolCalls:e.blockedToolCalls??null,skillsFired:Array.isArray(e.skillsTriggered)?e.skillsTriggered:[]}}static mapCompaction(e){return{timestamp:e.ts,command:e.command??null,originalChars:e.originalChars??null,outputChars:e.outputChars??null,charsSaved:e.charsSaved??null,estTokensSaved:e.estTokensSaved??null,originalLines:e.originalLines??null,outputLines:e.outputLines??null,elidedLines:e.elidedLines??null}}readNewLines(){let e=this.readCursor(),t;try{t=p.statSync(this.metricsFile).size}catch{return{lines:[],newOffset:e}}if(e>t&&(e=0),e===t)return{lines:[],newOffset:e};let n=p.openSync(this.metricsFile,"r");try{let o=t-e,s=Buffer.alloc(o);p.readSync(n,s,0,o,e);let i=s.toString("utf8"),c=i.lastIndexOf(`
29
- `);if(c<0)return{lines:[],newOffset:e};let l=i.slice(0,c+1),y=e+Buffer.byteLength(l,"utf8");return{lines:l.split(`
30
- `).filter(T=>T.trim().length>0),newOffset:y}}finally{p.closeSync(n)}}readCursor(){try{let e=JSON.parse(p.readFileSync(this.cursorFile,"utf8"));return typeof e.offset=="number"&&e.offset>=0?e.offset:0}catch{return 0}}writeCursor(e){try{p.mkdirSync(ie.dirname(this.cursorFile),{recursive:!0}),p.writeFileSync(this.cursorFile,JSON.stringify({offset:e,uploadedAt:new Date().toISOString()}))}catch{}}async postAll(e){for(let t=0;t<e.turns.length;t+=this.batchSize)await this.postBatch({turns:e.turns.slice(t,t+this.batchSize),compactions:[]});for(let t=0;t<e.compactions.length;t+=this.batchSize)await this.postBatch({turns:[],compactions:e.compactions.slice(t,t+this.batchSize)})}async postBatch(e){let t=`${this.apiUrl}/api/v1/workspaces/${this.workspaceId}/usage-telemetry`,n=new AbortController,o=setTimeout(()=>n.abort(),this.timeoutMs);try{let s=await this.fetchImpl(t,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"content-type":"application/json",accept:"application/json"},body:JSON.stringify(e),signal:n.signal});if(!s.ok)throw new Error(`usage-telemetry upload returned ${s.status}`)}finally{clearTimeout(o)}}};var I=a(require("fs")),ae=a(require("os")),u=a(require("path")),P=class r{constructor(e){this.repoRoot=e;this.config=r.readJson(u.join(e,".dezycro","config.json"))}repoRoot;config;static at(e=process.cwd()){return new r(r.findRepoRoot(e)??u.resolve(e))}get workspaceId(){return r.env("DZ_WORKSPACE_ID")??r.str(this.config?.workspaceId)}get tenantId(){return r.env("DZ_TENANT_ID")??r.str(this.config?.tenantId)}get projectId(){return r.str(this.config?.projectId)}get apiUrl(){let e=r.env("DZ_API_URL");if(e)return r.trimSlash(e);let t=Array.isArray(this.config?.environments)?this.config?.environments:[],n=t.find(s=>r.isObj(s)&&s.default===!0)??t[0],o=r.isObj(n)?r.str(n.apiUrl):null;return o?r.trimSlash(o):null}get token(){let e=r.env("DZ_TOKEN");if(e)return e;let t=[u.join(this.repoRoot,".dezycro","companion-token.local.json"),u.join(ae.homedir(),".dezycro","token.json")];for(let n of t){let o=r.str(r.readJson(n)?.token);if(o)return o}return null}activeFeature(){let e=r.readJson(u.join(this.repoRoot,".dezycro","active-feature.json")),t=r.str(e?.featureId);if(!t)return null;let n=r.str(e?.workspaceId)??this.workspaceId;return n?{workspaceId:n,featureId:t}:null}connection(){let e=this.apiUrl;if(!e)return{error:"no apiUrl (set DZ_API_URL or .dezycro/config.json environments[].apiUrl)"};let t=this.workspaceId;if(!t)return{error:"no workspaceId (set DZ_WORKSPACE_ID or .dezycro/config.json workspaceId)"};let n=this.token;return n?{apiUrl:e,workspaceId:t,token:n}:{error:"no token (run `dezycro setup` or set DZ_TOKEN)"}}static findRepoRoot(e){let t=u.resolve(e||process.cwd());for(let n=0;n<64;n+=1){if(I.existsSync(u.join(t,".dezycro")))return t;let o=u.dirname(t);if(o===t)return null;t=o}return null}static readJson(e){try{return JSON.parse(I.readFileSync(e,"utf8"))}catch{return null}}static isObj(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}static str(e){return typeof e=="string"&&e.length>0?e:null}static env(e){let t=process.env[e];return t&&t.length>0?t:null}static trimSlash(e){return e.replace(/\/$/,"")}};var z=class r{run(e){if(e.includes("--upload-dry-run")){this.uploadDryRun();return}let t=k.defaultFile(),n=k.fromFile(t);if(e.includes("--json")){process.stdout.write(`${JSON.stringify(n,null,2)}
31
- `);return}process.stdout.write(r.format(n,t))}async uploadDryRun(){let e=l=>{process.stdout.write(`${l}
32
- `)},t=P.at(process.cwd()),n=t.connection(),o=k.defaultFile(),s=ce.join(g.dir(),"gateway.upload-cursor.json"),i="error"in n?{apiUrl:"(unset)",workspaceId:t.workspaceId??"(unset)",token:"(unset)"}:n,c=await new C({...i,metricsFile:o,cursorFile:s}).upload({dryRun:!0});e("Dezycro telemetry \u2014 dry run (nothing sent)"),e(` metrics file ${o}`),e(` target ${i.apiUrl}/api/v1/workspaces/${i.workspaceId}/usage-telemetry`),"error"in n&&e(` connection NOT configured \u2014 ${n.error}`),e(` pending upload ${c.turns} turn + ${c.compactions} compaction event(s) since the cursor`)}static format(e,t){if(e.turns===0&&e.compactions===0)return`No metrics yet at ${t}
26
+ `)}};var ge=l(require("node:path"));var P=l(require("node:fs")),le=l(require("node:os")),f=l(require("node:path")),Ee="DZ_METRICS_DIR",Re="DZ_METRICS",g=class o{file;constructor(e="gateway"){this.file=o.prepare(e)}static enabled(){return process.env[Re]!=="0"}static dir(){let e=process.env[Ee];if(e)return e;let t=le.homedir();switch(process.platform){case"win32":return f.join(process.env.LOCALAPPDATA||f.join(t,"AppData","Local"),"Dezycro","metrics");case"darwin":return f.join(t,"Library","Application Support","Dezycro","metrics");default:return f.join(process.env.XDG_STATE_HOME||f.join(t,".local","state"),"dezycro","metrics")}}record(e){if(this.file)try{P.appendFileSync(this.file,`${JSON.stringify({ts:new Date().toISOString(),...e})}
27
+ `)}catch{}}static prepare(e){if(!o.enabled())return null;try{let t=o.dir();return P.mkdirSync(t,{recursive:!0}),f.join(t,`${e}.jsonl`)}catch{return null}}};var Ie={rules:[{nameIncludes:Q.UpdateTask,inputField:ee.Status,inputValues:[_.Done,_.Pushed],requireAll:[m.SpecPublished,m.VerifiedRecently],reason:"Cannot mark a task DONE/PUSHED yet."}]},H=class o{constructor(e,t){this.policy=e;this.state=t}policy;state;static STATE_PREDICATES={[m.SpecPublished]:e=>!!e&&e.needsSpecPublish!==!0,[m.VerifiedRecently]:e=>!e||!e.lastVerifyCompletionTs?!1:e.lastEditTs?Date.parse(e.lastVerifyCompletionTs)>=Date.parse(e.lastEditTs):!0};static FAILED_HINT={[m.SpecPublished]:"spec not published (controller/API changed) \u2014 run /dezycro:publish-spec",[m.VerifiedRecently]:"no passing verify since last edit \u2014 run /dezycro:verify"};decide(e,t){for(let n of this.policy?.rules??[]){if(!e||!e.includes(n.nameIncludes))continue;if(n.inputField){let a=t?.[n.inputField],c=(n.inputValues??[]).map(k=>String(k).toUpperCase());if(a==null||!c.includes(String(a).toUpperCase()))continue}let r=n.requireAll??[];if(r.length===0)return this.blocked(e,n.reason);let i=r.filter(a=>!o.STATE_PREDICATES[a]?.(this.state));if(i.length===0)continue;let s=i.map(a=>o.FAILED_HINT[a]||a).join("; ");return this.blocked(e,`${n.reason||"Blocked by Dezycro policy."} ${s}.`)}return null}blocked(e,t){return{toolName:e||"?",detail:t||"Blocked by Dezycro policy."}}};var tt=new Set([d.ContentBlockStart,d.ContentBlockDelta,d.ContentBlockStop]);var de=l(require("node:fs")),me=l(require("node:path"));var y=class o{static BIG_TOOL_CHARS=4e3;static defaultFile(){return me.join(g.dir(),"gateway.jsonl")}static fromFile(e=o.defaultFile()){let t;try{t=de.readFileSync(e,"utf8")}catch{return o.empty()}return o.aggregate(t.split(`
28
+ `))}static aggregate(e){let t=o.empty();for(let n of e){let r=o.parse(n);r&&(r.type==="turn"?o.addTurn(t,r):r.type==="compaction"&&o.addCompaction(t,r),o.trackTime(t,r.ts))}return t}static addTurn(e,t){e.turns+=1,e.inputTokens+=o.num(t.inputTokens),e.outputTokens+=o.num(t.outputTokens),e.cacheReadTokens+=o.num(t.cacheReadTokens),e.cacheCreationTokens+=o.num(t.cacheCreationTokens),e.totalDurationMs+=o.num(t.durationMs),e.gateBlocks+=o.num(t.blockedToolCalls);let n=o.num(t.freshToolChars);if(e.maxFreshToolChars=Math.max(e.maxFreshToolChars,n),n>o.BIG_TOOL_CHARS&&(e.bigToolTurns+=1),e.maxToolDefChars=Math.max(e.maxToolDefChars,o.num(t.toolDefChars)),e.maxSystemChars=Math.max(e.maxSystemChars,o.num(t.systemChars)),e.tailResultChars+=o.num(t.tailResultChars),e.tailTextChars+=o.num(t.tailTextChars),e.maxCacheCreationTokens=Math.max(e.maxCacheCreationTokens,o.num(t.cacheCreationTokens)),typeof t.status=="number"&&t.status!==200&&(e.errorTurns+=1),o.bump(e.models,typeof t.model=="string"?t.model:"(unknown)"),Array.isArray(t.skillsTriggered))for(let r of t.skillsTriggered)o.bump(e.skillsTriggered,String(r))}static addCompaction(e,t){e.compactions+=1,e.charsSaved+=o.num(t.charsSaved),e.estTokensSaved+=o.num(t.estTokensSaved),e.linesElided+=o.num(t.elidedLines),o.bump(e.commands,typeof t.command=="string"?t.command:"(unknown)")}static trackTime(e,t){typeof t=="string"&&((!e.firstTs||t<e.firstTs)&&(e.firstTs=t),(!e.lastTs||t>e.lastTs)&&(e.lastTs=t))}static parse(e){if(!e.trim())return null;try{return JSON.parse(e)}catch{return null}}static bump(e,t){e[t]=(e[t]??0)+1}static num(e){return typeof e=="number"&&Number.isFinite(e)?e:0}static empty(){return{turns:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,totalDurationMs:0,errorTurns:0,gateBlocks:0,maxFreshToolChars:0,bigToolTurns:0,maxToolDefChars:0,maxSystemChars:0,tailResultChars:0,tailTextChars:0,maxCacheCreationTokens:0,models:{},skillsTriggered:{},compactions:0,charsSaved:0,estTokensSaved:0,linesElided:0,commands:{},firstTs:null,lastTs:null}}};var u=l(require("node:fs")),he=l(require("node:path")),x=class o{apiUrl;workspaceId;token;metricsFile;cursorFile;batchSize;timeoutMs;fetchImpl;constructor(e){this.apiUrl=e.apiUrl,this.workspaceId=e.workspaceId,this.token=e.token,this.metricsFile=e.metricsFile,this.cursorFile=e.cursorFile,this.batchSize=e.batchSize??1e3,this.timeoutMs=e.timeoutMs??15e3,this.fetchImpl=e.fetchImpl??fetch}async upload({dryRun:e=!1}={}){let{lines:t,newOffset:n}=this.readNewLines(),r=o.toBatch(t),i=r.turns.length+r.compactions.length,s={turns:r.turns.length,compactions:r.compactions.length,newOffset:n,sent:!1,dryRun:e};return e?s:i===0?(n!==this.readCursor()&&this.writeCursor(n),s):(await this.postAll(r),this.writeCursor(n),{...s,sent:!0})}static toBatch(e){let t=[],n=[];for(let r of e){let i;try{i=JSON.parse(r)}catch{continue}typeof i.ts=="string"&&(i.type==="turn"?t.push(o.mapTurn(i)):i.type==="compaction"&&n.push(o.mapCompaction(i)))}return{turns:t,compactions:n}}static mapTurn(e){return{timestamp:e.ts,provider:e.provider??null,model:e.model??null,status:e.status??null,durationMs:e.durationMs??null,inputTokens:e.inputTokens??null,outputTokens:e.outputTokens??null,cacheReadTokens:e.cacheReadTokens??null,cacheCreationTokens:e.cacheCreationTokens??null,toolDefChars:e.toolDefChars??null,systemChars:e.systemChars??null,freshToolChars:e.freshToolChars??null,tailResultChars:e.tailResultChars??null,tailTextChars:e.tailTextChars??null,blockedToolCalls:e.blockedToolCalls??null,skillsFired:Array.isArray(e.skillsTriggered)?e.skillsTriggered:[]}}static mapCompaction(e){return{timestamp:e.ts,command:e.command??null,originalChars:e.originalChars??null,outputChars:e.outputChars??null,charsSaved:e.charsSaved??null,estTokensSaved:e.estTokensSaved??null,originalLines:e.originalLines??null,outputLines:e.outputLines??null,elidedLines:e.elidedLines??null}}readNewLines(){let e=this.readCursor(),t;try{t=u.statSync(this.metricsFile).size}catch{return{lines:[],newOffset:e}}if(e>t&&(e=0),e===t)return{lines:[],newOffset:e};let n=u.openSync(this.metricsFile,"r");try{let r=t-e,i=Buffer.alloc(r);u.readSync(n,i,0,r,e);let s=i.toString("utf8"),a=s.lastIndexOf(`
29
+ `);if(a<0)return{lines:[],newOffset:e};let c=s.slice(0,a+1),k=e+Buffer.byteLength(c,"utf8");return{lines:c.split(`
30
+ `).filter(T=>T.trim().length>0),newOffset:k}}finally{u.closeSync(n)}}readCursor(){try{let e=JSON.parse(u.readFileSync(this.cursorFile,"utf8"));return typeof e.offset=="number"&&e.offset>=0?e.offset:0}catch{return 0}}writeCursor(e){try{u.mkdirSync(he.dirname(this.cursorFile),{recursive:!0}),u.writeFileSync(this.cursorFile,JSON.stringify({offset:e,uploadedAt:new Date().toISOString()}))}catch{}}async postAll(e){for(let t=0;t<e.turns.length;t+=this.batchSize)await this.postBatch({turns:e.turns.slice(t,t+this.batchSize),compactions:[]});for(let t=0;t<e.compactions.length;t+=this.batchSize)await this.postBatch({turns:[],compactions:e.compactions.slice(t,t+this.batchSize)})}async postBatch(e){let t=`${this.apiUrl}/api/v1/workspaces/${this.workspaceId}/usage-telemetry`,n=new AbortController,r=setTimeout(()=>n.abort(),this.timeoutMs);try{let i=await this.fetchImpl(t,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"content-type":"application/json",accept:"application/json"},body:JSON.stringify(e),signal:n.signal});if(!i.ok)throw new Error(`usage-telemetry upload returned ${i.status}`)}finally{clearTimeout(r)}}};var M=l(require("fs")),fe=l(require("os")),p=l(require("path")),v=class o{constructor(e){this.repoRoot=e;this.config=o.readJson(p.join(e,".dezycro","config.json"))}repoRoot;config;static at(e=process.cwd()){return new o(o.findRepoRoot(e)??p.resolve(e))}get workspaceId(){return o.env("DZ_WORKSPACE_ID")??o.str(this.config?.workspaceId)}get tenantId(){return o.env("DZ_TENANT_ID")??o.str(this.config?.tenantId)}get projectId(){return o.str(this.config?.projectId)}get apiUrl(){let e=o.env("DZ_API_URL");if(e)return o.trimSlash(e);let t=Array.isArray(this.config?.environments)?this.config?.environments:[],n=t.find(i=>o.isObj(i)&&i.default===!0)??t[0],r=o.isObj(n)?o.str(n.apiUrl):null;return r?o.trimSlash(r):null}get token(){let e=o.env("DZ_TOKEN");if(e)return e;let t=[p.join(this.repoRoot,".dezycro","companion-token.local.json"),p.join(fe.homedir(),".dezycro","token.json")];for(let n of t){let r=o.str(o.readJson(n)?.token);if(r)return r}return null}activeFeature(){let e=o.readJson(p.join(this.repoRoot,".dezycro","active-feature.json")),t=o.str(e?.featureId);if(!t)return null;let n=o.str(e?.workspaceId)??this.workspaceId;return n?{workspaceId:n,featureId:t}:null}connection(){let e=this.apiUrl;if(!e)return{error:"no apiUrl (set DZ_API_URL or .dezycro/config.json environments[].apiUrl)"};let t=this.workspaceId;if(!t)return{error:"no workspaceId (set DZ_WORKSPACE_ID or .dezycro/config.json workspaceId)"};let n=this.token;return n?{apiUrl:e,workspaceId:t,token:n}:{error:"no token (run `dezycro setup` or set DZ_TOKEN)"}}static findRepoRoot(e){let t=p.resolve(e||process.cwd());for(let n=0;n<64;n+=1){if(M.existsSync(p.join(t,".dezycro")))return t;let r=p.dirname(t);if(r===t)return null;t=r}return null}static readJson(e){try{return JSON.parse(M.readFileSync(e,"utf8"))}catch{return null}}static isObj(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}static str(e){return typeof e=="string"&&e.length>0?e:null}static env(e){let t=process.env[e];return t&&t.length>0?t:null}static trimSlash(e){return e.replace(/\/$/,"")}};var z=class o{run(e){if(e.includes("--upload-dry-run")){this.uploadDryRun();return}let t=y.defaultFile(),n=y.fromFile(t);if(e.includes("--json")){process.stdout.write(`${JSON.stringify(n,null,2)}
31
+ `);return}process.stdout.write(o.format(n,t))}async uploadDryRun(){let e=c=>{process.stdout.write(`${c}
32
+ `)},t=v.at(process.cwd()),n=t.connection(),r=y.defaultFile(),i=ge.join(g.dir(),"gateway.upload-cursor.json"),s="error"in n?{apiUrl:"(unset)",workspaceId:t.workspaceId??"(unset)",token:"(unset)"}:n,a=await new x({...s,metricsFile:r,cursorFile:i}).upload({dryRun:!0});e("Dezycro telemetry \u2014 dry run (nothing sent)"),e(` metrics file ${r}`),e(` target ${s.apiUrl}/api/v1/workspaces/${s.workspaceId}/usage-telemetry`),"error"in n&&e(` connection NOT configured \u2014 ${n.error}`),e(` pending upload ${a.turns} turn + ${a.compactions} compaction event(s) since the cursor`)}static format(e,t){if(e.turns===0&&e.compactions===0)return`No metrics yet at ${t}
33
33
  (They're written as you run agents through \`dezycro run\`. DZ_METRICS=0 disables.)
34
- `;let n=l=>l.toLocaleString("en-US"),o=l=>n(Math.round(l/4)),s=l=>e.turns>0?n(Math.round(l/e.turns)):"0",i=[];i.push("Dezycro gateway metrics"),i.push(` ${t}`),e.firstTs&&e.lastTs&&i.push(` ${e.firstTs} \u2192 ${e.lastTs}`),i.push(""),i.push(`Turns: ${n(e.turns)} errors: ${n(e.errorTurns)} model time: ${(e.totalDurationMs/1e3).toFixed(0)}s`);let c=[`fresh input ~${s(e.inputTokens)} tok/turn`,`output ~${s(e.outputTokens)} tok/turn`];if(e.cacheReadTokens+e.inputTokens>0){let l=100*e.cacheReadTokens/(e.cacheReadTokens+e.inputTokens);c.push(`cache hit ${l.toFixed(1)}%`)}return i.push(c.join(" \xB7 ")),i.push(""),i.push("Where the tokens are (per request \u2014 content-free)"),i.push(` tool definitions ${n(e.maxToolDefChars)} chars (~${o(e.maxToolDefChars)} tok) \u2190 fixed per-request cost; schema-bloat lever`),i.push(` system prompt ${n(e.maxSystemChars)} chars (~${o(e.maxSystemChars)} tok)`),i.push(` fresh tool results ${n(e.tailResultChars)} chars (~${o(e.tailResultChars)} tok) total \xB7 biggest single ${n(e.maxFreshToolChars)} chars (~${o(e.maxFreshToolChars)} tok)`),i.push(` fresh user text ${n(e.tailTextChars)} chars (~${o(e.tailTextChars)} tok) total`),i.push(""),i.push("Cache"),i.push(` read ${n(e.cacheReadTokens)} tok \xB7 create ${n(e.cacheCreationTokens)} tok`),e.maxCacheCreationTokens>0&&i.push(` largest prefix write ${n(e.maxCacheCreationTokens)} tok (a spike here = cache-bust \u2014 the costly case)`),i.push(""),i.push("Request-side compaction opportunity (not yet compacted)"),i.push(` turns with >1k-tok fresh tool output ${n(e.bigToolTurns)}`),i.push(" (fresh tool results are the safe headroom; reversible elision is the lever \u2014 needs sizing first)"),i.push(""),i.push("Source-side compaction (shell output \u2014 already applied)"),i.push(` est. tokens saved ${n(e.estTokensSaved)} over ${n(e.compactions)} compaction(s)${r.breakdown(e.commands)}`),i.push(` lines elided ${n(e.linesElided)}`),i.push(""),i.push(`Totals: input ${n(e.inputTokens)} \xB7 output ${n(e.outputTokens)} \xB7 cache read ${n(e.cacheReadTokens)} \xB7 cache create ${n(e.cacheCreationTokens)}`),i.push(`Gate blocks: ${n(e.gateBlocks)}`),i.push(`Skills fired:${r.breakdown(e.skillsTriggered)||" none"}`),i.push(`Models:${r.breakdown(e.models)||" (none)"}`),i.push(""),`${i.join(`
34
+ `;let n=c=>c.toLocaleString("en-US"),r=c=>n(Math.round(c/4)),i=c=>e.turns>0?n(Math.round(c/e.turns)):"0",s=[];s.push("Dezycro gateway metrics"),s.push(` ${t}`),e.firstTs&&e.lastTs&&s.push(` ${e.firstTs} \u2192 ${e.lastTs}`),s.push(""),s.push(`Turns: ${n(e.turns)} errors: ${n(e.errorTurns)} model time: ${(e.totalDurationMs/1e3).toFixed(0)}s`);let a=[`fresh input ~${i(e.inputTokens)} tok/turn`,`output ~${i(e.outputTokens)} tok/turn`];if(e.cacheReadTokens+e.inputTokens>0){let c=100*e.cacheReadTokens/(e.cacheReadTokens+e.inputTokens);a.push(`cache hit ${c.toFixed(1)}%`)}return s.push(a.join(" \xB7 ")),s.push(""),s.push("Where the tokens are (per request \u2014 content-free)"),s.push(` tool definitions ${n(e.maxToolDefChars)} chars (~${r(e.maxToolDefChars)} tok) \u2190 fixed per-request cost; schema-bloat lever`),s.push(` system prompt ${n(e.maxSystemChars)} chars (~${r(e.maxSystemChars)} tok)`),s.push(` fresh tool results ${n(e.tailResultChars)} chars (~${r(e.tailResultChars)} tok) total \xB7 biggest single ${n(e.maxFreshToolChars)} chars (~${r(e.maxFreshToolChars)} tok)`),s.push(` fresh user text ${n(e.tailTextChars)} chars (~${r(e.tailTextChars)} tok) total`),s.push(""),s.push("Cache"),s.push(` read ${n(e.cacheReadTokens)} tok \xB7 create ${n(e.cacheCreationTokens)} tok`),e.maxCacheCreationTokens>0&&s.push(` largest prefix write ${n(e.maxCacheCreationTokens)} tok (a spike here = cache-bust \u2014 the costly case)`),s.push(""),s.push("Request-side compaction opportunity (not yet compacted)"),s.push(` turns with >1k-tok fresh tool output ${n(e.bigToolTurns)}`),s.push(" (fresh tool results are the safe headroom; reversible elision is the lever \u2014 needs sizing first)"),s.push(""),s.push("Source-side compaction (shell output \u2014 already applied)"),s.push(` est. tokens saved ${n(e.estTokensSaved)} over ${n(e.compactions)} compaction(s)${o.breakdown(e.commands)}`),s.push(` lines elided ${n(e.linesElided)}`),s.push(""),s.push(`Totals: input ${n(e.inputTokens)} \xB7 output ${n(e.outputTokens)} \xB7 cache read ${n(e.cacheReadTokens)} \xB7 cache create ${n(e.cacheCreationTokens)}`),s.push(`Gate blocks: ${n(e.gateBlocks)}`),s.push(`Skills fired:${o.breakdown(e.skillsTriggered)||" none"}`),s.push(`Models:${o.breakdown(e.models)||" (none)"}`),s.push(""),`${s.join(`
35
35
  `)}
36
- `}static breakdown(e){let t=Object.entries(e).sort((n,o)=>o[1]-n[1]);return t.length===0?"":` ${t.map(([n,o])=>`${n}=${o}`).join(", ")}`}};var le=`dezycro \u2014 Dezycro for AI coding agents
36
+ `}static breakdown(e){let t=Object.entries(e).sort((n,r)=>r[1]-n[1]);return t.length===0?"":` ${t.map(([n,r])=>`${n}=${r}`).join(", ")}`}};var Z=class{now(){return Date.now()}nowIso(){return new Date().toISOString()}sleep(e){return new Promise(t=>setTimeout(t,e))}},G=class{constructor(e,t,n,r,i){this.apiUrl=e;this.workspaceId=t;this.featureId=n;this.token=r;this.eventTypes=i}apiUrl;workspaceId;featureId;token;eventTypes;async wait(e,t){let n=new URL(`${this.apiUrl}/api/v1/workspaces/${this.workspaceId}/features/${this.featureId}/inbox/wait`);this.eventTypes&&n.searchParams.set("eventTypes",this.eventTypes),n.searchParams.set("since",e),n.searchParams.set("timeoutSec",String(t));let r=new AbortController,i=setTimeout(()=>r.abort(),(t+10)*1e3);try{let s=await fetch(n.toString(),{method:"GET",headers:{Authorization:`Bearer ${this.token}`,Accept:"application/json"},signal:r.signal});if(!s.ok)throw new Error(`inbox/wait returned ${s.status}`);let a=await s.json();return{nextCursor:typeof a.nextCursor=="string"?a.nextCursor:e,events:Array.isArray(a.events)?a.events:[]}}finally{clearTimeout(i)}}},O=class{constructor(e,t=30,n=1e3){this.totalTimeoutSec=e;this.perPollSec=t;this.errorBackoffMs=n}totalTimeoutSec;perPollSec;errorBackoffMs;static DEFAULT_TOTAL_TIMEOUT_SEC=600},V=class{constructor(e,t,n){this.gateway=e;this.clock=t;this.policy=n}gateway;clock;policy;async awaitEvent(){let e=this.clock.now()+this.policy.totalTimeoutSec*1e3,t=this.clock.nowIso(),n=!1,r="";for(;this.clock.now()<e;){let i=Math.ceil((e-this.clock.now())/1e3);if(i<=0)break;let s=Math.min(this.policy.perPollSec,i);try{let a=await this.gateway.wait(t,s);n=!0;let[c]=a.events;if(c)return{outcome:"EVENT",event:c};t=a.nextCursor||t}catch(a){r=a instanceof Error?a.message:String(a),this.clock.now()<e&&await this.clock.sleep(this.policy.errorBackoffMs)}}return n?{outcome:"TIMEOUT"}:{outcome:"ERROR",error:r||"event wait failed"}}},q=class{constructor(e,t,n){this.result=e;this.eventTypes=t;this.timeoutSec=n}result;eventTypes;timeoutSec;render(){switch(this.result.outcome){case"EVENT":return JSON.stringify(this.result.event);case"TIMEOUT":return`TIMEOUT: no ${this.eventTypes??"any"} event within ${this.timeoutSec}s.`;case"ERROR":return`ERROR: ${this.result.error??"unknown"}`}}exitCode(){switch(this.result.outcome){case"EVENT":return 0;case"TIMEOUT":return 5;case"ERROR":return 2}}},Y=class o{constructor(e,t,n,r){this.eventTypes=e;this.feature=t;this.timeoutSec=n;this.json=r}eventTypes;feature;timeoutSec;json;static fromArgv(e){let t=null,n=null,r=O.DEFAULT_TOTAL_TIMEOUT_SEC,i=!1;for(let s=0;s<e.length;s+=1){let a=e[s];if(a==="--event-types")t=e[s+1]??null,s+=1;else if(a==="--feature")n=e[s+1]??null,s+=1;else if(a==="--timeout"){let c=Number(e[s+1]);Number.isFinite(c)&&c>0&&(r=c),s+=1}else a==="--json"&&(i=!0)}return new o(t,n,r,i)}},U=class{constructor(e=new Z){this.clock=e}clock;async run(e){let t=Y.fromArgv(e),n=v.at(process.cwd()),r=n.connection();if("error"in r){this.fail(`not configured \u2014 ${r.error}`);return}let i=t.feature??n.activeFeature()?.featureId??null;if(!i){this.fail("no feature (pass --feature <id>, or run /dezycro:work to bind one)");return}let s=new G(r.apiUrl,r.workspaceId,i,r.token,t.eventTypes),a=await new V(s,this.clock,new O(t.timeoutSec)).awaitEvent(),c=new q(a,t.eventTypes,t.timeoutSec);process.stdout.write(`${t.json?JSON.stringify(a):c.render()}
37
+ `),process.exit(c.exitCode())}fail(e){process.stderr.write(`dezycro await-event: ${e}
38
+ `),process.exit(2)}};var ke=(s=>(s.Run="run",s.Setup="setup",s.ResolveAuth="resolve-auth",s.Completion="completion",s.Metrics="metrics",s.AwaitEvent="await-event",s))(ke||{}),Pe=new Set(["help","-h","--help"]),ye=`dezycro \u2014 Dezycro for AI coding agents
37
39
 
38
40
  Usage: dezycro <command> [args]
39
41
 
@@ -44,7 +46,9 @@ Commands:
44
46
  completion <bash|zsh|fish> Print a shell-completion script (e.g. eval "$(dezycro completion zsh)")
45
47
  metrics [--json] Summarize local usage metrics (tokens used + saved, skills, models)
46
48
  metrics --upload-dry-run Preview the content-free telemetry the daemon would upload (sends nothing)
49
+ await-event --event-types <csv> [--feature <id>] [--timeout <sec>] [--json]
50
+ Block until the command bus pushes a matching event; prints it and exits (0 event / 5 timeout / 2 error)
47
51
 
48
52
  Gateway control: dezycro run --status dezycro run --stop
49
- Custom port: dezycro run --port <n> <agent> (overrides DZ_PORT, default 13579)`,J=class{run(e){let[t,...n]=e;switch(t){case"run":new x().run(n);return;case"setup":new R().run();return;case"resolve-auth":new D().run(n[0]);return;case"completion":new $().run(n);return;case"metrics":new z().run(n);return;case void 0:case"help":case"-h":case"--help":console.log(le);return;default:console.error(`dezycro: unknown command '${t}'
50
- `),console.error(le),process.exit(2)}}};new J().run(process.argv.slice(2));
53
+ Custom port: dezycro run --port <n> <agent> (overrides DZ_PORT, default 13579)`,K=class{handlers=new Map([["run",e=>{new R().run(e)}],["setup",()=>new I().run()],["resolve-auth",e=>new A().run(e[0])],["completion",e=>new $().run(e)],["metrics",e=>new z().run(e)],["await-event",e=>{new U().run(e)}]]);run(e){let[t,...n]=e,r=this.handlers.get(t);if(r){r(n);return}if(t===void 0||Pe.has(t)){console.log(ye);return}console.error(`dezycro: unknown command '${t}'
54
+ `),console.error(ye),process.exit(2)}};new K().run(process.argv.slice(2));0&&(module.exports={Command});
@@ -1,14 +1,14 @@
1
- "use strict";var re=Object.create;var M=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty;var ue=(e,t)=>{for(var n in t)M(e,n,{get:t[n],enumerable:!0})},ot=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ie(t))!ce.call(e,r)&&r!==n&&M(e,r,{get:()=>t[r],enumerable:!(o=se(t,r))||o.enumerable});return e};var T=(e,t,n)=>(n=e!=null?re(ae(e)):{},ot(t||!e||!e.__esModule?M(n,"default",{value:e,enumerable:!0}):n,e)),le=e=>ot(M({},"__esModule",{value:!0}),e);var Cn={};ue(Cn,{QUALITY_GATE_REASON_PREFIX:()=>qt,TRIVIAL_TURN_CHAR_DEFAULT_EXPORT:()=>In,_extractEditedPaths:()=>mn,_handlePostEdit:()=>hn,_handleSessionStart:()=>bn,_handleStop:()=>Sn,_handleUpdateTaskGate:()=>yn,_handleUserPromptSubmit:()=>Tn,_handleWorkbookMutation:()=>kn,_readActiveFeatureId:()=>wn,_transcriptCharsSinceLastStop:()=>vn,dispatch:()=>rn});module.exports=le(Cn);var N=T(require("fs")),Wt=T(require("path"));var U=T(require("fs")),E=T(require("path")),rt=Object.freeze({conservative:{decision:.85,issue:.8,assumption:.9,taskStatus:.9},balanced:{decision:.75,issue:.7,assumption:.8,taskStatus:.85},aggressive:{decision:.6,issue:.55,assumption:.7,taskStatus:.75}}),R=Object.freeze({companion:{autoVerify:{preTaskDone:!0,prePush:!0,postEditPulse:{enabled:!0,threshold:5},autoPublishSpecOnControllerChange:!0,controllerPaths:["**/controllers/**/*.{kt,java,py,go,ts,tsx,js,rs,rb,cs}","**/api/**/*.{kt,java,py,go,ts,tsx,js,rs,rb,cs}"],verifyTimeoutSeconds:300,publishSpecTimeoutSeconds:300},autoWorkbookUpdates:{enabled:!0,preset:"conservative",maxAutoLogsPerTurn:2,maxAutoLogsPerSession:10,undoWindow:"next-turn",thresholds:{decision:null,issue:null,assumption:null,taskStatus:null},trivialTurnCharCutoff:600,hashRingBufferSize:32},coverageNudges:{enabled:!0,staleBaselineDays:14,fetchMode:"async"},authoring:{defaultDepth:"adaptive",existingWorkScan:!0,qualityGate:{enabled:!0},minViableContextGate:{enabled:!0}},safeMode:!1}});function W(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function st(e,t){if(!W(t))return t===void 0?e:t;let n=Array.isArray(e)?[...e]:{...e};for(let o of Object.keys(t)){let r=n[o],s=t[o];W(r)&&W(s)?n[o]=st(r,s):n[o]=s}return n}function it(e){let t=E.join(e,".dezycro","config.json"),n;try{n=U.readFileSync(t,"utf8")}catch(r){if(r.code==="ENOENT")return JSON.parse(JSON.stringify(R));throw r}let o;try{o=JSON.parse(n)}catch{return JSON.parse(JSON.stringify(R))}return st(JSON.parse(JSON.stringify(R)),o)}function at(e){let t=e?.companion?.autoWorkbookUpdates||{},n=t.preset||"conservative",o=rt[n]||rt.conservative,r=t.thresholds||{};return{decision:typeof r.decision=="number"?r.decision:o.decision,issue:typeof r.issue=="number"?r.issue:o.issue,assumption:typeof r.assumption=="number"?r.assumption:o.assumption,taskStatus:typeof r.taskStatus=="number"?r.taskStatus:o.taskStatus}}function A(e){let t=E.resolve(e||process.cwd());for(let n=0;n<64;n+=1){if(U.existsSync(E.join(t,".dezycro")))return t;let o=E.dirname(t);if(o===t)return null;t=o}return null}var h=T(require("fs")),O=T(require("path")),pe=500,fe=10,q=32,ct=64,ut=Object.freeze({autoDecisionLogs:0,autoIssueLogs:0,autoAssumptionLogs:0,autoTaskStatusLogs:0,undoCount:0,verifyAutoRuns:0,verifyAutoFailures:0,qualityGateFailures:0,contextGateFailures:0,lockContention:0,forceApprovals:0}),ge=Object.freeze({schemaVersion:1,currentSessionId:null,authoringMode:!1,authoringDocId:null,authoringDocType:null,authoringTranscriptPath:null,authoringStartedTs:null,pulseCount:0,lastEditTs:null,needsSpecPublish:!1,controllerEditsSinceLastPublish:[],coverageSnapshot:null,coverageSnapshotTs:null,coverageFetchPending:!1,lastVerifyCompletionTs:null,recentDecisionHashes:[],recentIssueHashes:[],recentAssumptionHashes:[],lastAutoWorkbookMutation:null,sessionAutoLogCount:0,turnAutoLogCount:0,currentTurnId:0,suppressWorkbookUpdatesUntil:null,pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:null,commandBus:{cursor:null,lastPollTs:null,lastAttemptTs:null,consecutiveFailures:0,recentEventIds:[]},metrics:ut});function lt(e){return O.join(e,".dezycro","companion-state.json")}function dt(e){return O.join(e,".dezycro",".companion-state.lock")}function me(e){return O.join(e,".dezycro",".companion-state.json.tmp")}function he(e){h.mkdirSync(O.join(e,".dezycro"),{recursive:!0})}function K(){return JSON.parse(JSON.stringify(ge))}function k(e){let t=lt(e);try{let n=h.readFileSync(t,"utf8"),o=JSON.parse(n);return{...K(),...o,metrics:{...ut,...o.metrics||{}}}}catch(n){let o=n;return o&&o.code==="ENOENT",K()}}function ye(e){let t=dt(e),n=Date.now();for(;Date.now()-n<pe;){try{let r=h.openSync(t,"wx");return h.writeSync(r,String(process.pid)),h.closeSync(r),!0}catch(r){if(r.code!=="EEXIST")throw r}let o=Date.now()+fe;for(;Date.now()<o;);}return!1}function Se(e){try{h.unlinkSync(dt(e))}catch{}}function Te(e,t){return t?{...e,...t}:e}function X(e,t,n){if(!t||e.includes(t))return e;let o=e.concat([t]);return o.length>n?o.slice(o.length-n):o}function d(e,t){if(he(e),!ye(e))return null;try{let n=k(e),o=t||{},r={...n};for(let a of Object.keys(o)){let c=o[a];if(a==="metrics")r.metrics=Te(n.metrics,c);else if(a==="pushDecisionHash")r.recentDecisionHashes=X(n.recentDecisionHashes,c,q);else if(a==="pushIssueHash")r.recentIssueHashes=X(n.recentIssueHashes,c,q);else if(a==="pushAssumptionHash")r.recentAssumptionHashes=X(n.recentAssumptionHashes,c,q);else if(a==="pushControllerEdit"){let u=c,p=n.controllerEditsSinceLastPublish.filter(y=>y.path!==u.path).concat([u]);r.controllerEditsSinceLastPublish=p.length>ct?p.slice(p.length-ct):p}else r[a]=c}let s=me(e),i=h.openSync(s,"w");return h.writeSync(i,JSON.stringify(r,null,2)),h.fsyncSync(i),h.closeSync(i),h.renameSync(s,lt(e)),r}finally{Se(e)}}function x(e,t,n=1){let o=k(e).metrics[t]||0;return d(e,{metrics:{[t]:o+n}})}var F=T(require("fs")),Z=T(require("path")),ke="companion.log";function pt(e,t){try{let n=Z.join(e,".dezycro");if(!F.existsSync(n))return;let o=JSON.stringify({ts:new Date().toISOString(),...t})+`
2
- `;F.appendFileSync(Z.join(n,ke),o,{encoding:"utf8"})}catch{}}function f(e,t,n){pt(e,{level:"info",event:t,...n||{}})}function H(e,t,n){pt(e,{level:"warn",event:t,...n||{}})}var gt=T(require("fs")),mt=T(require("path"));function ht(e){let t=e||{},n=t.repoRoot,o=typeof t.maxAgeMinutes=="number"?t.maxAgeMinutes:60;if(!n)return!1;let r=mt.join(n,".dezycro","state.json"),s;try{let l=gt.readFileSync(r,"utf8");s=JSON.parse(l)}catch{return!1}if(!s||typeof s!="object")return!1;let i=s.lastVerifyTs,a=s.lastVerifyRunId;if(!i||!a)return!1;let c=Date.parse(i);if(!Number.isFinite(c))return!1;let u=Date.now()-c;return!(u<0||u>o*60*1e3)}function yt(e){let t=e||{},n=t.paths||[],o=t.status||"DONE",r=n.length>0?n.join(","):"<paths>";return{reason:"Cannot mark task "+o+" \u2014 no recent passing verifier run found for the linked paths. Run `/dezycro:verify --path "+r+"` first to attach passing verifier evidence, then retry."}}function St(e){if(!e)return{needed:!1,controllerPaths:[],lastEditTs:null};let t=k(e),n=Array.isArray(t.controllerEditsSinceLastPublish)?t.controllerEditsSinceLastPublish:[],o=n.map(i=>i&&i.path).filter(Boolean),r=n.length>0&&n[n.length-1].editedTs||null;return{needed:!!t.needsSpecPublish&&o.length>0,controllerPaths:o,lastEditTs:r}}function ve(e){return String(e||"").replace(/\\/g,"/")}function kt(e){let t=e.match(/\{([^{}]+)\}/);if(!t||t.index===void 0)return[e];let n=t[0],r=t[1].split(","),s=[];for(let i of r){let a=e.slice(0,t.index)+i+e.slice(t.index+n.length);s.push(...kt(a))}return s}function Ie(e){let t="^";for(let n=0;n<e.length;n+=1){let o=e[n];o==="*"?e[n+1]==="*"?(n+=1,e[n+1]==="/"?(n+=1,t+="(?:.*/)?"):t+=".*"):t+="[^/]*":o==="?"?t+="[^/]":".+^$()|[]\\".indexOf(o)!==-1?t+="\\"+o:t+=o}return t+="$",new RegExp(t)}var Tt=new Map;function Ce(e){let t=Tt.get(e);if(t)return t;let n=kt(e).map(Ie);return Tt.set(e,n),n}function Ae(e,t){if(!e||!Array.isArray(t)||t.length===0)return!1;let n=ve(e);for(let o of t){if(typeof o!="string"||o.length===0)continue;let r=Ce(o);for(let s of r)if(s.test(n))return!0}return!1}function bt(e,t){return Array.isArray(e)?e.filter(n=>Ae(n,t)):[]}var b=T(require("fs")),j=T(require("path"));var wt=Object.freeze({IDLE:"IDLE",DETECT_INTENT:"DETECT_INTENT",SCAN_EXISTING_WORK:"SCAN_EXISTING_WORK",CLARIFY:"CLARIFY",PROPOSE_PLACEMENT:"PROPOSE_PLACEMENT",CREATE_FEATURE:"CREATE_FEATURE",TRD_DISCOVERY:"TRD_DISCOVERY",MIN_CONTEXT_GATE:"MIN_CONTEXT_GATE",DRAFT:"DRAFT",ITERATE:"ITERATE",QUALITY_GATE:"QUALITY_GATE",FINALIZE:"FINALIZE"}),vt=Object.freeze({PRD:"PRD",TRD:"TRD"}),_n=Object.freeze(["skip","draft it","just write it","next"]),Pn=Object.freeze([wt.MIN_CONTEXT_GATE,wt.QUALITY_GATE]),Pe="authoring-transcript.json",Ee="authoring-current-draft.json";function It(e){return j.join(e,".dezycro",Pe)}function Ct(e){return j.join(e,".dezycro",Ee)}function xe(e){b.mkdirSync(j.join(e,".dezycro"),{recursive:!0})}function Re(e,t){let n=`${e}.tmp`,o=b.openSync(n,"w");try{b.writeSync(o,JSON.stringify(t,null,2)),b.fsyncSync(o)}finally{b.closeSync(o)}b.renameSync(n,e)}function At(e){try{let t=b.readFileSync(e,"utf8");return JSON.parse(t)}catch{return null}}function _t(e,t){if(!t||!t.docId||!t.docType)throw new Error("authoring.enter: docId and docType required");if(t.docType!==vt.PRD&&t.docType!==vt.TRD)throw new Error(`authoring.enter: invalid docType ${t.docType}`);xe(e);let n=It(e),o=new Date().toISOString(),r=At(n),s=r&&r.docId===t.docId?r:{docId:t.docId,docType:t.docType,featureId:t.featureId||null,seed:t.seed||null,startedTs:o,discoverySummary:null,qaTurns:[],draftHistory:[],qualityGateHistory:[]};return Re(n,s),d(e,{authoringMode:!0,authoringDocId:t.docId,authoringDocType:t.docType,authoringTranscriptPath:n,authoringStartedTs:o}),s}function Pt(e){d(e,{authoringMode:!1,authoringDocId:null,authoringDocType:null,authoringTranscriptPath:null,authoringStartedTs:null});for(let t of[It(e),Ct(e)])try{b.unlinkSync(t)}catch{}}function Et(e){let t=k(e);return{active:!!(t&&t.authoringMode),docId:t?t.authoringDocId:null,docType:t?t.authoringDocType:null,transcriptPath:t?t.authoringTranscriptPath:null,startedTs:t?t.authoringStartedTs:null}}function xt(e){return At(Ct(e))}var En=Object.freeze(["architecture","data model","data-model","datamodel","api contract","api-contract","apicontract","migration","auth","queue","verifier-behavior","verifier behavior"]),De=Object.freeze([{id:"architecture",pattern:/^##\s+architecture\b/im},{id:"data_model",pattern:/^##\s+data\s+model\b/im},{id:"api_contracts",pattern:/^##\s+api\s+contracts?\b/im},{id:"failure_modes",pattern:/^##\s+failure\s+modes?/im},{id:"migration",pattern:/^##\s+migration\b/im},{id:"open_questions",pattern:/^##\s+open\s+questions?\b/im}]),Ne=/\b(TBD|TODO|FIXME|fill in later|to be determined)\b/i,Rt=1e3,Ot=/^##\s+Pillar\s+\d+\s*:\s*(.+?)\s*$/gim,xn=Object.freeze(["data_model","api_contracts","state_or_persistence","failure_modes","migration_or_rollout"]);function Le(e){if(!e||typeof e!="string")return[];let t=[];Ot.lastIndex=0;let n;for(;(n=Ot.exec(e))!==null;){let o=n[1].trim();o&&t.push(o)}return t}function Dt(e){let{trdContent:t,prdContent:n}=e,o=[],r=(t||"").toString(),s=r.trim().length;s<Rt&&o.push({section:"document",issue:`TRD is too short (${s} chars; minimum ${Rt}).`,required_fix:"Expand the draft with concrete technical detail."});for(let c of De)c.pattern.test(r)||o.push({section:c.id,issue:"Required H2 section is missing.",required_fix:`Add a "## ${c.id.replace(/_/g," ")}" section grounded in the PRD + discovery.`});let i=r.match(Ne);i&&o.push({section:"placeholders",issue:`Placeholder token "${i[0]}" present \u2014 TRDs must not ship with unresolved placeholders.`,required_fix:"Resolve or move the open item into the ## Open Questions section."});let a=Le(n);if(a.length>0){let c=[],u=r.toLowerCase();for(let l of a)u.includes(l.toLowerCase())||c.push(l);c.length>0&&o.push({section:"pillar_coverage",issue:`TRD does not mention PRD pillar(s): ${c.join(", ")}.`,required_fix:"Add a per-pillar technical-design section, or reference each pillar by name in the relevant TRD section."})}return{passed:o.length===0,blockingIssues:o,deterministic:!0}}var Nt=T(require("crypto"));function Lt(e,t,n){let o=String(e||"").toLowerCase().trim(),r=String(t||"").toLowerCase().trim().replace(/\s+/g," "),s=String(n||"").toLowerCase().trim();return Nt.createHash("sha1").update(`${o}::${r}::${s}`).digest("hex").slice(0,16)}var B=Object.freeze({decision:"Logging decision: {{summary}} \u2014 reason: {{reason}}. Say 'undo that' if wrong.",issue:"Logging issue ({{severity}}): {{summary}}. Say 'undo that' if wrong.",assumption:"Logging assumption: {{summary}} \u2014 rationale: {{rationale}}. Say 'undo that' if wrong.",task_status:"Marking task {{task_id}} as {{proposed_status}} \u2014 rationale: {{rationale}}. Say 'undo that' if wrong."}),Fe="Auto-logging paused \u2014 {{count}} entries logged this session. Type /dezycro:sync to log manually.";function Mt(e){let t=e.thresholds||{},n=Math.max(0,Number(e.perTurnSlotsLeft)||0),o=Math.max(0,Number(e.perSessionSlotsLeft)||0);if(n<=0||o<=0)return Fe.replace("{{count}}",o<=0?"session-cap":"turn-cap");let r=Math.min(n,o),s=(e.recentHashes||[]).filter(Boolean),i=["[Dezycro Companion]",`Feature: ${He(e.activeFeatureName,e.activeFeatureId)}. Slots: ${r} (${n}/turn, ${o}/session).`,"","Scan since your last message for committed signals to log:",` - Decision (conf \u2265 ${t.decision??.85}) \u2014 committed technical/product choice`,` - Issue (conf \u2265 ${t.issue??.8}) \u2014 current blocker/bug`,` - Assumption (conf \u2265 ${t.assumption??.9}) \u2014 unverified belief affecting impl`,` - Task-status (conf \u2265 ${t.taskStatus??.9}) \u2014 task is now DONE/PUSHED`,"","Skip: hypotheticals, brainstorming, implementation-obvious details, ephemeral content, intent statements while authoring a PRD/TRD."];return s.length>0&&i.push(`Already-logged hashes (skip dupes): ${s.join(", ")}`),i.push("","For each surviving candidate (max "+r+"): print the announce line verbatim and call the matching MCP tool.",' decision: "'+B.decision+'" \u2192 mcp__dezycro(-dev)?__add_decision',' issue: "'+B.issue+'" \u2192 mcp__dezycro(-dev)?__add_issue',' assumption: "'+B.assumption+'" \u2192 mcp__dezycro(-dev)?__add_assumption',' task_status: "'+B.task_status+'" \u2192 mcp__dezycro(-dev)?__update_task',"","If nothing meets the bar, simply continue with whatever the user asked next \u2014 do NOT output any acknowledgment line. The hook will silence itself for trivial turns."),i.join(`
3
- `)}function He(e,t){if(!t)return"(none \u2014 skip if no feature is active)";let n=String(t).slice(0,8);return e?`${e} (${n}\u2026)`:n+"\u2026"}function Ut(e){return typeof e!="string"?null:/add_decision$/.test(e)?"decision":/add_issue$/.test(e)?"issue":/add_assumption$/.test(e)?"assumption":/update_task$/.test(e)?"task-status":null}var Ft=Object.freeze(["undo that","no, wrong","revert that","undo the last log","wrong, undo"]);function Ht(e){if(typeof e!="string")return!1;let t=e.toLowerCase().trim();if(!t)return!1;for(let n=0;n<Ft.length;n+=1)if(t.includes(Ft[n]))return!0;return!1}function jt(e){if(!e||!e.tool||!e.entityId)return null;let t=e.entityId;switch(e.tool){case"add_decision":return{tool:"update_decision",args:{id:t,status:"INVALIDATED",reason:"undo by user"},humanLine:`Reverting the last auto-logged decision (${t.slice(0,8)}\u2026) \u2014 marking INVALIDATED.`};case"add_issue":return{tool:"update_issue",args:{id:t,status:"CANCELLED",reason:"undo by user"},humanLine:`Reverting the last auto-logged issue (${t.slice(0,8)}\u2026) \u2014 marking CANCELLED.`};case"add_assumption":return{tool:"update_issue",args:{id:t,status:"INVALIDATED",kind:"ASSUMPTION",reason:"undo by user"},humanLine:`Reverting the last auto-logged assumption (${t.slice(0,8)}\u2026) \u2014 marking INVALIDATED.`};case"update_task":return e.priorStatus?{tool:"update_task",args:{id:t,status:e.priorStatus},humanLine:`Reverting the last auto-task-status change \u2014 restoring ${t.slice(0,8)}\u2026 to ${e.priorStatus}.`}:null;default:return null}}function Bt(e,t){return!e||typeof e.createdInTurnId!="number"?!1:t===e.createdInTurnId+1}function Q(e,t){return`${e} ${t}${e===1?"":"s"}`}function tt(e){return!e||typeof e!="object"?null:{uncoveredPaths:Number(e.uncoveredPaths??0)||0,endpointsNotInSpec:Number(e.endpointsNotInSpec??0)||0,staleBaselines:Number(e.staleBaselines??0)||0}}function $(e){let t=tt(e);if(!t)return null;let n=[];return t.uncoveredPaths>0&&n.push(`${Q(t.uncoveredPaths,"path")} uncovered`),t.endpointsNotInSpec>0&&n.push(`${Q(t.endpointsNotInSpec,"endpoint")} not in spec`),t.staleBaselines>0&&n.push(`${Q(t.staleBaselines,"baseline")} stale`),n.length===0?null:`Coverage: ${n.join(", ")}`}function $t(e,t){let n=tt(e),o=tt(t);if(!o)return null;if(!n)return $(t);let s=[["paths uncovered",o.uncoveredPaths-n.uncoveredPaths],["endpoints not in spec",o.endpointsNotInSpec-n.endpointsNotInSpec],["baselines stale",o.staleBaselines-n.staleBaselines]].filter(([,a])=>a!==0);return s.length===0?null:`Coverage delta since last verify: ${s.map(([a,c])=>`${c>0?"+":""}${c} ${a}`).join(", ")}`}var V=T(require("fs")),Jt=T(require("os")),I=T(require("path")),J=class e{constructor(t){this.repoRoot=t;this.config=e.readJson(I.join(t,".dezycro","config.json"))}repoRoot;config;static at(t=process.cwd()){return new e(e.findRepoRoot(t)??I.resolve(t))}get workspaceId(){return e.env("DZ_WORKSPACE_ID")??e.str(this.config?.workspaceId)}get tenantId(){return e.env("DZ_TENANT_ID")??e.str(this.config?.tenantId)}get projectId(){return e.str(this.config?.projectId)}get apiUrl(){let t=e.env("DZ_API_URL");if(t)return e.trimSlash(t);let n=Array.isArray(this.config?.environments)?this.config?.environments:[],o=n.find(s=>e.isObj(s)&&s.default===!0)??n[0],r=e.isObj(o)?e.str(o.apiUrl):null;return r?e.trimSlash(r):null}get token(){let t=e.env("DZ_TOKEN");if(t)return t;let n=[I.join(this.repoRoot,".dezycro","companion-token.local.json"),I.join(Jt.homedir(),".dezycro","token.json")];for(let o of n){let r=e.str(e.readJson(o)?.token);if(r)return r}return null}activeFeature(){let t=e.readJson(I.join(this.repoRoot,".dezycro","active-feature.json")),n=e.str(t?.featureId);if(!n)return null;let o=e.str(t?.workspaceId)??this.workspaceId;return o?{workspaceId:o,featureId:n}:null}connection(){let t=this.apiUrl;if(!t)return{error:"no apiUrl (set DZ_API_URL or .dezycro/config.json environments[].apiUrl)"};let n=this.workspaceId;if(!n)return{error:"no workspaceId (set DZ_WORKSPACE_ID or .dezycro/config.json workspaceId)"};let o=this.token;return o?{apiUrl:t,workspaceId:n,token:o}:{error:"no token (run `dezycro setup` or set DZ_TOKEN)"}}static findRepoRoot(t){let n=I.resolve(t||process.cwd());for(let o=0;o<64;o+=1){if(V.existsSync(I.join(n,".dezycro")))return n;let r=I.dirname(n);if(r===n)return null;n=r}return null}static readJson(t){try{return JSON.parse(V.readFileSync(t,"utf8"))}catch{return null}}static isObj(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}static str(t){return typeof t=="string"&&t.length>0?t:null}static env(t){let n=process.env[t];return n&&n.length>0?n:null}static trimSlash(t){return t.replace(/\/$/,"")}};var Je=["sessionStart","userPromptSubmit","stop","postToolUse"],Ve=60,ze="HALT_AND_REPLAN",Vt=200,Ge=100,We=3,qe=1800;function zt(e,t,n,o){if(t<n)return e;let r=t-n+1,s=e*Math.pow(2,r);return Math.min(s,o)}async function D(e,t,n,o){let r=Ye(n),s=r.reactionMode,i={events:[],statePatch:null,reactionMode:s};if(!r.enabled||!r.hooks.has(t)&&t!=="sessionStart")return i;let a=o.commandBus,c=a.lastAttemptTs??a.lastPollTs;if(t!=="sessionStart"&&c){let S=Date.parse(c);if(!Number.isNaN(S)){let g=zt(r.minPollIntervalSeconds,a.consecutiveFailures??0,r.circuitBreakerThreshold,r.maxBackoffSeconds);if((Date.now()-S)/1e3<g)return i}}let u=new J(e),l=u.activeFeature();if(!l)return i;let p=u.apiUrl;if(!p)return i;let y=u.token;if(!y)return f(e,"command_bus_skip_no_token",{hookEvent:t}),i;let v=t==="sessionStart"?null:a.cursor,m=new Date().toISOString();try{let S=await Ze(p,l,y,v),g=new Set(a.recentEventIds??[]),w=S.events.filter(P=>!g.has(P.eventId)),C=Qe([...a.recentEventIds??[],...w.map(P=>P.eventId)]),L={commandBus:{cursor:S.nextCursor||a.cursor,lastPollTs:S.serverTs,lastAttemptTs:m,consecutiveFailures:0,recentEventIds:C}};return w.length>0&&f(e,"command_bus_events_received",{hookEvent:t,count:w.length,types:w.map(P=>P.eventType)}),{events:w,statePatch:L,reactionMode:s}}catch(S){let g=(a.consecutiveFailures??0)+1,w={commandBus:{...a,lastAttemptTs:m,consecutiveFailures:g}},C=zt(r.minPollIntervalSeconds,g,r.circuitBreakerThreshold,r.maxBackoffSeconds);return f(e,"command_bus_poll_failed",{hookEvent:t,error:S instanceof Error?S.message:String(S),consecutiveFailures:g,nextPollAfterSeconds:C,backoff:g>=r.circuitBreakerThreshold}),{events:[],statePatch:w,reactionMode:s}}}function z(e,t){if(e.length===0)return"";let n=[];n.push(`\u26A0\uFE0F Dezycro Command Bus: ${e.length} new event(s) on this feature.`),n.push("");for(let o of e)n.push(Ke(o));return e.some(o=>o.urgency==="BLOCKING")&&(n.push(""),n.push(Xe(t))),n.join(`
4
- `)}function Ke(e){if(e.eventType==="INVALIDATION"){let t=et(e.payload,"artifactSummary")??"(no summary)",n=et(e.payload,"reason")??"(no reason)",o=et(e.payload,"previousStatus")??"?",r=`${e.sourceType.toLowerCase()} ${e.sourceId??"?"}`;return`- INVALIDATION (${e.urgency}): ${r} ("${Gt(t,120)}") \u2014 reason: "${Gt(n,200)}" \u2014 was ${o}.`}return`- ${e.eventType} (${e.urgency}) source=${e.sourceType}/${e.sourceId??"-"}.`}function Xe(e){switch(e){case"HALT_AND_REPLAN":return"Reaction mode: HALT_AND_REPLAN \u2014 pause your current line of work, acknowledge in chat, and re-plan around these invalidations before touching code again.";case"ACKNOWLEDGE_AND_CONTINUE":return"Reaction mode: ACKNOWLEDGE_AND_CONTINUE \u2014 surface this in your reply but continue current work; do not silently reuse invalidated artifacts.";case"SILENT_LOG":return"Reaction mode: SILENT_LOG \u2014 recorded for the session transcript; no chat interruption.";default:return""}}function Ye(e){let t=e?.enabled!==!1,n=new Set(e?.pollHooks??Je);n.add("sessionStart");let o=Math.max(0,e?.minPollIntervalSeconds??Ve),r=e?.reactionMode??ze,s=Math.max(1,e?.circuitBreakerThreshold??We),i=Math.max(o,e?.maxBackoffSeconds??qe);return{enabled:t,hooks:n,minPollIntervalSeconds:o,reactionMode:r,circuitBreakerThreshold:s,maxBackoffSeconds:i}}async function Ze(e,t,n,o){let r=new URL(`${e}/api/v1/workspaces/${t.workspaceId}/features/${t.featureId}/inbox`);o&&r.searchParams.set("since",o),r.searchParams.set("limit",String(Ge));let s=new AbortController,i=setTimeout(()=>s.abort(),5e3);try{let a=await fetch(r.toString(),{method:"GET",headers:{Authorization:`Bearer ${n}`,Accept:"application/json"},signal:s.signal});if(!a.ok)throw new Error(`inbox poll returned ${a.status}`);let c=await a.json();if(!c||typeof c.serverTs!="string"||typeof c.nextCursor!="string")throw new Error("inbox poll response missing serverTs/nextCursor");return{serverTs:c.serverTs,nextCursor:c.nextCursor,events:Array.isArray(c.events)?c.events:[]}}finally{clearTimeout(i)}}function Qe(e){return e.length<=Vt?e:e.slice(e.length-Vt)}function et(e,t){let n=e?.[t];return typeof n=="string"?n:null}function Gt(e,t){return e.length<=t?e:e.slice(0,t-1)+"\u2026"}var en=new Set(["DONE","PUSHED"]),nn=["/dezycro:sync","log what we did","log this","save progress","save what we did","wrap up","we're done","we are done","end of session","sweep the workbook"];function on(e){if(typeof e!="string")return null;let t=e.toLowerCase().trim();if(!t)return null;for(let n of nn)if(t.includes(n))return n;return null}var qt="TRD quality gate (deterministic layer) blocked APPROVED transition: ";async function rn(e){let{event:t,route:n,payload:o,flags:r}=e;return t==="state"?cn(r||{}):t==="authoring-state"?un(r||{}):t==="pre-tool-use"&&n==="update_task"?Kt(o||{}):t==="pre-tool-use"&&n==="change_document_status"?an(o||{}):t==="post-tool-use"&&n==="edit"?Xt(o||{}):t==="post-tool-use"&&n==="workbook_mutation"?oe(o||{}):t==="session-start"?Zt(o||{}):t==="user-prompt-submit"?Qt(o||{}):t==="stop"?te(o||{}):0}function Kt(e){let t=A(process.cwd());if(!t)return process.stdout.write("{}"),0;let n=e&&e.tool_input||{},o=String(n.status||"").toUpperCase();if(!en.has(o))return process.stdout.write("{}"),0;let r=n.pathRefs,s=Array.isArray(r)?r.filter(Boolean):[];if(s.length===0)return process.stdout.write("{}"),0;let i=_(t);if((i&&i.companion&&i.companion.autoVerify||{}).preTaskDone===!1)return process.stdout.write("{}"),0;if(ht({repoRoot:t,paths:s})){if(f(t,"pre_done_gate_pass",{status:o,pathRefs:s}),o==="PUSHED"){let p=sn(t,i);if(p){f(t,"pre_push_coverage_nudge",{line:p});let y={systemMessage:p};return process.stdout.write(JSON.stringify(y)),0}}return process.stdout.write("{}"),0}x(t,"verifyAutoRuns"),x(t,"verifyAutoFailures"),H(t,"pre_done_gate_block",{status:o,pathRefs:s});let u=yt({paths:s,status:o}).reason,l={decision:"block",reason:u,hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:u}};return process.stdout.write(JSON.stringify(l)),0}function sn(e,t){if((t&&t.companion&&t.companion.coverageNudges||{}).enabled===!1)return null;let o=k(e).coverageSnapshot,r=$(o);return r?`[Companion] ${r} \u2014 verify passed, but consider checking these before push.`:null}function an(e){let n=e&&e.tool_input||{},o=n.status||n.newStatus||null,r=n.docId||n.documentId||n.id||null;if(o!=="APPROVED")return process.stdout.write("{}"),0;let s=A(process.cwd());if(!s)return process.stdout.write("{}"),0;let i=xt(s);if(!i||r&&i.docId&&i.docId!==r)return H(s,"quality_gate_degraded_permit",{reason:i?"docId_mismatch":"sidecar_missing",docId:r,sidecarDocId:i?i.docId:null}),process.stdout.write("{}"),0;if(i.docType!=="TRD")return process.stdout.write("{}"),0;let a=Dt({trdContent:i.content,prdContent:i.prdContent||""});if(a.passed)return f(s,"quality_gate_deterministic_pass",{docId:i.docId}),process.stdout.write("{}"),0;x(s,"qualityGateFailures");let c=a.blockingIssues.map(p=>`[${p.section}] ${p.issue}`).slice(0,5).join(" | "),u=`${qt}${c||"unspecified failure"}. Fix and try again.`;H(s,"quality_gate_blocked",{docId:i.docId,issues:a.blockingIssues});let l={decision:"block",reason:u,hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:u}};return process.stdout.write(JSON.stringify(l)),0}async function Xt(e){let t=A(process.cwd());if(!t)return 0;{let m=_(t),S=k(t),g=await D(t,"postToolUse",m?.companion?.commandBus,S);g.statePatch&&d(t,g.statePatch);let w=z(g.events,g.reactionMode);if(w){let C={hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:w}};return process.stdout.write(JSON.stringify(C)),0}}let n=e&&e.tool_input||{},o=Yt(n);if(o.length===0)return 0;let r=_(t),s=r&&r.companion&&r.companion.autoVerify||{},i=Array.isArray(s.controllerPaths)?s.controllerPaths:[],a=s.postEditPulse&&s.postEditPulse.enabled!==!1,c=s.postEditPulse&&Number(s.postEditPulse.threshold)||5,u=bt(o,i),l=new Date().toISOString(),y=(k(t).pulseCount||0)+1,v=a&&y>=c&&u.length>0;if(u.length===0)d(t,{pulseCount:y,lastEditTs:l});else for(let m=0;m<u.length;m+=1){let S=m===u.length-1,g={pushControllerEdit:{path:u[m],editedTs:l}};S&&(g.needsSpecPublish=!0,g.lastEditTs=l,g.pulseCount=v?0:y),d(t,g)}if(f(t,"post_edit",{edited:o.length,matchedControllers:u.length,pulseCount:v?0:y,nudged:v}),v){let m="[Companion] "+y+" edits since last verify and controller paths were touched ("+u.join(", ")+"). Consider running `/dezycro:verify` to catch regressions early.";process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:m}}))}return 0}function Yt(e){if(!e||typeof e!="object")return[];let t=e.file_path;if(typeof t=="string")return[t];let n=e.path;if(typeof n=="string")return[n];let o=e.edits;if(Array.isArray(o)){let r=new Set;for(let s of o)s&&typeof s.file_path=="string"&&r.add(s.file_path);return Array.from(r)}return[]}function cn(e){let t=A(process.cwd())||process.cwd();if(e.get){let n=k(t);return process.stdout.write(JSON.stringify(n,null,2)),0}if(typeof e.patch=="string"){let n;try{n=JSON.parse(e.patch)}catch(r){let s=r.message;return process.stdout.write(JSON.stringify({ok:!1,error:"invalid JSON for --patch: "+s})),1}return n===null||typeof n!="object"||Array.isArray(n)?(process.stdout.write(JSON.stringify({ok:!1,error:"--patch must be a JSON object"})),1):d(t,n)===null?(process.stdout.write(JSON.stringify({ok:!1,error:"lock contention \u2014 state not patched"})),1):(process.stdout.write(JSON.stringify({ok:!0})),0)}return process.stdout.write(JSON.stringify({ok:!1,error:"state requires one of --get or --patch=<json>"})),1}function un(e){let t=A(process.cwd())||process.cwd(),n=e.set||(e.get?"get":null);if(n==="enter"){let o=e["doc-id"],r=e["doc-type"];if(!o||!r)return process.stdout.write(JSON.stringify({ok:!1,error:"--doc-id and --doc-type are required for --set=enter"})),1;try{let s=_t(t,{docId:o,docType:r,featureId:e["feature-id"]||null,seed:e.seed||null});return process.stdout.write(JSON.stringify({ok:!0,transcript:s})),0}catch(s){return process.stdout.write(JSON.stringify({ok:!1,error:s.message})),1}}if(n==="exit")try{return Pt(t),process.stdout.write(JSON.stringify({ok:!0})),0}catch(o){return process.stdout.write(JSON.stringify({ok:!1,error:o.message})),1}if(n==="get"){let o=Et(t);return process.stdout.write(JSON.stringify({ok:!0,...o})),0}return process.stdout.write(JSON.stringify({ok:!1,error:"authoring-state requires one of --set=enter, --set=exit, --get"})),1}var ln=600;async function Zt(e){let t=A(process.cwd());if(!t)return 0;d(t,{sessionAutoLogCount:0,turnAutoLogCount:0,currentTurnId:0,lastAutoWorkbookMutation:null,coverageFetchPending:!1}),f(t,"session_start",{});let n=_(t),o=k(t),r=await D(t,"sessionStart",n?.companion?.commandBus,o);return r.statePatch&&d(t,r.statePatch),0}async function Qt(e){let t=A(process.cwd());if(!t)return 0;let n=k(t),o=(n.currentTurnId||0)+1;d(t,{currentTurnId:o,turnAutoLogCount:0});{let i=_(t),a=await D(t,"userPromptSubmit",i?.companion?.commandBus,n);a.statePatch&&d(t,a.statePatch);let c=z(a.events,a.reactionMode);if(c){let u={hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:c}};return process.stdout.write(JSON.stringify(u)),0}}let r=String(e?.prompt??e?.user_message??e?.message??"").trim(),s=on(r);if(s&&(d(t,{pendingWorkbookSweep:!0,pendingWorkbookSweepReason:"wrap_phrase:"+s}),f(t,"wrap_phrase_detected",{phrase:s})),r&&Ht(r)){let i=n.lastAutoWorkbookMutation;if(i&&Bt(i,o)){let a=jt(i);if(a){x(t,"undoCount"),d(t,{lastAutoWorkbookMutation:null}),f(t,"undo_directive",{tool:a.tool,entityId:i.entityId});let u={hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:"[Dezycro Companion \u2014 undo] "+a.humanLine+`
1
+ "use strict";var se=Object.create;var H=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var ue=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty;var le=(e,t)=>{for(var n in t)H(e,n,{get:t[n],enumerable:!0})},it=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ae(t))!ce.call(e,r)&&r!==n&&H(e,r,{get:()=>t[r],enumerable:!(o=ie(t,r))||o.enumerable});return e};var S=(e,t,n)=>(n=e!=null?se(ue(e)):{},it(t||!e||!e.__esModule?H(n,"default",{value:e,enumerable:!0}):n,e)),de=e=>it(H({},"__esModule",{value:!0}),e);var Tn={};le(Tn,{QUALITY_GATE_REASON_PREFIX:()=>Kt,TRIVIAL_TURN_CHAR_DEFAULT_EXPORT:()=>bn,_extractEditedPaths:()=>dn,_handlePostEdit:()=>pn,_handleSessionStart:()=>yn,_handleStop:()=>gn,_handleUpdateTaskGate:()=>fn,_handleUserPromptSubmit:()=>mn,_handleWorkbookMutation:()=>hn,_readActiveFeatureId:()=>Sn,_transcriptCharsSinceLastStop:()=>kn,dispatch:()=>tn});module.exports=de(Tn);var M=S(require("fs")),qt=S(require("path"));var U=S(require("fs")),A=S(require("path")),at=Object.freeze({conservative:{decision:.85,issue:.8,assumption:.9,taskStatus:.9},balanced:{decision:.75,issue:.7,assumption:.8,taskStatus:.85},aggressive:{decision:.6,issue:.55,assumption:.7,taskStatus:.75}}),O=Object.freeze({companion:{autoVerify:{preTaskDone:!0,prePush:!0,postEditPulse:{enabled:!0,threshold:5},autoPublishSpecOnControllerChange:!0,controllerPaths:["**/controllers/**/*.{kt,java,py,go,ts,tsx,js,rs,rb,cs}","**/api/**/*.{kt,java,py,go,ts,tsx,js,rs,rb,cs}"],verifyTimeoutSeconds:300,publishSpecTimeoutSeconds:300},autoWorkbookUpdates:{enabled:!0,preset:"conservative",maxAutoLogsPerTurn:2,maxAutoLogsPerSession:10,undoWindow:"next-turn",thresholds:{decision:null,issue:null,assumption:null,taskStatus:null},trivialTurnCharCutoff:600,hashRingBufferSize:32},coverageNudges:{enabled:!0,staleBaselineDays:14,fetchMode:"async"},authoring:{defaultDepth:"adaptive",existingWorkScan:!0,qualityGate:{enabled:!0},minViableContextGate:{enabled:!0}},safeMode:!1}});function K(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function ut(e,t){if(!K(t))return t===void 0?e:t;let n=Array.isArray(e)?[...e]:{...e};for(let o of Object.keys(t)){let r=n[o],s=t[o];K(r)&&K(s)?n[o]=ut(r,s):n[o]=s}return n}function ct(e){let t=A.join(e,".dezycro","config.json"),n;try{n=U.readFileSync(t,"utf8")}catch(r){if(r.code==="ENOENT")return JSON.parse(JSON.stringify(O));throw r}let o;try{o=JSON.parse(n)}catch{return JSON.parse(JSON.stringify(O))}return ut(JSON.parse(JSON.stringify(O)),o)}function lt(e){let t=e?.companion?.autoWorkbookUpdates||{},n=t.preset||"conservative",o=at[n]||at.conservative,r=t.thresholds||{};return{decision:typeof r.decision=="number"?r.decision:o.decision,issue:typeof r.issue=="number"?r.issue:o.issue,assumption:typeof r.assumption=="number"?r.assumption:o.assumption,taskStatus:typeof r.taskStatus=="number"?r.taskStatus:o.taskStatus}}function I(e){let t=A.resolve(e||process.cwd());for(let n=0;n<64;n+=1){if(U.existsSync(A.join(t,".dezycro")))return t;let o=A.dirname(t);if(o===t)return null;t=o}return null}var m=S(require("fs")),D=S(require("path")),fe=500,ge=10,X=32,dt=64,pt=Object.freeze({autoDecisionLogs:0,autoIssueLogs:0,autoAssumptionLogs:0,autoTaskStatusLogs:0,undoCount:0,verifyAutoRuns:0,verifyAutoFailures:0,qualityGateFailures:0,contextGateFailures:0,lockContention:0,forceApprovals:0}),me=Object.freeze({schemaVersion:1,currentSessionId:null,authoringMode:!1,authoringDocId:null,authoringDocType:null,authoringTranscriptPath:null,authoringStartedTs:null,pulseCount:0,lastEditTs:null,needsSpecPublish:!1,controllerEditsSinceLastPublish:[],coverageSnapshot:null,coverageSnapshotTs:null,coverageFetchPending:!1,lastVerifyCompletionTs:null,recentDecisionHashes:[],recentIssueHashes:[],recentAssumptionHashes:[],lastAutoWorkbookMutation:null,sessionAutoLogCount:0,turnAutoLogCount:0,currentTurnId:0,suppressWorkbookUpdatesUntil:null,pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:null,commandBus:{cursor:null,lastPollTs:null,lastAttemptTs:null,consecutiveFailures:0,recentEventIds:[]},metrics:pt});function ft(e){return D.join(e,".dezycro","companion-state.json")}function gt(e){return D.join(e,".dezycro",".companion-state.lock")}function he(e){return D.join(e,".dezycro",".companion-state.json.tmp")}function ye(e){m.mkdirSync(D.join(e,".dezycro"),{recursive:!0})}function Y(){return JSON.parse(JSON.stringify(me))}function k(e){let t=ft(e);try{let n=m.readFileSync(t,"utf8"),o=JSON.parse(n);return{...Y(),...o,metrics:{...pt,...o.metrics||{}}}}catch(n){let o=n;return o&&o.code==="ENOENT",Y()}}function Se(e){let t=gt(e),n=Date.now();for(;Date.now()-n<fe;){try{let r=m.openSync(t,"wx");return m.writeSync(r,String(process.pid)),m.closeSync(r),!0}catch(r){if(r.code!=="EEXIST")throw r}let o=Date.now()+ge;for(;Date.now()<o;);}return!1}function ke(e){try{m.unlinkSync(gt(e))}catch{}}function be(e,t){return t?{...e,...t}:e}function Q(e,t,n){if(!t||e.includes(t))return e;let o=e.concat([t]);return o.length>n?o.slice(o.length-n):o}function d(e,t){if(ye(e),!Se(e))return null;try{let n=k(e),o=t||{},r={...n};for(let a of Object.keys(o)){let u=o[a];if(a==="metrics")r.metrics=be(n.metrics,u);else if(a==="pushDecisionHash")r.recentDecisionHashes=Q(n.recentDecisionHashes,u,X);else if(a==="pushIssueHash")r.recentIssueHashes=Q(n.recentIssueHashes,u,X);else if(a==="pushAssumptionHash")r.recentAssumptionHashes=Q(n.recentAssumptionHashes,u,X);else if(a==="pushControllerEdit"){let c=u,f=n.controllerEditsSinceLastPublish.filter(h=>h.path!==c.path).concat([c]);r.controllerEditsSinceLastPublish=f.length>dt?f.slice(f.length-dt):f}else r[a]=u}let s=he(e),i=m.openSync(s,"w");return m.writeSync(i,JSON.stringify(r,null,2)),m.fsyncSync(i),m.closeSync(i),m.renameSync(s,ft(e)),r}finally{ke(e)}}function R(e,t,n=1){let o=k(e).metrics[t]||0;return d(e,{metrics:{[t]:o+n}})}var B=S(require("fs")),tt=S(require("path")),Te="companion.log";function mt(e,t){try{let n=tt.join(e,".dezycro");if(!B.existsSync(n))return;let o=JSON.stringify({ts:new Date().toISOString(),...t})+`
2
+ `;B.appendFileSync(tt.join(n,Te),o,{encoding:"utf8"})}catch{}}function g(e,t,n){mt(e,{level:"info",event:t,...n||{}})}function F(e,t,n){mt(e,{level:"warn",event:t,...n||{}})}var yt=S(require("fs")),St=S(require("path"));function kt(e){let t=e||{},n=t.repoRoot,o=typeof t.maxAgeMinutes=="number"?t.maxAgeMinutes:60;if(!n)return!1;let r=St.join(n,".dezycro","state.json"),s;try{let l=yt.readFileSync(r,"utf8");s=JSON.parse(l)}catch{return!1}if(!s||typeof s!="object")return!1;let i=s.lastVerifyTs,a=s.lastVerifyRunId;if(!i||!a)return!1;let u=Date.parse(i);if(!Number.isFinite(u))return!1;let c=Date.now()-u;return!(c<0||c>o*60*1e3)}function bt(e){let t=e||{},n=t.paths||[],o=t.status||"DONE",r=n.length>0?n.join(","):"<paths>";return{reason:"Cannot mark task "+o+" \u2014 no recent passing verifier run found for the linked paths. Run `/dezycro:verify --path "+r+"` first to attach passing verifier evidence, then retry."}}function Tt(e){if(!e)return{needed:!1,controllerPaths:[],lastEditTs:null};let t=k(e),n=Array.isArray(t.controllerEditsSinceLastPublish)?t.controllerEditsSinceLastPublish:[],o=n.map(i=>i&&i.path).filter(Boolean),r=n.length>0&&n[n.length-1].editedTs||null;return{needed:!!t.needsSpecPublish&&o.length>0,controllerPaths:o,lastEditTs:r}}function we(e){return String(e||"").replace(/\\/g,"/")}function Ct(e){let t=e.match(/\{([^{}]+)\}/);if(!t||t.index===void 0)return[e];let n=t[0],r=t[1].split(","),s=[];for(let i of r){let a=e.slice(0,t.index)+i+e.slice(t.index+n.length);s.push(...Ct(a))}return s}function Pe(e){let t="^";for(let n=0;n<e.length;n+=1){let o=e[n];o==="*"?e[n+1]==="*"?(n+=1,e[n+1]==="/"?(n+=1,t+="(?:.*/)?"):t+=".*"):t+="[^/]*":o==="?"?t+="[^/]":".+^$()|[]\\".indexOf(o)!==-1?t+="\\"+o:t+=o}return t+="$",new RegExp(t)}var vt=new Map;function Ie(e){let t=vt.get(e);if(t)return t;let n=Ct(e).map(Pe);return vt.set(e,n),n}function xe(e,t){if(!e||!Array.isArray(t)||t.length===0)return!1;let n=we(e);for(let o of t){if(typeof o!="string"||o.length===0)continue;let r=Ie(o);for(let s of r)if(s.test(n))return!0}return!1}function wt(e,t){return Array.isArray(e)?e.filter(n=>xe(n,t)):[]}var b=S(require("fs")),j=S(require("path"));var Pt=Object.freeze({IDLE:"IDLE",DETECT_INTENT:"DETECT_INTENT",SCAN_EXISTING_WORK:"SCAN_EXISTING_WORK",CLARIFY:"CLARIFY",PROPOSE_PLACEMENT:"PROPOSE_PLACEMENT",CREATE_FEATURE:"CREATE_FEATURE",TRD_DISCOVERY:"TRD_DISCOVERY",MIN_CONTEXT_GATE:"MIN_CONTEXT_GATE",DRAFT:"DRAFT",ITERATE:"ITERATE",QUALITY_GATE:"QUALITY_GATE",FINALIZE:"FINALIZE"}),It=Object.freeze({PRD:"PRD",TRD:"TRD"}),Cn=Object.freeze(["skip","draft it","just write it","next"]),wn=Object.freeze([Pt.MIN_CONTEXT_GATE,Pt.QUALITY_GATE]),_e="authoring-transcript.json",Re="authoring-current-draft.json";function xt(e){return j.join(e,".dezycro",_e)}function At(e){return j.join(e,".dezycro",Re)}function Ee(e){b.mkdirSync(j.join(e,".dezycro"),{recursive:!0})}function Oe(e,t){let n=`${e}.tmp`,o=b.openSync(n,"w");try{b.writeSync(o,JSON.stringify(t,null,2)),b.fsyncSync(o)}finally{b.closeSync(o)}b.renameSync(n,e)}function _t(e){try{let t=b.readFileSync(e,"utf8");return JSON.parse(t)}catch{return null}}function Rt(e,t){if(!t||!t.docId||!t.docType)throw new Error("authoring.enter: docId and docType required");if(t.docType!==It.PRD&&t.docType!==It.TRD)throw new Error(`authoring.enter: invalid docType ${t.docType}`);Ee(e);let n=xt(e),o=new Date().toISOString(),r=_t(n),s=r&&r.docId===t.docId?r:{docId:t.docId,docType:t.docType,featureId:t.featureId||null,seed:t.seed||null,startedTs:o,discoverySummary:null,qaTurns:[],draftHistory:[],qualityGateHistory:[]};return Oe(n,s),d(e,{authoringMode:!0,authoringDocId:t.docId,authoringDocType:t.docType,authoringTranscriptPath:n,authoringStartedTs:o}),s}function Et(e){d(e,{authoringMode:!1,authoringDocId:null,authoringDocType:null,authoringTranscriptPath:null,authoringStartedTs:null});for(let t of[xt(e),At(e)])try{b.unlinkSync(t)}catch{}}function Ot(e){let t=k(e);return{active:!!(t&&t.authoringMode),docId:t?t.authoringDocId:null,docType:t?t.authoringDocType:null,transcriptPath:t?t.authoringTranscriptPath:null,startedTs:t?t.authoringStartedTs:null}}function Dt(e){return _t(At(e))}var Pn=Object.freeze(["architecture","data model","data-model","datamodel","api contract","api-contract","apicontract","migration","auth","queue","verifier-behavior","verifier behavior"]),Ne=Object.freeze([{id:"architecture",pattern:/^##\s+architecture\b/im},{id:"data_model",pattern:/^##\s+data\s+model\b/im},{id:"api_contracts",pattern:/^##\s+api\s+contracts?\b/im},{id:"failure_modes",pattern:/^##\s+failure\s+modes?/im},{id:"migration",pattern:/^##\s+migration\b/im},{id:"open_questions",pattern:/^##\s+open\s+questions?\b/im}]),Le=/\b(TBD|TODO|FIXME|fill in later|to be determined)\b/i,Nt=1e3,Lt=/^##\s+Pillar\s+\d+\s*:\s*(.+?)\s*$/gim,In=Object.freeze(["data_model","api_contracts","state_or_persistence","failure_modes","migration_or_rollout"]);function Me(e){if(!e||typeof e!="string")return[];let t=[];Lt.lastIndex=0;let n;for(;(n=Lt.exec(e))!==null;){let o=n[1].trim();o&&t.push(o)}return t}function Mt(e){let{trdContent:t,prdContent:n}=e,o=[],r=(t||"").toString(),s=r.trim().length;s<Nt&&o.push({section:"document",issue:`TRD is too short (${s} chars; minimum ${Nt}).`,required_fix:"Expand the draft with concrete technical detail."});for(let u of Ne)u.pattern.test(r)||o.push({section:u.id,issue:"Required H2 section is missing.",required_fix:`Add a "## ${u.id.replace(/_/g," ")}" section grounded in the PRD + discovery.`});let i=r.match(Le);i&&o.push({section:"placeholders",issue:`Placeholder token "${i[0]}" present \u2014 TRDs must not ship with unresolved placeholders.`,required_fix:"Resolve or move the open item into the ## Open Questions section."});let a=Me(n);if(a.length>0){let u=[],c=r.toLowerCase();for(let l of a)c.includes(l.toLowerCase())||u.push(l);u.length>0&&o.push({section:"pillar_coverage",issue:`TRD does not mention PRD pillar(s): ${u.join(", ")}.`,required_fix:"Add a per-pillar technical-design section, or reference each pillar by name in the relevant TRD section."})}return{passed:o.length===0,blockingIssues:o,deterministic:!0}}var Ht=S(require("crypto"));function Ut(e,t,n){let o=String(e||"").toLowerCase().trim(),r=String(t||"").toLowerCase().trim().replace(/\s+/g," "),s=String(n||"").toLowerCase().trim();return Ht.createHash("sha1").update(`${o}::${r}::${s}`).digest("hex").slice(0,16)}var $=Object.freeze({decision:"Logging decision: {{summary}} \u2014 reason: {{reason}}. Say 'undo that' if wrong.",issue:"Logging issue ({{severity}}): {{summary}}. Say 'undo that' if wrong.",assumption:"Logging assumption: {{summary}} \u2014 rationale: {{rationale}}. Say 'undo that' if wrong.",task_status:"Marking task {{task_id}} as {{proposed_status}} \u2014 rationale: {{rationale}}. Say 'undo that' if wrong."}),Be="Auto-logging paused \u2014 {{count}} entries logged this session. Type /dezycro:sync to log manually.";function Bt(e){let t=e.thresholds||{},n=Math.max(0,Number(e.perTurnSlotsLeft)||0),o=Math.max(0,Number(e.perSessionSlotsLeft)||0);if(n<=0||o<=0)return Be.replace("{{count}}",o<=0?"session-cap":"turn-cap");let r=Math.min(n,o),s=(e.recentHashes||[]).filter(Boolean),i=["[Dezycro Companion]",`Feature: ${Fe(e.activeFeatureName,e.activeFeatureId)}. Slots: ${r} (${n}/turn, ${o}/session).`,"","Scan since your last message for committed signals to log:",` - Decision (conf \u2265 ${t.decision??.85}) \u2014 committed technical/product choice`,` - Issue (conf \u2265 ${t.issue??.8}) \u2014 current blocker/bug`,` - Assumption (conf \u2265 ${t.assumption??.9}) \u2014 unverified belief affecting impl`,` - Task-status (conf \u2265 ${t.taskStatus??.9}) \u2014 task is now DONE/PUSHED`,"","Skip: hypotheticals, brainstorming, implementation-obvious details, ephemeral content, intent statements while authoring a PRD/TRD."];return s.length>0&&i.push(`Already-logged hashes (skip dupes): ${s.join(", ")}`),i.push("","For each surviving candidate (max "+r+"): print the announce line verbatim and call the matching MCP tool.",' decision: "'+$.decision+'" \u2192 mcp__dezycro(-dev)?__add_decision',' issue: "'+$.issue+'" \u2192 mcp__dezycro(-dev)?__add_issue',' assumption: "'+$.assumption+'" \u2192 mcp__dezycro(-dev)?__add_assumption',' task_status: "'+$.task_status+'" \u2192 mcp__dezycro(-dev)?__update_task',"","If nothing meets the bar, simply continue with whatever the user asked next \u2014 do NOT output any acknowledgment line. The hook will silence itself for trivial turns."),i.join(`
3
+ `)}function Fe(e,t){if(!t)return"(none \u2014 skip if no feature is active)";let n=String(t).slice(0,8);return e?`${e} (${n}\u2026)`:n+"\u2026"}function Ft(e){return typeof e!="string"?null:/add_decision$/.test(e)?"decision":/add_issue$/.test(e)?"issue":/add_assumption$/.test(e)?"assumption":/update_task$/.test(e)?"task-status":null}var jt=Object.freeze(["undo that","no, wrong","revert that","undo the last log","wrong, undo"]);function $t(e){if(typeof e!="string")return!1;let t=e.toLowerCase().trim();if(!t)return!1;for(let n=0;n<jt.length;n+=1)if(t.includes(jt[n]))return!0;return!1}function Vt(e){if(!e||!e.tool||!e.entityId)return null;let t=e.entityId;switch(e.tool){case"add_decision":return{tool:"update_decision",args:{id:t,status:"INVALIDATED",reason:"undo by user"},humanLine:`Reverting the last auto-logged decision (${t.slice(0,8)}\u2026) \u2014 marking INVALIDATED.`};case"add_issue":return{tool:"update_issue",args:{id:t,status:"CANCELLED",reason:"undo by user"},humanLine:`Reverting the last auto-logged issue (${t.slice(0,8)}\u2026) \u2014 marking CANCELLED.`};case"add_assumption":return{tool:"update_issue",args:{id:t,status:"INVALIDATED",kind:"ASSUMPTION",reason:"undo by user"},humanLine:`Reverting the last auto-logged assumption (${t.slice(0,8)}\u2026) \u2014 marking INVALIDATED.`};case"update_task":return e.priorStatus?{tool:"update_task",args:{id:t,status:e.priorStatus},humanLine:`Reverting the last auto-task-status change \u2014 restoring ${t.slice(0,8)}\u2026 to ${e.priorStatus}.`}:null;default:return null}}function Gt(e,t){return!e||typeof e.createdInTurnId!="number"?!1:t===e.createdInTurnId+1}function et(e,t){return`${e} ${t}${e===1?"":"s"}`}function nt(e){return!e||typeof e!="object"?null:{uncoveredPaths:Number(e.uncoveredPaths??0)||0,endpointsNotInSpec:Number(e.endpointsNotInSpec??0)||0,staleBaselines:Number(e.staleBaselines??0)||0}}function V(e){let t=nt(e);if(!t)return null;let n=[];return t.uncoveredPaths>0&&n.push(`${et(t.uncoveredPaths,"path")} uncovered`),t.endpointsNotInSpec>0&&n.push(`${et(t.endpointsNotInSpec,"endpoint")} not in spec`),t.staleBaselines>0&&n.push(`${et(t.staleBaselines,"baseline")} stale`),n.length===0?null:`Coverage: ${n.join(", ")}`}function Jt(e,t){let n=nt(e),o=nt(t);if(!o)return null;if(!n)return V(t);let s=[["paths uncovered",o.uncoveredPaths-n.uncoveredPaths],["endpoints not in spec",o.endpointsNotInSpec-n.endpointsNotInSpec],["baselines stale",o.staleBaselines-n.staleBaselines]].filter(([,a])=>a!==0);return s.length===0?null:`Coverage delta since last verify: ${s.map(([a,u])=>`${u>0?"+":""}${u} ${a}`).join(", ")}`}var N={HaltAndReplan:"HALT_AND_REPLAN",AcknowledgeAndContinue:"ACKNOWLEDGE_AND_CONTINUE",SilentLog:"SILENT_LOG"};var J=S(require("fs")),zt=S(require("os")),w=S(require("path")),G=class e{constructor(t){this.repoRoot=t;this.config=e.readJson(w.join(t,".dezycro","config.json"))}repoRoot;config;static at(t=process.cwd()){return new e(e.findRepoRoot(t)??w.resolve(t))}get workspaceId(){return e.env("DZ_WORKSPACE_ID")??e.str(this.config?.workspaceId)}get tenantId(){return e.env("DZ_TENANT_ID")??e.str(this.config?.tenantId)}get projectId(){return e.str(this.config?.projectId)}get apiUrl(){let t=e.env("DZ_API_URL");if(t)return e.trimSlash(t);let n=Array.isArray(this.config?.environments)?this.config?.environments:[],o=n.find(s=>e.isObj(s)&&s.default===!0)??n[0],r=e.isObj(o)?e.str(o.apiUrl):null;return r?e.trimSlash(r):null}get token(){let t=e.env("DZ_TOKEN");if(t)return t;let n=[w.join(this.repoRoot,".dezycro","companion-token.local.json"),w.join(zt.homedir(),".dezycro","token.json")];for(let o of n){let r=e.str(e.readJson(o)?.token);if(r)return r}return null}activeFeature(){let t=e.readJson(w.join(this.repoRoot,".dezycro","active-feature.json")),n=e.str(t?.featureId);if(!n)return null;let o=e.str(t?.workspaceId)??this.workspaceId;return o?{workspaceId:o,featureId:n}:null}connection(){let t=this.apiUrl;if(!t)return{error:"no apiUrl (set DZ_API_URL or .dezycro/config.json environments[].apiUrl)"};let n=this.workspaceId;if(!n)return{error:"no workspaceId (set DZ_WORKSPACE_ID or .dezycro/config.json workspaceId)"};let o=this.token;return o?{apiUrl:t,workspaceId:n,token:o}:{error:"no token (run `dezycro setup` or set DZ_TOKEN)"}}static findRepoRoot(t){let n=w.resolve(t||process.cwd());for(let o=0;o<64;o+=1){if(J.existsSync(w.join(n,".dezycro")))return n;let r=w.dirname(n);if(r===n)return null;n=r}return null}static readJson(t){try{return JSON.parse(J.readFileSync(t,"utf8"))}catch{return null}}static isObj(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}static str(t){return typeof t=="string"&&t.length>0?t:null}static env(t){let n=process.env[t];return n&&n.length>0?n:null}static trimSlash(t){return t.replace(/\/$/,"")}};var Ge=["sessionStart","userPromptSubmit","stop","postToolUse"],Je=60,ze=N.HaltAndReplan,Wt=200,We=100,qe=3,Ke=1800,ot=class e{async pollIfDue(t,n,o,r){let s=this.resolveConfig(o),i=s.reactionMode,a={events:[],statePatch:null,reactionMode:i};if(!s.enabled||!s.hooks.has(n)&&n!=="sessionStart")return a;let u=r.commandBus,c=u.lastAttemptTs??u.lastPollTs;if(n!=="sessionStart"&&c){let p=Date.parse(c);if(!Number.isNaN(p)){let C=e.backoffSeconds(s.minPollIntervalSeconds,u.consecutiveFailures??0,s.circuitBreakerThreshold,s.maxBackoffSeconds);if((Date.now()-p)/1e3<C)return a}}let l=new G(t),f=l.activeFeature();if(!f)return a;let h=l.apiUrl;if(!h)return a;let v=l.token;if(!v)return g(t,"command_bus_skip_no_token",{hookEvent:n}),a;let y=n==="sessionStart"?null:u.cursor,P=new Date().toISOString();try{let p=await this.fetchInbox(h,f,v,y),C=new Set(u.recentEventIds??[]),T=p.events.filter(E=>!C.has(E.eventId)),_=this.trimRecent([...u.recentEventIds??[],...T.map(E=>E.eventId)]),q={commandBus:{cursor:p.nextCursor||u.cursor,lastPollTs:p.serverTs,lastAttemptTs:P,consecutiveFailures:0,recentEventIds:_}};return T.length>0&&g(t,"command_bus_events_received",{hookEvent:n,count:T.length,types:T.map(E=>E.eventType)}),{events:T,statePatch:q,reactionMode:i}}catch(p){let C=(u.consecutiveFailures??0)+1,T={commandBus:{...u,lastAttemptTs:P,consecutiveFailures:C}},_=e.backoffSeconds(s.minPollIntervalSeconds,C,s.circuitBreakerThreshold,s.maxBackoffSeconds);return g(t,"command_bus_poll_failed",{hookEvent:n,error:p instanceof Error?p.message:String(p),consecutiveFailures:C,nextPollAfterSeconds:_,backoff:C>=s.circuitBreakerThreshold}),{events:[],statePatch:T,reactionMode:i}}}static backoffSeconds(t,n,o,r){if(n<o)return t;let s=n-o+1;return Math.min(t*Math.pow(2,s),r)}resolveConfig(t){let n=t?.enabled!==!1,o=new Set(t?.pollHooks??Ge);o.add("sessionStart");let r=Math.max(0,t?.minPollIntervalSeconds??Je),s=t?.reactionMode??ze,i=Math.max(1,t?.circuitBreakerThreshold??qe),a=Math.max(r,t?.maxBackoffSeconds??Ke);return{enabled:n,hooks:o,minPollIntervalSeconds:r,reactionMode:s,circuitBreakerThreshold:i,maxBackoffSeconds:a}}async fetchInbox(t,n,o,r){let s=new URL(`${t}/api/v1/workspaces/${n.workspaceId}/features/${n.featureId}/inbox`);r&&s.searchParams.set("since",r),s.searchParams.set("limit",String(We));let i=new AbortController,a=setTimeout(()=>i.abort(),5e3);try{let u=await fetch(s.toString(),{method:"GET",headers:{Authorization:`Bearer ${o}`,Accept:"application/json"},signal:i.signal});if(!u.ok)throw new Error(`inbox poll returned ${u.status}`);let c=await u.json();if(!c||typeof c.serverTs!="string"||typeof c.nextCursor!="string")throw new Error("inbox poll response missing serverTs/nextCursor");return{serverTs:c.serverTs,nextCursor:c.nextCursor,events:Array.isArray(c.events)?c.events:[]}}finally{clearTimeout(a)}}trimRecent(t){return t.length<=Wt?t:t.slice(t.length-Wt)}},rt=class{renderForAgent(t,n){if(t.length===0)return"";let o=[`\u26A0\uFE0F Dezycro Command Bus: ${t.length} new event(s) on this feature.`,""];for(let r of t)o.push(this.renderEvent(r));return t.some(r=>r.urgency==="BLOCKING")&&o.push("",this.reactionGuidance(n)),o.join(`
4
+ `)}renderEvent(t){if(t.eventType==="INVALIDATION"){let r=this.stringField(t.payload,"artifactSummary")??"(no summary)",s=this.stringField(t.payload,"reason")??"(no reason)",i=this.stringField(t.payload,"previousStatus")??"?",a=`${t.sourceType.toLowerCase()} ${t.sourceId??"?"}`;return`- INVALIDATION (${t.urgency}): ${a} ("${this.truncate(r,120)}") \u2014 reason: "${this.truncate(s,200)}" \u2014 was ${i}.`}let n=this.summarizePayload(t.payload),o=`${t.sourceType.toLowerCase()}${t.sourceId?` ${t.sourceId}`:""}`;return`- [Dezycro] ${t.eventType} (${t.urgency}) from ${o}${n?`: ${n}`:""}.`}summarizePayload(t){let n=[];for(let[o,r]of Object.entries(t??{}))r!=null&&(Array.isArray(r)?n.push(`${o}=${r.join("|")}`):typeof r!="object"&&n.push(`${o}=${String(r)}`));return this.truncate(n.join(", "),240)}reactionGuidance(t){switch(t){case N.HaltAndReplan:return"Reaction mode: HALT_AND_REPLAN \u2014 pause your current line of work, acknowledge in chat, and re-plan around these invalidations before touching code again.";case N.AcknowledgeAndContinue:return"Reaction mode: ACKNOWLEDGE_AND_CONTINUE \u2014 surface this in your reply but continue current work; do not silently reuse invalidated artifacts.";case N.SilentLog:return"Reaction mode: SILENT_LOG \u2014 recorded for the session transcript; no chat interruption.";default:return""}}stringField(t,n){let o=t?.[n];return typeof o=="string"?o:null}truncate(t,n){return t.length<=n?t:t.slice(0,n-1)+"\u2026"}},L=new ot,z=new rt;var Ye=new Set(["DONE","PUSHED"]),Qe=["/dezycro:sync","log what we did","log this","save progress","save what we did","wrap up","we're done","we are done","end of session","sweep the workbook"];function Ze(e){if(typeof e!="string")return null;let t=e.toLowerCase().trim();if(!t)return null;for(let n of Qe)if(t.includes(n))return n;return null}var Kt="TRD quality gate (deterministic layer) blocked APPROVED transition: ";async function tn(e){let{event:t,route:n,payload:o,flags:r}=e;return t==="state"?on(r||{}):t==="authoring-state"?rn(r||{}):t==="pre-tool-use"&&n==="update_task"?Xt(o||{}):t==="pre-tool-use"&&n==="change_document_status"?nn(o||{}):t==="post-tool-use"&&n==="edit"?Yt(o||{}):t==="post-tool-use"&&n==="workbook_mutation"?re(o||{}):t==="session-start"?Zt(o||{}):t==="user-prompt-submit"?te(o||{}):t==="stop"?ee(o||{}):0}function Xt(e){let t=I(process.cwd());if(!t)return process.stdout.write("{}"),0;let n=e&&e.tool_input||{},o=String(n.status||"").toUpperCase();if(!Ye.has(o))return process.stdout.write("{}"),0;let r=n.pathRefs,s=Array.isArray(r)?r.filter(Boolean):[];if(s.length===0)return process.stdout.write("{}"),0;let i=x(t);if((i&&i.companion&&i.companion.autoVerify||{}).preTaskDone===!1)return process.stdout.write("{}"),0;if(kt({repoRoot:t,paths:s})){if(g(t,"pre_done_gate_pass",{status:o,pathRefs:s}),o==="PUSHED"){let f=en(t,i);if(f){g(t,"pre_push_coverage_nudge",{line:f});let h={systemMessage:f};return process.stdout.write(JSON.stringify(h)),0}}return process.stdout.write("{}"),0}R(t,"verifyAutoRuns"),R(t,"verifyAutoFailures"),F(t,"pre_done_gate_block",{status:o,pathRefs:s});let c=bt({paths:s,status:o}).reason,l={decision:"block",reason:c,hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:c}};return process.stdout.write(JSON.stringify(l)),0}function en(e,t){if((t&&t.companion&&t.companion.coverageNudges||{}).enabled===!1)return null;let o=k(e).coverageSnapshot,r=V(o);return r?`[Companion] ${r} \u2014 verify passed, but consider checking these before push.`:null}function nn(e){let n=e&&e.tool_input||{},o=n.status||n.newStatus||null,r=n.docId||n.documentId||n.id||null;if(o!=="APPROVED")return process.stdout.write("{}"),0;let s=I(process.cwd());if(!s)return process.stdout.write("{}"),0;let i=Dt(s);if(!i||r&&i.docId&&i.docId!==r)return F(s,"quality_gate_degraded_permit",{reason:i?"docId_mismatch":"sidecar_missing",docId:r,sidecarDocId:i?i.docId:null}),process.stdout.write("{}"),0;if(i.docType!=="TRD")return process.stdout.write("{}"),0;let a=Mt({trdContent:i.content,prdContent:i.prdContent||""});if(a.passed)return g(s,"quality_gate_deterministic_pass",{docId:i.docId}),process.stdout.write("{}"),0;R(s,"qualityGateFailures");let u=a.blockingIssues.map(f=>`[${f.section}] ${f.issue}`).slice(0,5).join(" | "),c=`${Kt}${u||"unspecified failure"}. Fix and try again.`;F(s,"quality_gate_blocked",{docId:i.docId,issues:a.blockingIssues});let l={decision:"block",reason:c,hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:c}};return process.stdout.write(JSON.stringify(l)),0}async function Yt(e){let t=I(process.cwd());if(!t)return 0;{let y=x(t),P=k(t),p=await L.pollIfDue(t,"postToolUse",y?.companion?.commandBus,P);p.statePatch&&d(t,p.statePatch);let C=z.renderForAgent(p.events,p.reactionMode);if(C){let T={hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:C}};return process.stdout.write(JSON.stringify(T)),0}}let n=e&&e.tool_input||{},o=Qt(n);if(o.length===0)return 0;let r=x(t),s=r&&r.companion&&r.companion.autoVerify||{},i=Array.isArray(s.controllerPaths)?s.controllerPaths:[],a=s.postEditPulse&&s.postEditPulse.enabled!==!1,u=s.postEditPulse&&Number(s.postEditPulse.threshold)||5,c=wt(o,i),l=new Date().toISOString(),h=(k(t).pulseCount||0)+1,v=a&&h>=u&&c.length>0;if(c.length===0)d(t,{pulseCount:h,lastEditTs:l});else for(let y=0;y<c.length;y+=1){let P=y===c.length-1,p={pushControllerEdit:{path:c[y],editedTs:l}};P&&(p.needsSpecPublish=!0,p.lastEditTs=l,p.pulseCount=v?0:h),d(t,p)}if(g(t,"post_edit",{edited:o.length,matchedControllers:c.length,pulseCount:v?0:h,nudged:v}),v){let y="[Companion] "+h+" edits since last verify and controller paths were touched ("+c.join(", ")+"). Consider running `/dezycro:verify` to catch regressions early.";process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:y}}))}return 0}function Qt(e){if(!e||typeof e!="object")return[];let t=e.file_path;if(typeof t=="string")return[t];let n=e.path;if(typeof n=="string")return[n];let o=e.edits;if(Array.isArray(o)){let r=new Set;for(let s of o)s&&typeof s.file_path=="string"&&r.add(s.file_path);return Array.from(r)}return[]}function on(e){let t=I(process.cwd())||process.cwd();if(e.get){let n=k(t);return process.stdout.write(JSON.stringify(n,null,2)),0}if(typeof e.patch=="string"){let n;try{n=JSON.parse(e.patch)}catch(r){let s=r.message;return process.stdout.write(JSON.stringify({ok:!1,error:"invalid JSON for --patch: "+s})),1}return n===null||typeof n!="object"||Array.isArray(n)?(process.stdout.write(JSON.stringify({ok:!1,error:"--patch must be a JSON object"})),1):d(t,n)===null?(process.stdout.write(JSON.stringify({ok:!1,error:"lock contention \u2014 state not patched"})),1):(process.stdout.write(JSON.stringify({ok:!0})),0)}return process.stdout.write(JSON.stringify({ok:!1,error:"state requires one of --get or --patch=<json>"})),1}function rn(e){let t=I(process.cwd())||process.cwd(),n=e.set||(e.get?"get":null);if(n==="enter"){let o=e["doc-id"],r=e["doc-type"];if(!o||!r)return process.stdout.write(JSON.stringify({ok:!1,error:"--doc-id and --doc-type are required for --set=enter"})),1;try{let s=Rt(t,{docId:o,docType:r,featureId:e["feature-id"]||null,seed:e.seed||null});return process.stdout.write(JSON.stringify({ok:!0,transcript:s})),0}catch(s){return process.stdout.write(JSON.stringify({ok:!1,error:s.message})),1}}if(n==="exit")try{return Et(t),process.stdout.write(JSON.stringify({ok:!0})),0}catch(o){return process.stdout.write(JSON.stringify({ok:!1,error:o.message})),1}if(n==="get"){let o=Ot(t);return process.stdout.write(JSON.stringify({ok:!0,...o})),0}return process.stdout.write(JSON.stringify({ok:!1,error:"authoring-state requires one of --set=enter, --set=exit, --get"})),1}var sn=600;async function Zt(e){let t=I(process.cwd());if(!t)return 0;d(t,{sessionAutoLogCount:0,turnAutoLogCount:0,currentTurnId:0,lastAutoWorkbookMutation:null,coverageFetchPending:!1}),g(t,"session_start",{});let n=x(t),o=k(t),r=await L.pollIfDue(t,"sessionStart",n?.companion?.commandBus,o);return r.statePatch&&d(t,r.statePatch),0}async function te(e){let t=I(process.cwd());if(!t)return 0;let n=k(t),o=(n.currentTurnId||0)+1;d(t,{currentTurnId:o,turnAutoLogCount:0});{let i=x(t),a=await L.pollIfDue(t,"userPromptSubmit",i?.companion?.commandBus,n);a.statePatch&&d(t,a.statePatch);let u=z.renderForAgent(a.events,a.reactionMode);if(u){let c={hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:u}};return process.stdout.write(JSON.stringify(c)),0}}let r=String(e?.prompt??e?.user_message??e?.message??"").trim(),s=Ze(r);if(s&&(d(t,{pendingWorkbookSweep:!0,pendingWorkbookSweepReason:"wrap_phrase:"+s}),g(t,"wrap_phrase_detected",{phrase:s})),r&&$t(r)){let i=n.lastAutoWorkbookMutation;if(i&&Gt(i,o)){let a=Vt(i);if(a){R(t,"undoCount"),d(t,{lastAutoWorkbookMutation:null}),g(t,"undo_directive",{tool:a.tool,entityId:i.entityId});let c={hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:"[Dezycro Companion \u2014 undo] "+a.humanLine+`
5
5
 
6
6
  Call `+a.tool+` with arguments:
7
7
  `+JSON.stringify(a.args,null,2)+`
8
8
 
9
- Then confirm the reversal in one short sentence.`}};return process.stdout.write(JSON.stringify(u)),0}}}{let i=dn(t);if(i){f(t,"publish_spec_nudge",{paths:i.count});let a={hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:i.text}};return process.stdout.write(JSON.stringify(a)),0}}return pn(t,n),process.stdout.write("{}"),0}function dn(e){let t=_(e);if((t&&t.companion&&t.companion.autoVerify||{}).autoPublishSpecOnControllerChange===!1)return null;let o=St(e);if(!o.needed||o.controllerPaths.length===0)return null;let r=8,s=o.controllerPaths,i=s.slice(0,r).map(c=>" - "+c);return s.length>r&&i.push(" - \u2026and "+(s.length-r)+" more"),{text:"[Dezycro Companion] "+s.length+` controller/API file(s) changed since the last published spec:
9
+ Then confirm the reversal in one short sentence.`}};return process.stdout.write(JSON.stringify(c)),0}}}{let i=an(t);if(i){g(t,"publish_spec_nudge",{paths:i.count});let a={hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:i.text}};return process.stdout.write(JSON.stringify(a)),0}}return un(t,n),process.stdout.write("{}"),0}function an(e){let t=x(e);if((t&&t.companion&&t.companion.autoVerify||{}).autoPublishSpecOnControllerChange===!1)return null;let o=Tt(e);if(!o.needed||o.controllerPaths.length===0)return null;let r=8,s=o.controllerPaths,i=s.slice(0,r).map(u=>" - "+u);return s.length>r&&i.push(" - \u2026and "+(s.length-r)+" more"),{text:"[Dezycro Companion] "+s.length+` controller/API file(s) changed since the last published spec:
10
10
  `+i.join(`
11
- `)+"\n\nNew or changed endpoints are NOT yet reflected in the published OpenAPI spec, so verification cannot see them. Before continuing, run `/dezycro:publish-spec` to upload the updated spec (this regenerates the JEP), then `/dezycro:verify` to check the feature against it. This reminder repeats each turn until the spec is published and clears automatically after `/dezycro:publish-spec`.",count:s.length}}function pn(e,t){if(_(e)?.companion?.coverageNudges?.enabled===!1)return;let o=t.coverageSnapshot;if(!o||o.surfacedTs)return;let r=$(o);if(!r)return;d(e,{coverageSnapshot:{...o,surfacedTs:new Date().toISOString()}}),f(e,"coverage_one_liner",{line:r});let s={hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:"[Companion] "+r}};process.stdout.write(JSON.stringify(s))}async function te(e){let t=A(process.cwd());if(!t)return 0;let n=_(t);{let w=k(t),C=await D(t,"stop",n?.companion?.commandBus,w);C.statePatch&&d(t,C.statePatch);let L=z(C.events,C.reactionMode);if(L){let P={systemMessage:L};return process.stdout.write(JSON.stringify(P)),0}}let o=n?.companion?.autoWorkbookUpdates||{};if(n?.companion?.safeMode===!0||o.enabled===!1)return nt();let r=k(t),s=!!(r.lastVerifyCompletionTs&&r.lastVerifyCompletionTs!==r.lastSeenVerifyCompletionTs);if(!!!(r.pendingWorkbookSweep||s))return f(t,"stop_skip",{reason:"no_trigger"}),s&&d(t,{lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs}),G(t,r);if(r.authoringMode)return f(t,"stop_skip",{reason:"authoring_mode"}),d(t,{pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs||r.lastSeenVerifyCompletionTs}),G(t,r);let a=Number(o.maxAutoLogsPerTurn??2),c=Number(o.maxAutoLogsPerSession??10),u=Math.max(0,a-(r.turnAutoLogCount||0)),l=Math.max(0,c-(r.sessionAutoLogCount||0));if(u===0||l===0)return f(t,"stop_skip",{reason:"caps_exhausted",perTurnSlotsLeft:u,perSessionSlotsLeft:l}),d(t,{pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs||r.lastSeenVerifyCompletionTs}),G(t,r);if(r.suppressWorkbookUpdatesUntil&&Date.now()<new Date(r.suppressWorkbookUpdatesUntil).getTime())return f(t,"stop_skip",{reason:"suppressed"}),d(t,{pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs||r.lastSeenVerifyCompletionTs}),G(t,r);d(t,{pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs||r.lastSeenVerifyCompletionTs});let p=at(n),y=[...r.recentDecisionHashes||[],...r.recentIssueHashes||[],...r.recentAssumptionHashes||[]],v=ne(t),m=Mt({thresholds:p,perTurnSlotsLeft:u,perSessionSlotsLeft:l,recentHashes:y,activeFeatureId:v.featureId,activeFeatureName:v.featureName});f(t,"stop_sweep_directive",{perTurnSlotsLeft:u,perSessionSlotsLeft:l,recentHashCount:y.length});let S=ee(t,r);S&&(m+=`
11
+ `)+"\n\nNew or changed endpoints are NOT yet reflected in the published OpenAPI spec, so verification cannot see them. Before continuing, run `/dezycro:publish-spec` to upload the updated spec (this regenerates the JEP), then `/dezycro:verify` to check the feature against it. This reminder repeats each turn until the spec is published and clears automatically after `/dezycro:publish-spec`.",count:s.length}}function un(e,t){if(x(e)?.companion?.coverageNudges?.enabled===!1)return;let o=t.coverageSnapshot;if(!o||o.surfacedTs)return;let r=V(o);if(!r)return;d(e,{coverageSnapshot:{...o,surfacedTs:new Date().toISOString()}}),g(e,"coverage_one_liner",{line:r});let s={hookSpecificOutput:{hookEventName:"UserPromptSubmit",additionalContext:"[Companion] "+r}};process.stdout.write(JSON.stringify(s))}async function ee(e){let t=I(process.cwd());if(!t)return 0;let n=x(t);{let C=k(t),T=await L.pollIfDue(t,"stop",n?.companion?.commandBus,C);T.statePatch&&d(t,T.statePatch);let _=z.renderForAgent(T.events,T.reactionMode);if(_){let q={systemMessage:_};return process.stdout.write(JSON.stringify(q)),0}}let o=n?.companion?.autoWorkbookUpdates||{};if(n?.companion?.safeMode===!0||o.enabled===!1)return st();let r=k(t),s=!!(r.lastVerifyCompletionTs&&r.lastVerifyCompletionTs!==r.lastSeenVerifyCompletionTs);if(!!!(r.pendingWorkbookSweep||s))return g(t,"stop_skip",{reason:"no_trigger"}),s&&d(t,{lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs}),W(t,r);if(r.authoringMode)return g(t,"stop_skip",{reason:"authoring_mode"}),d(t,{pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs||r.lastSeenVerifyCompletionTs}),W(t,r);let a=Number(o.maxAutoLogsPerTurn??2),u=Number(o.maxAutoLogsPerSession??10),c=Math.max(0,a-(r.turnAutoLogCount||0)),l=Math.max(0,u-(r.sessionAutoLogCount||0));if(c===0||l===0)return g(t,"stop_skip",{reason:"caps_exhausted",perTurnSlotsLeft:c,perSessionSlotsLeft:l}),d(t,{pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs||r.lastSeenVerifyCompletionTs}),W(t,r);if(r.suppressWorkbookUpdatesUntil&&Date.now()<new Date(r.suppressWorkbookUpdatesUntil).getTime())return g(t,"stop_skip",{reason:"suppressed"}),d(t,{pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs||r.lastSeenVerifyCompletionTs}),W(t,r);d(t,{pendingWorkbookSweep:!1,pendingWorkbookSweepReason:null,lastSeenVerifyCompletionTs:r.lastVerifyCompletionTs||r.lastSeenVerifyCompletionTs});let f=lt(n),h=[...r.recentDecisionHashes||[],...r.recentIssueHashes||[],...r.recentAssumptionHashes||[]],v=oe(t),y=Bt({thresholds:f,perTurnSlotsLeft:c,perSessionSlotsLeft:l,recentHashes:h,activeFeatureId:v.featureId,activeFeatureName:v.featureName});g(t,"stop_sweep_directive",{perTurnSlotsLeft:c,perSessionSlotsLeft:l,recentHashCount:h.length});let P=ne(t,r);P&&(y+=`
12
12
 
13
- `+S);let g={decision:"block",reason:m};return process.stdout.write(JSON.stringify(g)),0}function G(e,t){let n=ee(e,t);if(!n)return nt();f(e,"stop_coverage_delta",{delta:n});let o={systemMessage:n};return process.stdout.write(JSON.stringify(o)),0}function ee(e,t){let n=t.lastVerifyCompletionTs,o=t.coverageSnapshot;if(!n||!o)return null;let r=o.surfacedTs?new Date(o.surfacedTs).getTime():0;if(new Date(n).getTime()<=r)return null;let i=$t(o.previous||null,o);return i?(d(e,{coverageSnapshot:{...o,surfacedTs:new Date().toISOString()}}),"[Companion] "+i):null}function nt(){return process.stdout.write("{}"),0}function fn(e){try{let t=e?.transcript_path;if(!t||typeof t!="string"||!N.existsSync(t))return null;let o=N.readFileSync(t,"utf8").split(`
14
- `).filter(Boolean),r=0,s=!1;for(let i=o.length-1;i>=0;i-=1){let a;try{a=JSON.parse(o[i])}catch{continue}let c=a?.message?.role??a?.role;if(c==="assistant"){let u=JSON.stringify(a.message?.content??a.content??"");r+=u.length}else if(c==="user"){if(s)break;s=!0;let u=JSON.stringify(a.message?.content??a.content??"");r+=u.length}if(r>1e6)break}return r}catch{return null}}function gn(e){return ne(e).featureId}function ne(e){try{let t=N.readFileSync(Wt.join(e,".dezycro","active-feature.json"),"utf8"),n=JSON.parse(t);return{featureId:n?.featureId||null,featureName:n?.featureName||null}}catch{return{featureId:null,featureName:null}}}function _(e){try{return it(e)}catch{return JSON.parse(JSON.stringify(R))}}function oe(e){let t=A(process.cwd());if(!t)return 0;let n=e?.tool_name||"",o=Ut(n);if(!o)return 0;let r=e?.tool_input||{},s=e?.tool_response||e?.response||{},i=String(r.summary||r.title||r.description||r.statement||""),a=r.taskId||r.linkedTaskId||null,c=Lt(o,i,a),u=s.data,l=s.id||(u?u.id:void 0)||r.taskId||null,p=k(t),y=(p.turnAutoLogCount||0)+1,v=(p.sessionAutoLogCount||0)+1,m={turnAutoLogCount:y,sessionAutoLogCount:v,lastAutoWorkbookMutation:{tool:n.split("__").pop()||"",entityId:l,createdInTurnId:p.currentTurnId||0,createdTs:new Date().toISOString(),priorStatus:r.priorStatus||null}};return o==="decision"&&(m.pushDecisionHash=c),o==="issue"&&(m.pushIssueHash=c),o==="assumption"&&(m.pushAssumptionHash=c),d(t,m),x(t,o==="decision"?"autoDecisionLogs":o==="issue"?"autoIssueLogs":o==="assumption"?"autoAssumptionLogs":"autoTaskStatusLogs"),f(t,"workbook_mutation",{kind:o,entityId:l,turnAutoLogCount:y,sessionAutoLogCount:v}),process.stdout.write("{}"),0}var mn=Yt,hn=Xt,yn=Kt,Sn=te,Tn=Qt,kn=oe,bn=Zt,wn=gn,vn=fn,In=ln;0&&(module.exports={QUALITY_GATE_REASON_PREFIX,TRIVIAL_TURN_CHAR_DEFAULT_EXPORT,_extractEditedPaths,_handlePostEdit,_handleSessionStart,_handleStop,_handleUpdateTaskGate,_handleUserPromptSubmit,_handleWorkbookMutation,_readActiveFeatureId,_transcriptCharsSinceLastStop,dispatch});
13
+ `+P);let p={decision:"block",reason:y};return process.stdout.write(JSON.stringify(p)),0}function W(e,t){let n=ne(e,t);if(!n)return st();g(e,"stop_coverage_delta",{delta:n});let o={systemMessage:n};return process.stdout.write(JSON.stringify(o)),0}function ne(e,t){let n=t.lastVerifyCompletionTs,o=t.coverageSnapshot;if(!n||!o)return null;let r=o.surfacedTs?new Date(o.surfacedTs).getTime():0;if(new Date(n).getTime()<=r)return null;let i=Jt(o.previous||null,o);return i?(d(e,{coverageSnapshot:{...o,surfacedTs:new Date().toISOString()}}),"[Companion] "+i):null}function st(){return process.stdout.write("{}"),0}function cn(e){try{let t=e?.transcript_path;if(!t||typeof t!="string"||!M.existsSync(t))return null;let o=M.readFileSync(t,"utf8").split(`
14
+ `).filter(Boolean),r=0,s=!1;for(let i=o.length-1;i>=0;i-=1){let a;try{a=JSON.parse(o[i])}catch{continue}let u=a?.message?.role??a?.role;if(u==="assistant"){let c=JSON.stringify(a.message?.content??a.content??"");r+=c.length}else if(u==="user"){if(s)break;s=!0;let c=JSON.stringify(a.message?.content??a.content??"");r+=c.length}if(r>1e6)break}return r}catch{return null}}function ln(e){return oe(e).featureId}function oe(e){try{let t=M.readFileSync(qt.join(e,".dezycro","active-feature.json"),"utf8"),n=JSON.parse(t);return{featureId:n?.featureId||null,featureName:n?.featureName||null}}catch{return{featureId:null,featureName:null}}}function x(e){try{return ct(e)}catch{return JSON.parse(JSON.stringify(O))}}function re(e){let t=I(process.cwd());if(!t)return 0;let n=e?.tool_name||"",o=Ft(n);if(!o)return 0;let r=e?.tool_input||{},s=e?.tool_response||e?.response||{},i=String(r.summary||r.title||r.description||r.statement||""),a=r.taskId||r.linkedTaskId||null,u=Ut(o,i,a),c=s.data,l=s.id||(c?c.id:void 0)||r.taskId||null,f=k(t),h=(f.turnAutoLogCount||0)+1,v=(f.sessionAutoLogCount||0)+1,y={turnAutoLogCount:h,sessionAutoLogCount:v,lastAutoWorkbookMutation:{tool:n.split("__").pop()||"",entityId:l,createdInTurnId:f.currentTurnId||0,createdTs:new Date().toISOString(),priorStatus:r.priorStatus||null}};return o==="decision"&&(y.pushDecisionHash=u),o==="issue"&&(y.pushIssueHash=u),o==="assumption"&&(y.pushAssumptionHash=u),d(t,y),R(t,o==="decision"?"autoDecisionLogs":o==="issue"?"autoIssueLogs":o==="assumption"?"autoAssumptionLogs":"autoTaskStatusLogs"),g(t,"workbook_mutation",{kind:o,entityId:l,turnAutoLogCount:h,sessionAutoLogCount:v}),process.stdout.write("{}"),0}var dn=Qt,pn=Yt,fn=Xt,gn=ee,mn=te,hn=re,yn=Zt,Sn=ln,kn=cn,bn=sn;0&&(module.exports={QUALITY_GATE_REASON_PREFIX,TRIVIAL_TURN_CHAR_DEFAULT_EXPORT,_extractEditedPaths,_handlePostEdit,_handleSessionStart,_handleStop,_handleUpdateTaskGate,_handleUserPromptSubmit,_handleWorkbookMutation,_readActiveFeatureId,_transcriptCharsSinceLastStop,dispatch});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dezycro-ai/agent-plugin",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "Official Dezycro plugin for AI coding agents (Claude Code today, more to come) — reverse-engineer your codebase into features, PRDs, TRDs, and live verification.",
5
5
  "bin": {
6
6
  "dezycro": "./dist/cli/dezycro.js"
@@ -90,21 +90,23 @@ If no `setup` command, skip this step. If there's a `healthCheck` but no `setup`
90
90
 
91
91
  2. Call `pull_verifier(featureId, platform)` via MCP (using the `pull_verifier` tool with `featureId` and `platform` parameters).
92
92
 
93
- 3. If the tool returns an error indicating no binary exists:
94
- - Check generation status by calling `generation_status(workspaceId, featureId)` via MCP.
95
- - If generation is **in progress** (status is not IDLE/COMPLETE/FAILED):
96
- - Tell the user: "JEP generation in progress — waiting for binary..."
97
- - Poll `generation_status` every 15 seconds, up to 20 times (5 minutes).
98
- - Show a brief status update every poll: "Still generating... (<status>)"
99
- - Once status is COMPLETE, retry `pull_verifier`.
100
- - If status is FAILED or timeout reached, tell the user:
101
- > JEP generation failed or timed out. Check the generation logs or run `/dezycro:publish-spec` to retry.
102
- - Then stop.
103
- - If generation is **IDLE** (never started):
104
- - Tell the user:
105
- > No verifier binary available. The feature needs an API spec first.
106
- > Run `/dezycro:publish-spec` to upload your spec and trigger JEP generation.
107
- - Then stop.
93
+ 3. If the tool returns an error indicating no binary exists, the verifier is still generating or compiling. Don't busy-poll — block on the *pushed* event with the bundled generic CLI, filtered to the verifier event type. It server-side long-polls `/inbox/wait`, prints the first matching event as JSON the moment it lands, and exits 0 (event) / 5 (timeout) / 2 (error). It reads the token/workspace/active-feature from `.dezycro/` itself:
94
+
95
+ ```bash
96
+ dezycro await-event --event-types VERIFIER_STATUS_UPDATE --feature "$FEATURE" --timeout 600
97
+ echo "exit=$?"
98
+ ```
99
+
100
+ Act on the exit code, then (on 0) on the event's `payload`:
101
+
102
+ - **exit 5 (TIMEOUT)**: no event within the budget. Do one final direct `pull_verifier`; if it still returns no binary, tell the user verification did not run and to check the generation pipeline. Do NOT claim verification ran.
103
+ - **exit 2 (ERROR / not configured)**: couldn't reach the endpoint, or no feature is bound. Show the line; fall back to a single `pull_verifier` retry before giving up.
104
+ - **exit 0**: an event was printed as JSON. Read its `payload` and act:
105
+ - **`payload.status` = `READY`**: the binary is ready. Re-run `pull_verifier(featureId, platform)` and continue to Step 4.4.
106
+ - **`payload.status` = `EMPTY`, or `payload.stage` = `JEP_GENERATION`**: generation produced no executable checks (the journeys aren't checkable API outcomes). STOP. Quote `payload.message`/`payload.reasonCode`, tell the user to fix the spec, and re-run `/dezycro:publish-spec`. Do NOT claim verification ran.
107
+ - **`payload.status` = `FAILED`** (typically `payload.stage` = `COMPILE`): the verifier build failed. STOP. Quote the message and offer to retry via the `retry_verifier_build` MCP tool, then re-run this wait. Do NOT claim verification ran.
108
+
109
+ (If the agent is doing other work instead of waiting here, it doesn't need this command — the Dezycro companion injects the same event as a background nudge when it lands; read its `payload` the same way.)
108
110
 
109
111
  4. From the response, extract `downloadUrl`, `contentHash`, and any CLI usage hints.
110
112