@devflow-tools/cli 0.17.1 → 0.17.3
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.
- package/dist/plugin-files/.claude-plugin/plugin.json +1 -1
- package/dist/plugin-files/dist/command-registry.json +5 -5
- package/dist/plugin-files/dist/hooks/hook-daemon.js +25 -25
- package/dist/plugin-files/dist/hooks/memory-snapshot-cache.js +1 -1
- package/dist/plugin-files/dist/hooks/post-tool-use-failure.js +2 -2
- package/dist/plugin-files/dist/hooks/post-tool-use.js +6 -5
- package/dist/plugin-files/dist/hooks/pre-tool-use.js +4 -3
- package/dist/plugin-files/dist/hooks/session-end.js +6 -6
- package/dist/plugin-files/dist/hooks/stop.js +9 -9
- package/dist/plugin-files/dist/hooks/user-prompt-submit.js +9 -14
- package/dist/plugin-files/hooks/session-start +13 -0
- package/dist/plugin-files/package.json +10 -10
- package/package.json +26 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {createHash,randomUUID}from'node:crypto';import {readFileSync,openSync,constants,fstatSync,closeSync,writeFileSync,fsyncSync,unlinkSync,lstatSync,mkdirSync,chmodSync,renameSync,rmSync}from'node:fs';import {resolve,join,dirname,isAbsolute,basename}from'node:path';import {getProjectStateDir}from'@devflow-tools/sdk';var S=1,v="memory-snapshot-v1.json",B=512*1024,V=256*1024,q=2e3,ce=500,de=10,ue=240,me=300*1e3,le=720*60*60*1e3,P=2147483647,he=100,X=250,Q=3e4,fe=10,w=new Map;function Z(e){return e.currentUid===void 0?{ownerSafe:true,modeSafe:true}:{ownerSafe:e.ownerUid===e.currentUid,modeSafe:(e.mode&18)===0}}function h(e){return resolve(e)}function p(e){return createHash("sha256").update(h(e)).digest("hex").slice(0,16)}function C(e,t={}){let o=p(e),n=t.stateRoot?join(t.stateRoot,o):getProjectStateDir(h(e));return join(n,v)}function b(e,t){let n=(e instanceof Error?e.message:"").replace(/[\r\n\t]+/gu," ").trim().slice(0,160);return n?`${t}:${n}`:t}function L(e,t){return Array.isArray(e)&&e.length<=t&&e.every(o=>typeof o=="string"&&o.length>0&&o.length<=512)}function ye(e){if(!e||typeof e!="object"||Array.isArray(e))return false;let t=e;return typeof t.id=="string"&&t.id.length>0&&t.id.length<=512&&typeof t.kind=="string"&&t.kind.length>0&&t.kind.length<=128&&(t.family===void 0||typeof t.family=="string"&&t.family.length>0&&t.family.length<=256)&&(t.entity===void 0||typeof t.entity=="string"&&t.entity.length>0&&t.entity.length<=256)&&L(t.memoryIds,100)&&(t.status==="withheld"||t.status==="resolved")&&(t.summary===void 0||typeof t.summary=="string"&&t.summary.length<=2e3)}function pe(e){if(!e||typeof e!="object"||Array.isArray(e))return false;let t=e;return typeof t.reason=="string"&&t.reason.length>0&&t.reason.length<=512&&(t.stale===void 0||typeof t.stale=="boolean")}function T(e,t,o){if(!e||typeof e!="object"||Array.isArray(e))return null;let n=e,r=h(t),s=p(r),a=n.generation===void 0?0:n.generation;return n.version!==S||n.projectRoot!==r||n.projectHash!==s||typeof n.markdown!="string"||Buffer.byteLength(n.markdown,"utf8")>V||!L(n.memoryIds,q)||!Array.isArray(n.conflicts)||n.conflicts.length>ce||!n.conflicts.every(ye)||typeof n.generatedAt!="number"||!Number.isFinite(n.generatedAt)||n.generatedAt<0||n.generatedAt>o+me||!Number.isInteger(a)||a<0||a>P||!["ready","pending","degraded","disabled"].includes(String(n.status))||n.degradation!==void 0&&!pe(n.degradation)?null:{...n,generation:a}}function $(e,t,o,n,r=0){let s=h(e);return {version:S,projectRoot:s,projectHash:p(s),markdown:"",memoryIds:[],conflicts:[],generatedAt:n,generation:r,status:t,degradation:{reason:o}}}function l(e,t={}){let o=t.now??Date.now(),n=C(e,t),r;try{r=openSync(n,constants.O_RDONLY|constants.O_NOFOLLOW);let s=fstatSync(r);if(!s.isFile()||s.size<=0||s.size>B)throw new Error("cache_size_invalid");let a=Z({...typeof process.getuid=="function"?{currentUid:process.getuid()}:{},ownerUid:s.uid,mode:s.mode});if(!a.ownerSafe)throw new Error("cache_owner_invalid");if(!a.modeSafe)throw new Error("cache_permissions_unsafe");let c=JSON.parse(readFileSync(r,"utf8")),d=T(c,e,o);if(!d)throw new Error("cache_schema_invalid");return d.status==="ready"&&o-d.generatedAt>le?{snapshot:{...d,status:"degraded",degradation:{reason:"cache_stale",stale:!0}},source:"cache",valid:!0,stale:!0}:{snapshot:d,source:"cache",valid:!0,stale:!1}}catch(s){let c=s.code==="ENOENT";return {snapshot:$(e,c?"pending":"degraded",c?"cache_missing":b(s,"cache_invalid"),o),source:"none",valid:false,stale:false}}finally{if(r!==void 0)try{closeSync(r);}catch{}}}function I(e){if(!Number.isInteger(e)||e<0||e>=P)throw new Error("memory_snapshot_generation_exhausted");return e+1}function ge(e){let t=dirname(e);mkdirSync(t,{recursive:true,mode:448}),chmodSync(t,448);}function D(e){ge(e);let t=`${e}.lock`,o={pid:process.pid,createdAt:Date.now(),token:randomUUID()},n=JSON.stringify(o),r;try{return r=openSync(t,"wx",384),writeFileSync(r,n),fsyncSync(r),{fd:r,path:t,contents:n}}catch(s){if(r!==void 0){try{closeSync(r);}catch{}try{unlinkSync(t);}catch{}}if(s.code==="EEXIST")return null;throw s}}function Se(e){if(!e||typeof e!="object"||Array.isArray(e))return false;let t=e;return Number.isInteger(t.pid)&&Number(t.pid)>0&&typeof t.createdAt=="number"&&Number.isFinite(t.createdAt)&&typeof t.token=="string"&&t.token.length>0}function we(e){try{return process.kill(e,0),!1}catch(t){return t.code==="ESRCH"}}function Me(e){return !e.canonicalCachePath||!e.directoryIsSafe||!e.lockIsRegularFile||!e.metadataValid||!e.contentsUnchanged||!e.ownerDead&&!e.stale?false:e.currentUid!==void 0?e.directoryUid===e.currentUid&&e.lockUid===e.currentUid:true}function be(e){return isAbsolute(e)&&resolve(e)===e&&basename(e)===v&&/^[a-f0-9]{16}$/u.test(basename(dirname(e)))}function ee(e,t){let o=`${e}.lock`;try{let n=lstatSync(dirname(e)),r=lstatSync(o),s=readFileSync(o,"utf8"),a=null;try{let F=JSON.parse(s);Se(F)&&(a=F);}catch{}let c=a?.createdAt??r.mtimeMs,d=Date.now()-c>t,u=a?we(a.pid):!1,m=readFileSync(o,"utf8")===s,i=typeof process.getuid=="function"?process.getuid():void 0,f=Z({...i!==void 0?{currentUid:i}:{},ownerUid:n.uid,mode:n.mode});return Me({canonicalCachePath:be(e),directoryIsSafe:n.isDirectory()&&!n.isSymbolicLink()&&f.modeSafe,lockIsRegularFile:r.isFile()&&!r.isSymbolicLink(),metadataValid:a!==null,ownerDead:u,stale:d,contentsUnchanged:m,...i!==void 0?{currentUid:i}:{},directoryUid:n.uid,lockUid:r.uid})?(unlinkSync(o),!0):!1}catch{return false}}function te(e){try{closeSync(e.fd);}catch{}try{readFileSync(e.path,"utf8")===e.contents&&unlinkSync(e.path);}catch{}}function _e(e,t,o){let n=D(e);if(!n&&ee(e,t.lockStaleMs??Q)&&(n=D(e)),!n)throw new Error("memory_snapshot_cache_lock_busy");try{return o()}finally{te(n);}}function ke(e){return new Promise(t=>setTimeout(t,e))}function R(e,t,o,n){let r=Number.isFinite(e)?Math.floor(e):t;return Math.min(n,Math.max(o,r))}async function Ce(e,t){let o=R(t.lockTimeoutMs,he,0,X),n=R(t.lockRetryMs,fe,1,X),r=R(t.lockStaleMs,Q,0,Number.MAX_SAFE_INTEGER),s=Date.now()+o;for(;;){let a=D(e);if(a)return a;if(ee(e,r))continue;let c=s-Date.now();if(c<=0)throw new Error("memory_snapshot_cache_lock_timeout");await ke(Math.min(n,c));}}async function G(e,t,o){let n=await Ce(e,t);try{return await o()}finally{te(n);}}function N(e,t,o,n){let r=n.now??Date.now(),s=h(e),a={version:S,projectRoot:s,projectHash:p(s),markdown:t.markdown,memoryIds:t.memoryIds??[],conflicts:t.conflicts??[],generatedAt:r,generation:o,status:t.status??"ready",...t.degradation?{degradation:t.degradation}:{}};if(!T(a,e,r))throw new Error("memory_snapshot_payload_invalid");let c=JSON.stringify(a);if(Buffer.byteLength(c,"utf8")>B)throw new Error("memory_snapshot_cache_too_large");let d=C(e,n),u=dirname(d);mkdirSync(u,{recursive:true,mode:448}),chmodSync(u,448);let m=join(u,`.${v}.${process.pid}.${randomUUID()}.tmp`),i;try{i=openSync(m,"wx",384),writeFileSync(i,c),fsyncSync(i),closeSync(i),i=void 0,chmodSync(m,384),renameSync(m,d),chmodSync(d,384);let f;try{f=openSync(u,"r");try{fsyncSync(f);}catch{}}finally{f!==void 0&&closeSync(f);}return a}finally{if(i!==void 0)try{closeSync(i);}catch{}rmSync(m,{force:true});}}function Pe(e,t,o={}){let n=C(e,o);return _e(n,o,()=>{let r=l(e,o),s=o.fixedGeneration??I(r.valid?r.snapshot.generation:0);if(!Number.isInteger(s)||s<0||s>P)throw new Error("memory_snapshot_generation_invalid");if(o.fixedGeneration!==void 0&&r.valid&&s<=r.snapshot.generation)throw new Error("memory_snapshot_fixed_generation_not_advanced");return N(e,t,s,o)})}function Re(e,t){let n=(w.get(e)??Promise.resolve()).catch(()=>{}).then(t),r=n.then(()=>{},()=>{});return w.set(e,r),n.finally(()=>{w.get(e)===r&&w.delete(e);})}function O(e,t,o,n,r){return e.valid?e.snapshot.generation>r?{...e,persisted:false}:{...e,snapshot:{...e.snapshot,status:"degraded",degradation:{reason:o,stale:e.stale||void 0}},persisted:false}:{snapshot:$(t,"degraded",o,n,r),source:"none",valid:false,stale:false,persisted:false}}async function Oe(e){let t=C(e.projectRoot,e.cacheOptions);return Re(t,async()=>{let o=l(e.projectRoot,e.cacheOptions),n=o.valid?o.snapshot.generation:0,r;try{r=await e.load();}catch(s){let a=b(s,`refresh_failed:${e.reason}`);try{return await G(t,e.cacheOptions??{},()=>{let c=l(e.projectRoot,e.cacheOptions);if(c.valid)return O(c,e.projectRoot,a,e.cacheOptions?.now??Date.now(),n);let d=I(n),u=$(e.projectRoot,"degraded",a,e.cacheOptions?.now??Date.now(),d);return {snapshot:N(e.projectRoot,u,d,e.cacheOptions??{}),source:"cache",valid:!0,stale:!1,persisted:!0}})}catch(c){let d=l(e.projectRoot,e.cacheOptions);return O(d,e.projectRoot,b(c,a),e.cacheOptions?.now??Date.now(),n)}}try{return await G(t,e.cacheOptions??{},()=>{let s=l(e.projectRoot,e.cacheOptions);if(s.valid&&s.snapshot.generation>n)return {...s,persisted:!1};let a=I(Math.max(n,s.valid?s.snapshot.generation:0));return {snapshot:N(e.projectRoot,r,a,e.cacheOptions??{}),source:"cache",valid:!0,stale:!1,persisted:!0}})}catch(s){let a=l(e.projectRoot,e.cacheOptions);return O(a,e.projectRoot,b(s,`refresh_commit_failed:${e.reason}`),e.cacheOptions?.now??Date.now(),n)}})}async function Le(e){return Oe({projectRoot:e.projectRoot,reason:e.reason,cacheOptions:e.cacheOptions,load:async()=>{if(e.injectConfig===false)return {status:"disabled",markdown:"",memoryIds:[],conflicts:[]};let t=typeof e.injectConfig=="object"?e.injectConfig:{},o=Number.isFinite(t.topN)?Math.max(0,Math.floor(t.topN)):
|
|
1
|
+
import {createHash,randomUUID}from'node:crypto';import {readFileSync,openSync,constants,fstatSync,closeSync,writeFileSync,fsyncSync,unlinkSync,lstatSync,mkdirSync,chmodSync,renameSync,rmSync}from'node:fs';import {resolve,join,dirname,isAbsolute,basename}from'node:path';import {getProjectStateDir}from'@devflow-tools/sdk';var S=1,v="memory-snapshot-v1.json",B=512*1024,V=256*1024,q=2e3,ce=500,de=10,ue=240,me=300*1e3,le=720*60*60*1e3,P=2147483647,he=100,X=250,Q=3e4,fe=10,w=new Map;function Z(e){return e.currentUid===void 0?{ownerSafe:true,modeSafe:true}:{ownerSafe:e.ownerUid===e.currentUid,modeSafe:(e.mode&18)===0}}function h(e){return resolve(e)}function p(e){return createHash("sha256").update(h(e)).digest("hex").slice(0,16)}function C(e,t={}){let o=p(e),n=t.stateRoot?join(t.stateRoot,o):getProjectStateDir(h(e));return join(n,v)}function b(e,t){let n=(e instanceof Error?e.message:"").replace(/[\r\n\t]+/gu," ").trim().slice(0,160);return n?`${t}:${n}`:t}function L(e,t){return Array.isArray(e)&&e.length<=t&&e.every(o=>typeof o=="string"&&o.length>0&&o.length<=512)}function ye(e){if(!e||typeof e!="object"||Array.isArray(e))return false;let t=e;return typeof t.id=="string"&&t.id.length>0&&t.id.length<=512&&typeof t.kind=="string"&&t.kind.length>0&&t.kind.length<=128&&(t.family===void 0||typeof t.family=="string"&&t.family.length>0&&t.family.length<=256)&&(t.entity===void 0||typeof t.entity=="string"&&t.entity.length>0&&t.entity.length<=256)&&L(t.memoryIds,100)&&(t.status==="withheld"||t.status==="resolved")&&(t.summary===void 0||typeof t.summary=="string"&&t.summary.length<=2e3)}function pe(e){if(!e||typeof e!="object"||Array.isArray(e))return false;let t=e;return typeof t.reason=="string"&&t.reason.length>0&&t.reason.length<=512&&(t.stale===void 0||typeof t.stale=="boolean")}function T(e,t,o){if(!e||typeof e!="object"||Array.isArray(e))return null;let n=e,r=h(t),s=p(r),a=n.generation===void 0?0:n.generation;return n.version!==S||n.projectRoot!==r||n.projectHash!==s||typeof n.markdown!="string"||Buffer.byteLength(n.markdown,"utf8")>V||!L(n.memoryIds,q)||!Array.isArray(n.conflicts)||n.conflicts.length>ce||!n.conflicts.every(ye)||typeof n.generatedAt!="number"||!Number.isFinite(n.generatedAt)||n.generatedAt<0||n.generatedAt>o+me||!Number.isInteger(a)||a<0||a>P||!["ready","pending","degraded","disabled"].includes(String(n.status))||n.degradation!==void 0&&!pe(n.degradation)?null:{...n,generation:a}}function $(e,t,o,n,r=0){let s=h(e);return {version:S,projectRoot:s,projectHash:p(s),markdown:"",memoryIds:[],conflicts:[],generatedAt:n,generation:r,status:t,degradation:{reason:o}}}function l(e,t={}){let o=t.now??Date.now(),n=C(e,t),r;try{r=openSync(n,constants.O_RDONLY|constants.O_NOFOLLOW);let s=fstatSync(r);if(!s.isFile()||s.size<=0||s.size>B)throw new Error("cache_size_invalid");let a=Z({...typeof process.getuid=="function"?{currentUid:process.getuid()}:{},ownerUid:s.uid,mode:s.mode});if(!a.ownerSafe)throw new Error("cache_owner_invalid");if(!a.modeSafe)throw new Error("cache_permissions_unsafe");let c=JSON.parse(readFileSync(r,"utf8")),d=T(c,e,o);if(!d)throw new Error("cache_schema_invalid");return d.status==="ready"&&o-d.generatedAt>le?{snapshot:{...d,status:"degraded",degradation:{reason:"cache_stale",stale:!0}},source:"cache",valid:!0,stale:!0}:{snapshot:d,source:"cache",valid:!0,stale:!1}}catch(s){let c=s.code==="ENOENT";return {snapshot:$(e,c?"pending":"degraded",c?"cache_missing":b(s,"cache_invalid"),o),source:"none",valid:false,stale:false}}finally{if(r!==void 0)try{closeSync(r);}catch{}}}function I(e){if(!Number.isInteger(e)||e<0||e>=P)throw new Error("memory_snapshot_generation_exhausted");return e+1}function ge(e){let t=dirname(e);mkdirSync(t,{recursive:true,mode:448}),chmodSync(t,448);}function D(e){ge(e);let t=`${e}.lock`,o={pid:process.pid,createdAt:Date.now(),token:randomUUID()},n=JSON.stringify(o),r;try{return r=openSync(t,"wx",384),writeFileSync(r,n),fsyncSync(r),{fd:r,path:t,contents:n}}catch(s){if(r!==void 0){try{closeSync(r);}catch{}try{unlinkSync(t);}catch{}}if(s.code==="EEXIST")return null;throw s}}function Se(e){if(!e||typeof e!="object"||Array.isArray(e))return false;let t=e;return Number.isInteger(t.pid)&&Number(t.pid)>0&&typeof t.createdAt=="number"&&Number.isFinite(t.createdAt)&&typeof t.token=="string"&&t.token.length>0}function we(e){try{return process.kill(e,0),!1}catch(t){return t.code==="ESRCH"}}function Me(e){return !e.canonicalCachePath||!e.directoryIsSafe||!e.lockIsRegularFile||!e.metadataValid||!e.contentsUnchanged||!e.ownerDead&&!e.stale?false:e.currentUid!==void 0?e.directoryUid===e.currentUid&&e.lockUid===e.currentUid:true}function be(e){return isAbsolute(e)&&resolve(e)===e&&basename(e)===v&&/^[a-f0-9]{16}$/u.test(basename(dirname(e)))}function ee(e,t){let o=`${e}.lock`;try{let n=lstatSync(dirname(e)),r=lstatSync(o),s=readFileSync(o,"utf8"),a=null;try{let F=JSON.parse(s);Se(F)&&(a=F);}catch{}let c=a?.createdAt??r.mtimeMs,d=Date.now()-c>t,u=a?we(a.pid):!1,m=readFileSync(o,"utf8")===s,i=typeof process.getuid=="function"?process.getuid():void 0,f=Z({...i!==void 0?{currentUid:i}:{},ownerUid:n.uid,mode:n.mode});return Me({canonicalCachePath:be(e),directoryIsSafe:n.isDirectory()&&!n.isSymbolicLink()&&f.modeSafe,lockIsRegularFile:r.isFile()&&!r.isSymbolicLink(),metadataValid:a!==null,ownerDead:u,stale:d,contentsUnchanged:m,...i!==void 0?{currentUid:i}:{},directoryUid:n.uid,lockUid:r.uid})?(unlinkSync(o),!0):!1}catch{return false}}function te(e){try{closeSync(e.fd);}catch{}try{readFileSync(e.path,"utf8")===e.contents&&unlinkSync(e.path);}catch{}}function _e(e,t,o){let n=D(e);if(!n&&ee(e,t.lockStaleMs??Q)&&(n=D(e)),!n)throw new Error("memory_snapshot_cache_lock_busy");try{return o()}finally{te(n);}}function ke(e){return new Promise(t=>setTimeout(t,e))}function R(e,t,o,n){let r=Number.isFinite(e)?Math.floor(e):t;return Math.min(n,Math.max(o,r))}async function Ce(e,t){let o=R(t.lockTimeoutMs,he,0,X),n=R(t.lockRetryMs,fe,1,X),r=R(t.lockStaleMs,Q,0,Number.MAX_SAFE_INTEGER),s=Date.now()+o;for(;;){let a=D(e);if(a)return a;if(ee(e,r))continue;let c=s-Date.now();if(c<=0)throw new Error("memory_snapshot_cache_lock_timeout");await ke(Math.min(n,c));}}async function G(e,t,o){let n=await Ce(e,t);try{return await o()}finally{te(n);}}function N(e,t,o,n){let r=n.now??Date.now(),s=h(e),a={version:S,projectRoot:s,projectHash:p(s),markdown:t.markdown,memoryIds:t.memoryIds??[],conflicts:t.conflicts??[],generatedAt:r,generation:o,status:t.status??"ready",...t.degradation?{degradation:t.degradation}:{}};if(!T(a,e,r))throw new Error("memory_snapshot_payload_invalid");let c=JSON.stringify(a);if(Buffer.byteLength(c,"utf8")>B)throw new Error("memory_snapshot_cache_too_large");let d=C(e,n),u=dirname(d);mkdirSync(u,{recursive:true,mode:448}),chmodSync(u,448);let m=join(u,`.${v}.${process.pid}.${randomUUID()}.tmp`),i;try{i=openSync(m,"wx",384),writeFileSync(i,c),fsyncSync(i),closeSync(i),i=void 0,chmodSync(m,384),renameSync(m,d),chmodSync(d,384);let f;try{f=openSync(u,"r");try{fsyncSync(f);}catch{}}finally{f!==void 0&&closeSync(f);}return a}finally{if(i!==void 0)try{closeSync(i);}catch{}rmSync(m,{force:true});}}function Pe(e,t,o={}){let n=C(e,o);return _e(n,o,()=>{let r=l(e,o),s=o.fixedGeneration??I(r.valid?r.snapshot.generation:0);if(!Number.isInteger(s)||s<0||s>P)throw new Error("memory_snapshot_generation_invalid");if(o.fixedGeneration!==void 0&&r.valid&&s<=r.snapshot.generation)throw new Error("memory_snapshot_fixed_generation_not_advanced");return N(e,t,s,o)})}function Re(e,t){let n=(w.get(e)??Promise.resolve()).catch(()=>{}).then(t),r=n.then(()=>{},()=>{});return w.set(e,r),n.finally(()=>{w.get(e)===r&&w.delete(e);})}function O(e,t,o,n,r){return e.valid?e.snapshot.generation>r?{...e,persisted:false}:{...e,snapshot:{...e.snapshot,status:"degraded",degradation:{reason:o,stale:e.stale||void 0}},persisted:false}:{snapshot:$(t,"degraded",o,n,r),source:"none",valid:false,stale:false,persisted:false}}async function Oe(e){let t=C(e.projectRoot,e.cacheOptions);return Re(t,async()=>{let o=l(e.projectRoot,e.cacheOptions),n=o.valid?o.snapshot.generation:0,r;try{r=await e.load();}catch(s){let a=b(s,`refresh_failed:${e.reason}`);try{return await G(t,e.cacheOptions??{},()=>{let c=l(e.projectRoot,e.cacheOptions);if(c.valid)return O(c,e.projectRoot,a,e.cacheOptions?.now??Date.now(),n);let d=I(n),u=$(e.projectRoot,"degraded",a,e.cacheOptions?.now??Date.now(),d);return {snapshot:N(e.projectRoot,u,d,e.cacheOptions??{}),source:"cache",valid:!0,stale:!1,persisted:!0}})}catch(c){let d=l(e.projectRoot,e.cacheOptions);return O(d,e.projectRoot,b(c,a),e.cacheOptions?.now??Date.now(),n)}}try{return await G(t,e.cacheOptions??{},()=>{let s=l(e.projectRoot,e.cacheOptions);if(s.valid&&s.snapshot.generation>n)return {...s,persisted:!1};let a=I(Math.max(n,s.valid?s.snapshot.generation:0));return {snapshot:N(e.projectRoot,r,a,e.cacheOptions??{}),source:"cache",valid:!0,stale:!1,persisted:!0}})}catch(s){let a=l(e.projectRoot,e.cacheOptions);return O(a,e.projectRoot,b(s,`refresh_commit_failed:${e.reason}`),e.cacheOptions?.now??Date.now(),n)}})}async function Le(e){return Oe({projectRoot:e.projectRoot,reason:e.reason,cacheOptions:e.cacheOptions,load:async()=>{if(e.injectConfig===false)return {status:"disabled",markdown:"",memoryIds:[],conflicts:[]};let t=typeof e.injectConfig=="object"?e.injectConfig:{},o=Number.isFinite(t.topN)?Math.max(0,Math.floor(t.topN)):4,n=Number.isFinite(t.budgetTokens)?Math.max(1,Math.floor(t.budgetTokens)):400,r=await e.memory.getAll({purpose:"session_bootstrap",budgetTokens:n,limit:o}),a=Number.isInteger(r.truncatedCount)&&r.truncatedCount>=0?r.truncatedCount:null,c=r.memories.length===0&&a!==0,d=a!==null&&a>0?"snapshot_results_truncated":"snapshot_truncation_unknown",u=(r.conflicts??[]).map(i=>({id:i.id,kind:i.kind,family:i.family,entity:i.entity,memoryIds:i.memoryIds,status:i.status,...i.summary?{summary:i.summary}:{}})),m=c?`## Project memory
|
|
2
2
|
DevFlow memory snapshot=degraded; reason=${d}. Memory result completeness is not authoritative; do not conclude that the project has no memories.`:r.memories.length===0&&u.length>0?`## Project memory
|
|
3
3
|
${u.length} explicit preference conflict(s) are withheld from automatic guidance; an explicit choice is required.`:r.memories.length===0?`## Project memory
|
|
4
4
|
\u672C\u9879\u76EE\u6682\u65E0\u8BB0\u5FC6`:`## Project memory (auto-injected, ${r.memories.length} items, ${r.tokenCount} tokens)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {classifyWorkflowFailure}from'@devflow-tools/workflow-engine/failure-classifier';import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,linkSync,readdirSync,renameSync,unlinkSync}from'fs';import {join as join$1}from'path';import {homedir as homedir$1}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {request}from'node:http';import {existsSync as existsSync$1,mkdirSync as mkdirSync$1,appendFileSync}from'node:fs';import {join}from'node:path';import {homedir}from'node:os';import {getLocalApiKey,getProjectStateDir,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure}from'@devflow-tools/sdk';import {randomUUID,createHash}from'crypto';import {emitSemanticControlLog}from'@devflow-tools/telemetry';function
|
|
2
|
-
`);}catch{}}function Ee(o){return new Promise(t=>setTimeout(t,o))}var W=1e4,we=3e4,_=500,R=class{constructor(t){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=t?.apiUrl,this.cacheDir=t?.cacheDir??join$1(process.env.DEVFLOW_STATE_DIR??join$1(homedir$1(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join$1(homedir$1(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}async sendEvent(t){let e={...t,input:this.truncateInput(t.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),t.eventId):null}async sendExecutionStart(t,e,n,i,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:n,startedAt:i,projectRoot:r,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",n=Date.now(),i){let r={executionId:t,status:e,finishedAt:n,metadata:i},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(t,e,n){let i={id:t,projectRoot:e,startedAt:n,label:e.split("/").pop()??"unknown"},r=this.commitOrCache("session_start",i);return r&&this.postHttp("/api/telemetry/sessions",i),r}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let n={sessionId:t,finishedAt:e},i=this.commitOrCache("session_end",n);return i&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),i}async flushCache(){try{let n=this.getDatabase(),i=n.listTelemetryFailures({unresolvedOnly:!0,limit:_}).reverse();for(let r of i)try{this.applyOperation(r.operation,r.payload),n.resolveTelemetryFailure(r.id);}catch{}n.trimTelemetryFailures(_);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync(n)).flatMap(n=>readdirSync(n).filter(i=>i.endsWith(".json")).map(i=>{let r=join$1(n,i);try{return {cacheFile:r,envelope:xe(JSON.parse(readFileSync(r,"utf8")),i)}}catch{return null}})).filter(n=>n!==null).sort((n,i)=>n.envelope.timestamp-i.envelope.timestamp||z(n.envelope.operation)-z(i.envelope.operation));for(let{cacheFile:n,envelope:i}of e)try{let r=this.getDatabase();r.insertTelemetryFailure({id:i.id,operation:i.operation,payload:i.payload,error:i.failure,createdAt:i.timestamp}),this.applyOperation(i.operation,i.payload),r.resolveTelemetryFailure(i.id),unlinkSync(n);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(n){return this.cacheOperation(t,e,n),false}}applyOperation(t,e){let n=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(n,e),n.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(n,e),n.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":n.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":n.ensureSession(e),n.insertRun({id:V(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!n.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,failureCategory:e.failureCategory,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":n.closeSession(e.sessionId,e.finishedAt),n.updateRun(V(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let n=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!n)throw new Error("Canonical session ID is required for telemetry");let i=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:n,projectRoot:i,label:i==="unknown"?void 0:i.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,n){let i=Date.now(),r={id:`failure:${i}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:i};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:i}),s.trimTelemetryFailures(_),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${i}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(r,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of t.slice(0,Math.max(0,t.length-_)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},we).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(t,e){E(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=W?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,W)}...`}}};function z(o){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(o)}function V(o){return `hook-run:${o}`}function xe(o,t){if(!o||typeof o!="object")throw new Error("Invalid telemetry cache envelope");let e=o;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let n=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!n)throw new Error("Unknown legacy telemetry cache operation");let i=e.payload??{},r=Number(i.timestamp??i.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:n,payload:i,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:r}}function Se(o){return o??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function h(o){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(Se(o))}function K(o){return Buffer.from(o,"utf8").toString("base64url")}function Te(o,t,e){let n=t?.trim();if(n){let i=/^[a-zA-Z0-9:._-]{1,192}$/.test(n)?n:`tool-${createHash("sha256").update(n.slice(0,1024)).digest("hex").slice(0,32)}`;return `${o}:${i}`}return `${o}:legacy-${e}-${randomUUID().slice(0,8)}`}function ne(o){return `${o}:legacy-journal`}var I=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(h(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let n=this.get(e);if(n)return n.lastActivityAt=Date.now(),this.persist(n),n;let i=Date.now(),r={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:i,lastActivityAt:i};return this.sessions.set(e,r),this.persist(r),r}startExecution(t,e,n){let i=this.registerSession(t);return (!i.executionId||i.skillName!==e)&&(i.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),i.skillName=e,i.requiredMcpTools=[...new Set(n)],i.lastActivityAt=Date.now(),this.persist(i),i}bindTaskIdentity(t,e){let n=this.registerSession(t);return n.activeTurnId=e.turnId,n.activeRequestId=e.requestId,n.intentArtifactHash=e.intentArtifactHash,n.lastActivityAt=Date.now(),this.persist(n),n}get(t){let e=t.trim();if(!e)return null;let n=this.sessions.get(e);if(n)return this.replayEvidenceJournal(n),n;let i=this.snapshotPath(e);if(!existsSync(i))return null;try{let r=JSON.parse(readFileSync(i,"utf8"));return r.sessionId!==e||r.projectRoot!==this.projectRoot?null:(r.requiredMcpTools=Array.isArray(r.requiredMcpTools)?r.requiredMcpTools:[],r.evidenceObligations=Y(r.evidenceObligations),r.evidenceDegradations=Q(r.evidenceDegradations),r.evidenceOutcomes=Z(r.evidenceOutcomes),this.replayEvidenceJournal(r),this.sessions.set(e,r),r)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let n=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),n}addEvidenceObligation(t,e,n=Date.now(),i){let r=this.registerSession(t),a=(i?void 0:r.evidenceObligations.find(d=>d.contractId===e.id))?.obligationId??Te(e.id,i,n);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:n,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let c=r.evidenceObligations.find(d=>d.obligationId===a);return c?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(c)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,n,i,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(l=>l.obligationId===e);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(i)?i:"";if(!c)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:c,violations:n.slice(0,16).map(l=>l.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let d=s.evidenceObligations.find(l=>l.obligationId===e);return d?structuredClone(d):null}resolveEvidenceObligation(t,e){let n=this.get(t);if(!n)return false;let i=n.evidenceObligations.find(s=>s.obligationId===e);if(!i)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:i.contractId,at:r},`resolve\0${e}`),this.replayEvidenceJournal(n),n.lastActivityAt=r,this.persist(n),true}degradeEvidenceObligation(t,e,n,i=Date.now()){let r=this.get(t),s=r?.evidenceObligations.find(c=>c.obligationId===e);if(!r||!s)return false;let a=n.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:i,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(r),r.lastActivityAt=i,this.persist(r),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${K(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",K(t))}appendEvidenceEvent(t,e,n){let i=this.evidenceJournalDir(t);mkdirSync(i,{recursive:true,mode:448});let r=createHash("sha256").update(n).digest("hex"),s=join$1(i,`${e.kind}-${r}.json`);if(existsSync(s))return;let a=join$1(i,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Y(t.evidenceObligations),t.evidenceDegradations=Q(t.evidenceDegradations),t.evidenceOutcomes=Z(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let n;try{n=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let i=n.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=Fe(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||ee(r.kind)-ee(s.kind));for(let r of i)this.applyEvidenceEvent(t,r);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let n=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(n)return;let s=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let i=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!i||n||i.correctionFingerprint===e.fingerprint)return;i.attempt+=1,i.correctionRequested=true,i.correctionRequestedAt=e.at,i.correctionFingerprint=e.fingerprint,i.violations=e.violations;return}let r=i?.attempt??0;t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),!n&&(e.kind==="degrade"&&t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r}),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}}));}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),n=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(n,JSON.stringify(t),{mode:384}),renameSync(n,e);}};function Y(o){return Array.isArray(o)?o.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!ie(e.contract))return [];let n=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:ne(e.contractId),i=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,r=e.correctionFingerprint??i;return r!==void 0&&!/^[a-f0-9]{64}$/.test(r)?[]:[{...e,obligationId:n,correctionFingerprint:r}]}).slice(-8):[]}function Q(o){return Array.isArray(o)?o.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function Z(o){return Array.isArray(o)?o.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function Fe(o){if(!o||typeof o!="object")return null;let t=o,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let i={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:ne(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return ie(t.contract)?{kind:e,...i,contract:t.contract}:null;if(e==="correction"){let r=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)&&Array.isArray(t.violations)&&t.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:e,...i,fingerprint:r,violations:t.violations}:null}return e==="resolve"?{kind:e,...i}:typeof t.reason=="string"&&t.reason.length<=240?{kind:e,...i,reason:t.reason}:null}function ee(o){return o==="add"?0:o==="correction"?1:2}function ie(o){if(!o||typeof o!="object")return false;let t=o,e=t.requiredSections,n=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(n)&&n.length<=16&&n.every(i=>typeof i=="string"&&i.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function re(o,t){return t?`evt_tool_${createHash("sha256").update(`${o}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}function w(o){if(!o||typeof o!="object"||Array.isArray(o))return {};let t=o,e={};for(let n of ["lastMcpCall","bypassCount"])if(n in t){let i=t[n];if(i==null)continue;e[n]=typeof i=="number"&&Number.isFinite(i)&&i>=0?i:0;}return e}function je(o,t){return o.lastMcpCall===t.lastMcpCall&&o.bypassCount===t.bypassCount}function He(o){try{return existsSync(o)?w(JSON.parse(readFileSync(o,"utf-8"))):{}}catch{return {}}}function Le(o,t,e){let n=e instanceof Error?e.message:String(e);emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:o},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:n,fallback:"fail_open"}});}function oe(o){let t=h(o);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join$1(t,e))&&unlinkSync(join$1(t,e));}catch{}}function qe(o,t){if(o.getHookReceipt(t)){oe(t);return}let e=join$1(h(t),"receipt.json");if(!existsSync(e))return;let n=He(e);o.updateHookReceipt(t,()=>n),oe(t);}function ae(o,t,e){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),qe(n,o);let i={},r=n.updateHookReceipt(o,a=>(i=w(a),w(t(i)))),s=w(r);return {receipt:s,applied:!0,changed:!je(i,s)}}catch(i){return Le(o,e,i),{receipt:{},applied:false,changed:false}}finally{try{n?.close();}catch{}}}function Ne(o,t){return ae(o,()=>t,"write").applied}function Je(o,t){return ae(o,t,"update")}var se={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},Ue=new Set(["Write","Edit","NotebookEdit"]),We=new Set(["failed","timeout","unavailable"]);function ze(o){switch(o){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var x=class{constructor(t,e,n){this.projectRoot=t;this.sessionId=e;this.executionId=n;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(e&&e.expiresAt>Date.now())return "context_ready";e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}return "context_gathering"}getContextReceipt(){if(!this.sessionId||!this.executionId)return null;let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);return e&&e.expiresAt>Date.now()?e:(e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId),null)}catch{return null}finally{try{t?.close();}catch{}}}evaluate(t,e){let n=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(n==="context_gathering"&&se[t])return {permissionDecision:"deny",reasonCode:"DEVFLOW_CONTEXT_REQUIRED",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(n==="context_ready"){if(Ue.has(t)){let c=this.evaluateRequiredAction();if(c)return c}return {permissionDecision:"allow"}}let i=se[t];if(!i)return {permissionDecision:"allow"};let r=Je(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!r.applied)return {permissionDecision:"allow"};let s=r.receipt.bypassCount??0,a=ze(t);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${i} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){Ne(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(t,e,n,i){if(!this.sessionId||!this.executionId)return false;let r;try{r=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let s=r.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(!s||s.expiresAt<=Date.now()||s.canonicalAction?.tool!==t)return !1;let a=Date.now(),c=i?.trim()?`${i.trim()}:${e}`:`${t}:${e}:${a}`,d=s.actionAttempts??[];return r.upsertContextReceipt({...s,actionAttempts:d.some(l=>l.id===c||i&&l.toolUseId===i&&l.status===e)?d:[...d,{id:c,tool:t,status:e,attemptedAt:a,toolUseId:i,reason:n?.slice(0,500)}].slice(-20),actionSatisfiedAt:e==="succeeded"?a:s.actionSatisfiedAt,actionDegradation:e==="succeeded"?void 0:s.actionDegradation}),!0}catch{return false}finally{try{r?.close();}catch{}}}evaluateRequiredAction(){let t=this.getContextReceipt(),e=t?.canonicalAction;if(!t||!e||!e.required||e.status!=="required")return null;let n=e.binding;if(n.requiredContextReceipt!==t.contextHash||n.projectRoot!==this.projectRoot||n.sessionId!==this.sessionId||n.requestId!==t.requestId||n.executionId&&n.executionId!==this.executionId)return {permissionDecision:"deny",reasonCode:"DEVFLOW_ACTION_BINDING_STALE",reason:"DevFlow canonical action binding is stale or mismatched. Call mcp__devflow__get_project_context again before writing."};if(t.actionSatisfiedAt)return null;if(t.actionDegradation?.authorizedByContextReceipt===t.contextHash)return {permissionDecision:"allow",additionalContext:`DevFlow degraded fallback authorized by context receipt ${t.contextHash}: ${t.actionDegradation.reason}`};let i=(t.actionAttempts??[]).filter(r=>r.tool===e.tool&&We.has(r.status));if(i.length>0){let r=i.at(-1),s={missedTool:e.tool,failedAttemptCount:i.length,reason:`${r.status}:${r.reason??"canonical domain action did not complete"}`,authorizedByContextReceipt:t.contextHash,authorizedAt:Date.now()};return this.persistDegradation(t,s),{permissionDecision:"allow",additionalContext:`DevFlow canonical tool mcp__devflow__${e.tool} ${r.status}; degraded direct write authorized by context receipt ${t.contextHash}. Preserve the action contract and verification plan.`}}return {permissionDecision:"deny",reasonCode:"DEVFLOW_REQUIRED_ACTION",reason:`DevFlow required action not completed. Call mcp__devflow__${e.tool} using context receipt ${t.contextHash}, then retry the write. Direct fallback is allowed only after unavailable, failed, or timeout evidence.`}}persistDegradation(t,e){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let i=n.getContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!i||i.contextHash!==t.contextHash||i.actionDegradation)return;n.upsertContextReceipt({...i,actionDegradation:e});let r=n.getSkillExecution(t.executionId);if(!r)return;let s=r.metadata&&typeof r.metadata=="object"?r.metadata:{},a=Array.isArray(s.requiredActionDegradations)?s.requiredActionDegradations:[];n.updateSkillExecution(t.executionId,{missedMcpTools:[...new Set([...r.missedMcpTools??[],e.missedTool])],failedToolCalls:Math.max(r.failedToolCalls??0,e.failedAttemptCount),fallbackCount:(r.fallbackCount??0)+1,fallbackReasons:[...new Set([...r.fallbackReasons??[],`required_action_${e.reason}`])],metadata:{...s,requiredActionDegradations:[...a,e]}});}catch{}finally{try{n?.close();}catch{}}}};var f=process.env.CLAUDE_PROJECT_DIR||process.cwd();function ce(o,t){let e=Number(o);return Number.isInteger(e)&&e>=0?e:t}async function Be(o,t){let e=t.timeoutMs??ce(process.env.DEVFLOW_FAILURE_TIMEOUT_MS,1500),n=t.maxRetries??ce(process.env.DEVFLOW_FAILURE_MAX_RETRIES,0),i=`/api/memory/session-events?rootPath=${encodeURIComponent(f)}`,r=await E(i,o,{timeout:e,maxRetries:n,durableMirror:true,fallbackReason:"tool_failure_persisted_in_local_telemetry"});if(!r.delivered)throw new Error(r.fallbackReason??"post_tool_failure_delivery_failed")}async function Ge(o,t={}){let e;try{e=JSON.parse(o);}catch{return}let n=e.tool_name||"",i=e.tool_input||{},r=e.error||"",s=e.session_id?.trim();if(!s)return;let a=new I(f).registerSession(s);if(n.startsWith("mcp__devflow__")){let de=/timeout|timed out|deadline/i.test(r)?"timeout":/unavailable|not active|unknown tool|not found|not registered|route not found/i.test(r)?"unavailable":"failed";new x(f,s,a.executionId??s).recordDomainActionOutcome(n.replace(/^mcp__[^_]+__/,""),de,r,e.tool_use_id);}let c=re(s,e.tool_use_id),d=classifyWorkflowFailure({stepId:n,toolName:n,error:new Error(r||`${n||"tool"} failed`),errorStack:r||void 0}),l=typeof i=="object"&&i.command?i.command:n,u={id:`memory:${c}`,sessionId:s,tool:n,command:l,exitCode:-1,stderr:r,durationMs:0,createdAt:Date.now(),kind:n==="Bash"?"bash_error":"tool_use",payload:{command:l,exitCode:-1,stderr:r,failureSource:"PostToolUseFailure",failureCategory:d.category}},p=!t.telemetryClient,C=t.telemetryClient??new R,b=n.startsWith("mcp__"),le={eventId:c,executionId:a.executionId??s,sessionId:s,projectRoot:f,toolUseId:e.tool_use_id,timestamp:u.createdAt,toolName:n,toolType:b?"mcp":"direct",isMcpTool:b,mcpToolName:b?n:void 0,mcpEnforced:b,mcpFallback:false,kind:"error",input:i,duration:0,error:r,blocked:false,failureCategory:d.category};try{await C.sendEvent(le),await C.completeEvent({eventId:c,sessionId:s,error:r,duration:0,completedAt:Date.now()});}finally{p&&C.close();}t.eventDelivery?await t.eventDelivery(u):await Be(u,t);}if(process.argv[1]?.endsWith("post-tool-use-failure")||process.argv[1]?.endsWith("post-tool-use-failure.js")){let o=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{try{await Ge(t.trim()||process.argv[2]||""),o(JSON.stringify({status:"ok"}));}catch(e){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:f},level:"warn",timestamp:Date.now(),data:{stage:"post_tool_failure_delivery",reason:e.message,fallback:"durable_retry_on_next_runtime"}}),o(JSON.stringify({status:"degraded",reason:"post_tool_failure_delivery_failed",fallback:"durable_retry_on_next_runtime"}));}}),process.stdin.on("error",e=>{emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:f},level:"warn",timestamp:Date.now(),data:{stage:"post_tool_failure_input",reason:e.message,fallback:"host_event_continues"}}),o(JSON.stringify({status:"degraded",reason:"post_tool_failure_input_failed",fallback:"host_event_continues"}));});}export{Ge as handlePostToolUseFailure};
|
|
1
|
+
import {classifyWorkflowFailure}from'@devflow-tools/workflow-engine/failure-classifier';import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,linkSync,readdirSync,renameSync,unlinkSync}from'fs';import {join as join$1}from'path';import {homedir as homedir$1}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {request}from'node:http';import {realpathSync,existsSync as existsSync$1,mkdirSync as mkdirSync$1,appendFileSync}from'node:fs';import {join}from'node:path';import {homedir}from'node:os';import {getLocalApiKey,appendTaskRuntimeBoundary,taskSpecFromImmutableIntent,getProjectStateDir,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure}from'@devflow-tools/sdk';import {randomUUID,createHash}from'crypto';import {emitSemanticControlLog}from'@devflow-tools/telemetry';import {createHash as createHash$1}from'node:crypto';function A(n,t,e){try{let i=openGlobalDevFlowDatabase();try{i.insertEvent({kind:n,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{i.close();}}catch{}}var De=getLocalApiKey(),C=join(homedir(),".devflow","errors");async function R(n,t,e={}){let i=e.endpoint??resolveRuntimeEndpoint().url,o=e.timeout??1500,r=e.durableMirror??true,a=e.maxRetries??(r?0:2),s=e.circuitBreaker??true,c=acquireRuntimeHttpCircuit(i,n);if(s&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let l;for(let u=0;u<=a;u+=1)try{return await Se(i,n,t,o),s&®isterRuntimeHttpSuccess(i,n).transitioned&&A("http_circuit_transition",{endpoint:i,path:new URL(n,i).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(m){l=m instanceof Error?m:new Error(String(m)),u<a&&await Te(Math.min(100*2**u,1e3));}if(!l)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!s)return L(n,l),{delivered:false,suppressed:false,fallbackReason:l.message};let d=registerRuntimeHttpFailure(i,n,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return d.transitioned&&(L(n,l),A("http_circuit_transition",{endpoint:i,path:new URL(n,i).pathname,previous:c.state.status,status:"open",failures:d.state.failures,openUntil:d.state.openUntil,fallbackReason:d.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:d.state.fallbackReason}}function Se(n,t,e,i){return new Promise((o,r)=>{let a=JSON.stringify(e),s=new URL(t,n),c=false,l=u=>{c||(c=true,u?r(u):o());},d=request({hostname:s.hostname,port:s.port,path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":De,"Content-Length":Buffer.byteLength(a)},timeout:i},u=>{u.on("error",l),u.on("end",()=>{let m=u.statusCode??0;l(m>=200&&m<300?void 0:new Error(`HTTP ${m}`));}),u.resume();});d.on("error",l),d.on("timeout",()=>d.destroy(new Error(`HTTP mirror timed out after ${i}ms`))),d.write(a),d.end();})}function L(n,t){try{existsSync$1(C)||mkdirSync$1(C,{recursive:!0}),appendFileSync(join(C,"http-errors.log"),`${new Date().toISOString()} | ${n} | ${t.message}
|
|
2
|
+
`);}catch{}}function Te(n){return new Promise(t=>setTimeout(t,n))}var z=1e4,Oe=3e4,E=500,w=class{constructor(t){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=t?.apiUrl,this.cacheDir=t?.cacheDir??join$1(process.env.DEVFLOW_STATE_DIR??join$1(homedir$1(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join$1(homedir$1(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}async sendEvent(t){let e={...t,input:this.truncateInput(t.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),t.eventId):null}async sendExecutionStart(t,e,i,o,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),a=[]){let s={executionId:t,sessionId:e,skillName:i,startedAt:o,projectRoot:r,requiredMcpTools:a};this.commitOrCache("execution_start",s)&&this.postHttp("/api/telemetry/skill-execution/start",s);}async sendExecutionComplete(t,e="completed",i=Date.now(),o){let r={executionId:t,status:e,finishedAt:i,metadata:o},a=this.commitOrCache("execution_complete",r);return a&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),a}async sendSessionStart(t,e,i){let o={id:t,projectRoot:e,startedAt:i,label:e.split("/").pop()??"unknown"},r=this.commitOrCache("session_start",o);return r&&this.postHttp("/api/telemetry/sessions",o),r}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let i={sessionId:t,finishedAt:e},o=this.commitOrCache("session_end",i);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),o}async flushCache(){try{let i=this.getDatabase(),o=i.listTelemetryFailures({unresolvedOnly:!0,limit:E}).reverse();for(let r of o)try{this.applyOperation(r.operation,r.payload),i.resolveTelemetryFailure(r.id);}catch{}i.trimTelemetryFailures(E);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(i=>!!i))].filter(i=>existsSync(i)).flatMap(i=>readdirSync(i).filter(o=>o.endsWith(".json")).map(o=>{let r=join$1(i,o);try{return {cacheFile:r,envelope:je(JSON.parse(readFileSync(r,"utf8")),o)}}catch{return null}})).filter(i=>i!==null).sort((i,o)=>i.envelope.timestamp-o.envelope.timestamp||B(i.envelope.operation)-B(o.envelope.operation));for(let{cacheFile:i,envelope:o}of e)try{let r=this.getDatabase();r.insertTelemetryFailure({id:o.id,operation:o.operation,payload:o.payload,error:o.failure,createdAt:o.timestamp}),this.applyOperation(o.operation,o.payload),r.resolveTelemetryFailure(o.id),unlinkSync(i);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(i){return this.cacheOperation(t,e,i),false}}applyOperation(t,e){let i=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(i,e),i.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(i,e),i.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":i.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":i.ensureSession(e),i.insertRun({id:G(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!i.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,failureCategory:e.failureCategory,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":i.closeSession(e.sessionId,e.finishedAt),i.updateRun(G(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let i=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!i)throw new Error("Canonical session ID is required for telemetry");let o=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:i,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,i){let o=Date.now(),r={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:i instanceof Error?i.message:String(i),timestamp:o};try{let a=this.getDatabase();a.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:o}),a.trimTelemetryFailures(E),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let a=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(a,JSON.stringify(r,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of t.slice(0,Math.max(0,t.length-E)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},Oe).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(t,e){R(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=z?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,z)}...`}}};function B(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function G(n){return `hook-run:${n}`}function je(n,t){if(!n||typeof n!="object")throw new Error("Invalid telemetry cache envelope");let e=n;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let i=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!i)throw new Error("Unknown legacy telemetry cache operation");let o=e.payload??{},r=Number(o.timestamp??o.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:i,payload:o,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:r}}function qe(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function _(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(qe(n))}function Q(n){return Buffer.from(n,"utf8").toString("base64url")}function He(n,t,e){let i=t?.trim();if(i){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(i)?i:`tool-${createHash("sha256").update(i.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${o}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function oe(n){return `${n}:legacy-journal`}var S=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(_(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let i=this.get(e);if(i)return i.lastActivityAt=Date.now(),this.persist(i),i;let o=Date.now(),r={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:o,lastActivityAt:o};return this.sessions.set(e,r),this.persist(r),r}startExecution(t,e,i){let o=this.registerSession(t);return (!o.executionId||o.skillName!==e)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=e,o.requiredMcpTools=[...new Set(i)],o.lastActivityAt=Date.now(),this.persist(o),o}bindTaskIdentity(t,e){let i=this.registerSession(t);return i.activeTurnId=e.turnId,i.activeRequestId=e.requestId,i.intentArtifactHash=e.intentArtifactHash,i.lastActivityAt=Date.now(),this.persist(i),i}get(t){let e=t.trim();if(!e)return null;let i=this.sessions.get(e);if(i)return this.replayEvidenceJournal(i),i;let o=this.snapshotPath(e);if(!existsSync(o))return null;try{let r=JSON.parse(readFileSync(o,"utf8"));return r.sessionId!==e||r.projectRoot!==this.projectRoot?null:(r.requiredMcpTools=Array.isArray(r.requiredMcpTools)?r.requiredMcpTools:[],r.evidenceObligations=Z(r.evidenceObligations),r.evidenceDegradations=ee(r.evidenceDegradations),r.evidenceOutcomes=te(r.evidenceOutcomes),this.replayEvidenceJournal(r),this.sessions.set(e,r),r)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let i=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),i}addEvidenceObligation(t,e,i=Date.now(),o){let r=this.registerSession(t),s=(o?void 0:r.evidenceObligations.find(l=>l.contractId===e.id))?.obligationId??He(e.id,o,i);this.appendEvidenceEvent(t,{kind:"add",obligationId:s,contractId:e.id,at:i,contract:e},`add\0${s}`),this.replayEvidenceJournal(r);let c=r.evidenceObligations.find(l=>l.obligationId===s);return c?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(c)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,i,o,r=Date.now()){let a=this.get(t),s=a?.evidenceObligations.find(d=>d.obligationId===e);if(!a||!s)return null;let c=/^[a-f0-9]{64}$/.test(o)?o:"";if(!c)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:s.contractId,at:r,fingerprint:c,violations:i.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(a),a.lastActivityAt=r,this.persist(a);let l=a.evidenceObligations.find(d=>d.obligationId===e);return l?structuredClone(l):null}resolveEvidenceObligation(t,e){let i=this.get(t);if(!i)return false;let o=i.evidenceObligations.find(a=>a.obligationId===e);if(!o)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve\0${e}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}resolveDegradedEvidence(t,e){let i=this.get(t),o=i?.evidenceDegradations.find(a=>a.obligationId===e);if(!i||!o)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve-degraded\0${e}\0${r}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}degradeEvidenceObligation(t,e,i,o=Date.now()){let r=this.get(t),a=r?.evidenceObligations.find(c=>c.obligationId===e);if(!r||!a)return false;let s=i.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:a.contractId,at:o,reason:s},`degrade\0${e}\0${s}`),this.replayEvidenceJournal(r),r.lastActivityAt=o,this.persist(r),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${Q(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Q(t))}appendEvidenceEvent(t,e,i){let o=this.evidenceJournalDir(t);mkdirSync(o,{recursive:true,mode:448});let r=createHash("sha256").update(i).digest("hex"),a=join$1(o,`${e.kind}-${r}.json`);if(existsSync(a))return;let s=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(s,JSON.stringify(e),{mode:384});try{linkSync(s,a);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(s,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Z(t.evidenceObligations),t.evidenceDegradations=ee(t.evidenceDegradations),t.evidenceOutcomes=te(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let i;try{i=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let o=i.flatMap(r=>{try{let a=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(a,"utf8")>64*1024)return [];let s=Le(JSON.parse(a));return s?[s]:[]}catch{return []}}).sort((r,a)=>r.at-a.at||ne(r.kind)-ne(a.kind));for(let r of o)this.applyEvidenceEvent(t,r);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let i=t.evidenceOutcomes.find(a=>a.obligationId===e.obligationId);if(e.kind==="add"){if(i)return;let a=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);a?(a.contract=e.contract,a.promptedAt=Math.min(a.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let o=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);if(e.kind==="correction"){if(!o||i||o.correctionFingerprint===e.fingerprint)return;o.attempt+=1,o.correctionRequested=true,o.correctionRequestedAt=e.at,o.correctionFingerprint=e.fingerprint,o.violations=e.violations;return}let r=o?.attempt??i?.attempt??0;if(e.kind==="resolve"&&i?.status==="degraded")t.evidenceOutcomes=t.evidenceOutcomes.filter(a=>a.obligationId!==e.obligationId),t.evidenceDegradations=t.evidenceDegradations.filter(a=>a.obligationId!==e.obligationId);else if(i)return;e.kind==="degrade"?(t.evidenceObligations=t.evidenceObligations.filter(a=>a.obligationId!==e.obligationId),t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r,contract:o?.contract})):t.evidenceObligations=t.evidenceObligations.filter(a=>a.obligationId!==e.obligationId),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}});}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),i=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(i,JSON.stringify(t),{mode:384}),renameSync(i,e);}};function Z(n){return Array.isArray(n)?n.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!re(e.contract))return [];let i=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:oe(e.contractId),o=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,r=e.correctionFingerprint??o;return r!==void 0&&!/^[a-f0-9]{64}$/.test(r)?[]:[{...e,obligationId:i,correctionFingerprint:r}]}).slice(-8):[]}function ee(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function te(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function Le(n){if(!n||typeof n!="object")return null;let t=n,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let o={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:oe(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return re(t.contract)?{kind:e,...o,contract:t.contract}:null;if(e==="correction"){let r=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)&&Array.isArray(t.violations)&&t.violations.every(a=>typeof a=="string"&&a.length<=240)?{kind:e,...o,fingerprint:r,violations:t.violations}:null}return e==="resolve"?{kind:e,...o}:typeof t.reason=="string"&&t.reason.length<=240?{kind:e,...o,reason:t.reason}:null}function ne(n){return n==="add"?0:n==="correction"?1:2}function re(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,i=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(i)&&i.length<=16&&i.every(o=>typeof o=="string"&&o.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function ae(n,t){return t?`evt_tool_${createHash("sha256").update(`${n}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}function T(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let t=n,e={};for(let i of ["lastMcpCall","bypassCount"])if(i in t){let o=t[i];if(o==null)continue;e[i]=typeof o=="number"&&Number.isFinite(o)&&o>=0?o:0;}return e}function We(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function Ve(n){try{return existsSync(n)?T(JSON.parse(readFileSync(n,"utf-8"))):{}}catch{return {}}}function ze(n,t,e){let i=e instanceof Error?e.message:String(e);emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:n},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:i,fallback:"fail_open"}});}function se(n){let t=_(n);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join$1(t,e))&&unlinkSync(join$1(t,e));}catch{}}function Be(n,t){if(n.getHookReceipt(t)){se(t);return}let e=join$1(_(t),"receipt.json");if(!existsSync(e))return;let i=Ve(e);n.updateHookReceipt(t,()=>i),se(t);}function de(n,t,e){let i;try{i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),Be(i,n);let o={},r=i.updateHookReceipt(n,s=>(o=T(s),T(t(o)))),a=T(r);return {receipt:a,applied:!0,changed:!We(o,a)}}catch(o){return ze(n,e,o),{receipt:{},applied:false,changed:false}}finally{try{i?.close();}catch{}}}function Ge(n,t){return de(n,()=>t,"write").applied}function Ke(n,t){return de(n,t,"update")}var ce={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},Xe=new Set(["Write","Edit","NotebookEdit"]),Ye=new Set(["failed","timeout","unavailable"]);function Qe(n){switch(n){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var k=class{constructor(t,e,i){this.projectRoot=t;this.sessionId=e;this.executionId=i;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(e&&e.expiresAt>Date.now())return "context_ready";e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}return "context_gathering"}getContextReceipt(){if(!this.sessionId||!this.executionId)return null;let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);return e&&e.expiresAt>Date.now()?e:(e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId),null)}catch{return null}finally{try{t?.close();}catch{}}}evaluate(t,e){let i=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(i==="context_gathering"&&ce[t])return {permissionDecision:"deny",reasonCode:"DEVFLOW_CONTEXT_REQUIRED",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(i==="context_ready"){if(Xe.has(t)){let c=this.evaluateRequiredAction();if(c)return c}return {permissionDecision:"allow"}}let o=ce[t];if(!o)return {permissionDecision:"allow"};let r=Ke(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!r.applied)return {permissionDecision:"allow"};let a=r.receipt.bypassCount??0,s=Qe(t);return a>=s?{permissionDecision:"allow",additionalContext:`\u5DF2 ${a} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${o} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){Ge(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(t,e,i,o){if(!this.sessionId||!this.executionId)return false;let r;try{r=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let a=r.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(!a||a.expiresAt<=Date.now()||a.canonicalAction?.tool!==t)return !1;let s=Date.now(),c=o?.trim()?`${o.trim()}:${e}`:`${t}:${e}:${s}`,l=a.actionAttempts??[];return r.upsertContextReceipt({...a,actionAttempts:l.some(d=>d.id===c||o&&d.toolUseId===o&&d.status===e)?l:[...l,{id:c,tool:t,status:e,attemptedAt:s,toolUseId:o,reason:i?.slice(0,500)}].slice(-20),actionSatisfiedAt:e==="succeeded"?s:a.actionSatisfiedAt,actionDegradation:e==="succeeded"?void 0:a.actionDegradation}),!0}catch{return false}finally{try{r?.close();}catch{}}}evaluateRequiredAction(){let t=this.getContextReceipt(),e=t?.canonicalAction;if(!t||!e||!e.required||e.status!=="required")return null;let i=e.binding;if(i.requiredContextReceipt!==t.contextHash||i.projectRoot!==this.projectRoot||i.sessionId!==this.sessionId||i.requestId!==t.requestId||i.executionId&&i.executionId!==this.executionId)return {permissionDecision:"deny",reasonCode:"DEVFLOW_ACTION_BINDING_STALE",reason:"DevFlow canonical action binding is stale or mismatched. Call mcp__devflow__get_project_context again before writing."};if(t.actionSatisfiedAt)return null;if(t.actionDegradation?.authorizedByContextReceipt===t.contextHash)return {permissionDecision:"allow",additionalContext:`DevFlow degraded fallback authorized by context receipt ${t.contextHash}: ${t.actionDegradation.reason}`};let o=(t.actionAttempts??[]).filter(r=>r.tool===e.tool&&Ye.has(r.status));if(o.length>0){let r=o.at(-1),a={missedTool:e.tool,failedAttemptCount:o.length,reason:`${r.status}:${r.reason??"canonical domain action did not complete"}`,authorizedByContextReceipt:t.contextHash,authorizedAt:Date.now()};return this.persistDegradation(t,a),{permissionDecision:"allow",additionalContext:`DevFlow canonical tool mcp__devflow__${e.tool} ${r.status}; degraded direct write authorized by context receipt ${t.contextHash}. Preserve the action contract and verification plan.`}}return {permissionDecision:"deny",reasonCode:"DEVFLOW_REQUIRED_ACTION",reason:`DevFlow required action not completed. Call mcp__devflow__${e.tool} using context receipt ${t.contextHash}, then retry the write. Direct fallback is allowed only after unavailable, failed, or timeout evidence.`}}persistDegradation(t,e){let i;try{i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let o=i.getContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!o||o.contextHash!==t.contextHash||o.actionDegradation)return;i.upsertContextReceipt({...o,actionDegradation:e});let r=i.getSkillExecution(t.executionId);if(!r)return;let a=r.metadata&&typeof r.metadata=="object"?r.metadata:{},s=Array.isArray(a.requiredActionDegradations)?a.requiredActionDegradations:[];i.updateSkillExecution(t.executionId,{missedMcpTools:[...new Set([...r.missedMcpTools??[],e.missedTool])],failedToolCalls:Math.max(r.failedToolCalls??0,e.failedAttemptCount),fallbackCount:(r.fallbackCount??0)+1,fallbackReasons:[...new Set([...r.fallbackReasons??[],`required_action_${e.reason}`])],metadata:{...a,requiredActionDegradations:[...s,e]}});}catch{}finally{try{i?.close();}catch{}}}};function ue(n){let t=nt(n.projectRoot),e=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let i=it(e,{...n,projectRoot:t});return i?appendTaskRuntimeBoundary({projectRoot:i.projectRoot,taskSpec:taskSpecFromImmutableIntent(ot(i)),kind:n.kind,payload:n.payload,dedupeKey:n.dedupeKey,producer:n.producer,database:e})?.snapshot??null:null}catch(i){return emitSemanticControlLog({event:"task.runtime.shadow_mismatch",identity:{projectRoot:t,sessionId:n.sessionId,...n.turnId?{turnId:n.turnId}:{},...n.requestId?{requestId:n.requestId}:{}},level:"warn",timestamp:Date.now(),data:{stage:n.kind,reason:st(i),authority:"legacy"}}),null}finally{e.close();}}function nt(n){try{return realpathSync(n)}catch{return n}}function pe(n){if(!rt(n.legacyState))return;let t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:100});try{let e=t.getTaskRuntimeSnapshot(n.artifact.projectRoot,n.artifact.sessionId,n.artifact.turnId);if(!e)return;let i=at(n.legacyState);if(e.terminal===i)return;emitSemanticControlLog({event:"task.runtime.shadow_mismatch",identity:me(n.artifact),level:"warn",timestamp:Date.now(),data:{stage:"terminal_projection",legacyState:n.legacyState,shadowTerminal:e.terminal,expectedTerminal:i,authority:"legacy"}});}catch{}finally{t.close();}}function it(n,t){return n.listLatestTaskIntentArtifacts(t.projectRoot,t.sessionId).find(e=>t.turnId?e.turnId===t.turnId:t.requestId?e.requestId===t.requestId:true)}function ot(n){return {identity:me(n),version:n.version,...n.supersedesHash?{supersedesHash:n.supersedesHash}:{},rawPrompt:n.rawPrompt,normalizedPrompt:n.normalizedPrompt,...n.command?{command:n.command}:{},slashArgs:n.slashArgs,...n.activeSkill?{activeSkill:n.activeSkill}:{},intent:n.intent,action:n.action,entities:n.entities,targetAnchors:n.targetAnchors,policyConstraints:n.policyConstraints,classificationEvidence:n.classificationEvidence,sourceEventIds:n.sourceEventIds,sourceHash:n.sourceHash,artifactHash:n.artifactHash,createdAt:n.createdAt}}function me(n){return {projectRoot:n.projectRoot,projectId:n.projectId,hostId:n.hostId,sessionId:n.sessionId,turnId:n.turnId,requestId:n.requestId,...n.executionId?{executionId:n.executionId}:{}}}function rt(n){return n==="action_failed"||n==="closed"||n==="closed_with_degradation"||n==="closed_with_retry_work"}function at(n){return n==="closed"?"completed":n==="closed_with_degradation"?"completed_with_degradation":n==="closed_with_retry_work"?"retry_pending":"failed"}function st(n){return n instanceof Error?n.message:String(n)}var dt={open:["intent_bound"],intent_bound:["context_ready","context_degraded"],context_ready:["action_required","action_not_required"],context_degraded:["action_required","action_not_required"],action_required:["action_satisfied","action_degraded","action_failed"],action_not_required:["memory_decided","memory_quarantined"],action_satisfied:["memory_decided","memory_quarantined"],action_degraded:["memory_decided","memory_quarantined"],action_failed:["action_satisfied","action_degraded"],memory_decided:["closed","closed_with_degradation","closed_with_retry_work"],memory_quarantined:["closed_with_degradation","closed_with_retry_work"],closed:[],closed_with_degradation:[],closed_with_retry_work:[]};function lt(n){let t=ut(n);return pe({artifact:n.artifact,legacyState:t.toState}),t}function ut(n){let t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=gt(t,n.artifact);if(yt(e.toState))return e;let i=t.getContextReceiptForRequest(n.artifact.projectRoot,n.artifact.sessionId,n.artifact.requestId),o=n.artifact.intent==="memory";if(!i&&!o)return e;let r=i?pt(n.artifact,i):"context_ready";e.toState==="intent_bound"&&(e=p(t,e,n,r,o?"task_context_not_required":r==="context_ready"?"canonical_context_receipt_ready":"canonical_context_receipt_degraded"));let a=i?mt(n.artifact,i):"action_not_required";if((e.toState==="context_ready"||e.toState==="context_degraded")&&(a==="action_not_required"?e=p(t,e,n,"action_not_required","task_action_not_required"):e=p(t,e,n,"action_required","canonical_action_obligation_present")),e.toState==="action_required"){if(a==="action_required")return e;if(a==="action_failed")return p(t,e,n,"action_failed","canonical_action_attempt_failed");a==="action_degraded"?e=p(t,e,n,"action_degraded","canonical_action_unavailable_or_degraded"):a==="action_satisfied"&&(e=p(t,e,n,"action_satisfied","canonical_action_succeeded"));}if(e.toState==="action_failed")if(a==="action_satisfied")e=p(t,e,n,"action_satisfied","canonical_action_retry_succeeded");else if(a==="action_degraded")e=p(t,e,n,"action_degraded","canonical_action_retry_degraded");else return e;let s=r==="context_degraded"||a==="action_degraded";return ["action_not_required","action_satisfied","action_degraded"].includes(e.toState)&&(e=p(t,e,n,n.memoryStatus==="pending"?"memory_quarantined":"memory_decided",n.memoryStatus==="pending"?n.reason:`canonical_memory_${n.memoryStatus}`)),e.toState==="memory_decided"?p(t,e,n,s?"closed_with_degradation":"closed",n.reason):e.toState==="memory_quarantined"?p(t,e,n,n.retryOwned?"closed_with_retry_work":"closed_with_degradation",n.retryOwned?"durable_retry_owner_confirmed":"terminal_obligation_unowned"):e}finally{t.close();}}function ge(n){let t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=t.getActiveContextReceipt(n.projectRoot,n.sessionId,n.executionId),i=typeof e?.canonicalAction?.binding.turnId=="string"?e.canonicalAction.binding.turnId:void 0;if(!i)return null;let o=t.listLatestTaskIntentArtifacts(n.projectRoot,n.sessionId).find(a=>a.turnId===i),r=t.getMemoryTurn(i);return !o||!r?null:lt({artifact:o,memoryStatus:r.status,memoryReceiptId:r.receiptId,reason:n.reason})}finally{t.close();}}function pt(n,t){return n.intent==="memory"||n.intent==="knowledge"||(t.selectedFiles?.length??0)>0?"context_ready":"context_degraded"}function mt(n,t){let e=t.canonicalAction,o=(e?(t.actionAttempts??[]).filter(r=>r.tool===e.tool):[]).at(-1);return t.actionSatisfiedAt||o?.status==="succeeded"?"action_satisfied":o&&["failed","timeout","unavailable"].includes(o.status)?"action_failed":t.actionDegradation||e?.status==="degraded"||e?.status==="unsupported"?"action_degraded":e?.required||ft(n)?"action_required":"action_not_required"}function ft(n){return ["create","modify","debug","test","format"].includes(n.action)||["feature","refactor","performance"].includes(n.intent)}function gt(n,t){let e=n.getLatestTerminalTransition(t.projectRoot,t.sessionId,t.turnId);if(!e)throw new Error(`TERMINAL_INTENT_STATE_MISSING:${t.turnId}`);return e}function p(n,t,e,i,o){if(!dt[t.toState]?.includes(i))throw new Error(`TERMINAL_PATH_UNAVAILABLE:${t.toState}->${i}`);let r=t.sequence+1,a=`terminal:${createHash$1("sha256").update(`${e.artifact.artifactHash}\0${r}\0${i}`).digest("hex").slice(0,24)}`,s=n.appendTerminalTransition({projectRoot:e.artifact.projectRoot,projectId:e.artifact.projectId,hostId:e.artifact.hostId,sessionId:e.artifact.sessionId,turnId:e.artifact.turnId,requestId:e.artifact.requestId,executionId:e.artifact.executionId,sequence:r,fromState:t.toState,toState:i,receiptId:a,sourceReceiptId:e.memoryReceiptId??t.receiptId,reason:o,payload:{memoryStatus:e.memoryStatus,retryOwned:e.retryOwned??false,sourceIntentHash:e.artifact.artifactHash},createdAt:Date.now()});return emitSemanticControlLog({event:"terminal.state.transitioned",identity:{projectRoot:e.artifact.projectRoot,projectId:e.artifact.projectId,hostId:e.artifact.hostId,sessionId:e.artifact.sessionId,turnId:e.artifact.turnId,requestId:e.artifact.requestId,...e.artifact.executionId?{executionId:e.artifact.executionId}:{}},level:i==="closed"?"info":i.includes("degradation")||i.includes("retry")||i==="action_failed"?"warn":"info",timestamp:Date.now(),data:{fromState:t.toState,nextState:i,receiptId:a,reason:o}}),s}function yt(n){return n==="closed"||n==="closed_with_degradation"||n==="closed_with_retry_work"}var g=process.env.CLAUDE_PROJECT_DIR||process.cwd();function ye(n,t){let e=Number(n);return Number.isInteger(e)&&e>=0?e:t}async function _t(n,t){let e=t.timeoutMs??ye(process.env.DEVFLOW_FAILURE_TIMEOUT_MS,1500),i=t.maxRetries??ye(process.env.DEVFLOW_FAILURE_MAX_RETRIES,0),o=`/api/memory/session-events?rootPath=${encodeURIComponent(g)}`,r=await R(o,n,{timeout:e,maxRetries:i,durableMirror:true,fallbackReason:"tool_failure_persisted_in_local_telemetry"});if(!r.delivered)throw new Error(r.fallbackReason??"post_tool_failure_delivery_failed")}async function vt(n,t={}){let e;try{e=JSON.parse(n);}catch{return}let i=e.tool_name||"",o=e.tool_input||{},r=e.error||"",a=e.session_id?.trim();if(!a)return;let s=new S(g).registerSession(a);if(i.startsWith("mcp__devflow__")){let I=/timeout|timed out|deadline/i.test(r)?"timeout":/unavailable|not active|unknown tool|not found|not registered|route not found/i.test(r)?"unavailable":"failed";if(new k(g,a,s.executionId??a).recordDomainActionOutcome(i.replace(/^mcp__[^_]+__/,""),I,r,e.tool_use_id)){ue({projectRoot:g,sessionId:a,executionId:s.executionId??a,kind:"action.failed",payload:{receiptId:e.tool_use_id??`${i}:failed`,reasonCode:I==="timeout"?"canonical_action_timeout":I==="unavailable"?"canonical_action_unavailable":"canonical_action_failed",tool:i.replace(/^mcp__[^_]+__/,"")},dedupeKey:`${e.tool_use_id??i}:${I}`,producer:"devflow-post-tool-use-failure"});try{ge({projectRoot:g,sessionId:a,executionId:s.executionId??a,reason:"post_tool_use_failure"});}catch{}}}let c=ae(a,e.tool_use_id),l=classifyWorkflowFailure({stepId:i,toolName:i,error:new Error(r||`${i||"tool"} failed`),errorStack:r||void 0}),d=typeof o=="object"&&o.command?o.command:i,u={id:`memory:${c}`,sessionId:a,tool:i,command:d,exitCode:-1,stderr:r,durationMs:0,createdAt:Date.now(),kind:i==="Bash"?"bash_error":"tool_use",payload:{command:d,exitCode:-1,stderr:r,failureSource:"PostToolUseFailure",failureCategory:l.category}},m=!t.telemetryClient,x=t.telemetryClient??new w,b=i.startsWith("mcp__"),he={eventId:c,executionId:s.executionId??a,sessionId:a,projectRoot:g,toolUseId:e.tool_use_id,timestamp:u.createdAt,toolName:i,toolType:b?"mcp":"direct",isMcpTool:b,mcpToolName:b?i:void 0,mcpEnforced:b,mcpFallback:false,kind:"error",input:o,duration:0,error:r,blocked:false,failureCategory:l.category};try{await x.sendEvent(he),await x.completeEvent({eventId:c,sessionId:a,error:r,duration:0,completedAt:Date.now()});}finally{m&&x.close();}t.eventDelivery?await t.eventDelivery(u):await _t(u,t);}if(process.argv[1]?.endsWith("post-tool-use-failure")||process.argv[1]?.endsWith("post-tool-use-failure.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{try{await vt(t.trim()||process.argv[2]||""),n(JSON.stringify({status:"ok"}));}catch(e){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:g},level:"warn",timestamp:Date.now(),data:{stage:"post_tool_failure_delivery",reason:e.message,fallback:"durable_retry_on_next_runtime"}}),n(JSON.stringify({status:"degraded",reason:"post_tool_failure_delivery_failed",fallback:"durable_retry_on_next_runtime"}));}}),process.stdin.on("error",e=>{emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:g},level:"warn",timestamp:Date.now(),data:{stage:"post_tool_failure_input",reason:e.message,fallback:"host_event_continues"}}),n(JSON.stringify({status:"degraded",reason:"post_tool_failure_input_failed",fallback:"host_event_continues"}));});}export{vt as handlePostToolUseFailure};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,linkSync,readdirSync,renameSync,unlinkSync}from'fs';import {join as join$1,dirname}from'path';import {getLogWriter,emitSemanticControlLog}from'@devflow-tools/telemetry';import {request}from'node:http';import {existsSync as existsSync$1,
|
|
2
|
-
`);}catch{}}function it(n){return new Promise(t=>setTimeout(t,n))}function W(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function y(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(W(n))}function O(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let t=n,e={};for(let i of ["lastMcpCall","bypassCount"])if(i in t){let r=t[i];if(r==null)continue;e[i]=typeof r=="number"&&Number.isFinite(r)&&r>=0?r:0;}return e}function at(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function ct(n){try{return existsSync(n)?O(JSON.parse(readFileSync(n,"utf-8"))):{}}catch{return {}}}function lt(n,t,e){let i=e instanceof Error?e.message:String(e);emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:n},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:i,fallback:"fail_open"}});}function fe(n){let t=y(n);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join$1(t,e))&&unlinkSync(join$1(t,e));}catch{}}function dt(n,t){if(n.getHookReceipt(t)){fe(t);return}let e=join$1(y(t),"receipt.json");if(!existsSync(e))return;let i=ct(e);n.updateHookReceipt(t,()=>i),fe(t);}function me(n,t,e){let i;try{i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),dt(i,n);let r={},o=i.updateHookReceipt(n,a=>(r=O(a),O(t(r)))),s=O(o);return {receipt:s,applied:!0,changed:!at(r,s)}}catch(r){return lt(n,e,r),{receipt:{},applied:false,changed:false}}finally{try{i?.close();}catch{}}}function G(n,t){return me(n,()=>t,"write").applied}function K(n,t){return me(n,t,"update")}var ge={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},ut=new Set(["Write","Edit","NotebookEdit"]),pt=new Set(["failed","timeout","unavailable"]);function ft(n){switch(n){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var T=class{constructor(t,e,i){this.projectRoot=t;this.sessionId=e;this.executionId=i;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(e&&e.expiresAt>Date.now())return "context_ready";e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}return "context_gathering"}getContextReceipt(){if(!this.sessionId||!this.executionId)return null;let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);return e&&e.expiresAt>Date.now()?e:(e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId),null)}catch{return null}finally{try{t?.close();}catch{}}}evaluate(t,e){let i=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(i==="context_gathering"&&ge[t])return {permissionDecision:"deny",reasonCode:"DEVFLOW_CONTEXT_REQUIRED",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(i==="context_ready"){if(ut.has(t)){let c=this.evaluateRequiredAction();if(c)return c}return {permissionDecision:"allow"}}let r=ge[t];if(!r)return {permissionDecision:"allow"};let o=K(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!o.applied)return {permissionDecision:"allow"};let s=o.receipt.bypassCount??0,a=ft(t);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${r} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){G(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(t,e,i,r){if(!this.sessionId||!this.executionId)return false;let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let s=o.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(!s||s.expiresAt<=Date.now()||s.canonicalAction?.tool!==t)return !1;let a=Date.now(),c=r?.trim()?`${r.trim()}:${e}`:`${t}:${e}:${a}`,l=s.actionAttempts??[];return o.upsertContextReceipt({...s,actionAttempts:l.some(d=>d.id===c||r&&d.toolUseId===r&&d.status===e)?l:[...l,{id:c,tool:t,status:e,attemptedAt:a,toolUseId:r,reason:i?.slice(0,500)}].slice(-20),actionSatisfiedAt:e==="succeeded"?a:s.actionSatisfiedAt,actionDegradation:e==="succeeded"?void 0:s.actionDegradation}),!0}catch{return false}finally{try{o?.close();}catch{}}}evaluateRequiredAction(){let t=this.getContextReceipt(),e=t?.canonicalAction;if(!t||!e||!e.required||e.status!=="required")return null;let i=e.binding;if(i.requiredContextReceipt!==t.contextHash||i.projectRoot!==this.projectRoot||i.sessionId!==this.sessionId||i.requestId!==t.requestId||i.executionId&&i.executionId!==this.executionId)return {permissionDecision:"deny",reasonCode:"DEVFLOW_ACTION_BINDING_STALE",reason:"DevFlow canonical action binding is stale or mismatched. Call mcp__devflow__get_project_context again before writing."};if(t.actionSatisfiedAt)return null;if(t.actionDegradation?.authorizedByContextReceipt===t.contextHash)return {permissionDecision:"allow",additionalContext:`DevFlow degraded fallback authorized by context receipt ${t.contextHash}: ${t.actionDegradation.reason}`};let r=(t.actionAttempts??[]).filter(o=>o.tool===e.tool&&pt.has(o.status));if(r.length>0){let o=r.at(-1),s={missedTool:e.tool,failedAttemptCount:r.length,reason:`${o.status}:${o.reason??"canonical domain action did not complete"}`,authorizedByContextReceipt:t.contextHash,authorizedAt:Date.now()};return this.persistDegradation(t,s),{permissionDecision:"allow",additionalContext:`DevFlow canonical tool mcp__devflow__${e.tool} ${o.status}; degraded direct write authorized by context receipt ${t.contextHash}. Preserve the action contract and verification plan.`}}return {permissionDecision:"deny",reasonCode:"DEVFLOW_REQUIRED_ACTION",reason:`DevFlow required action not completed. Call mcp__devflow__${e.tool} using context receipt ${t.contextHash}, then retry the write. Direct fallback is allowed only after unavailable, failed, or timeout evidence.`}}persistDegradation(t,e){let i;try{i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let r=i.getContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!r||r.contextHash!==t.contextHash||r.actionDegradation)return;i.upsertContextReceipt({...r,actionDegradation:e});let o=i.getSkillExecution(t.executionId);if(!o)return;let s=o.metadata&&typeof o.metadata=="object"?o.metadata:{},a=Array.isArray(s.requiredActionDegradations)?s.requiredActionDegradations:[];i.updateSkillExecution(t.executionId,{missedMcpTools:[...new Set([...o.missedMcpTools??[],e.missedTool])],failedToolCalls:Math.max(o.failedToolCalls??0,e.failedAttemptCount),fallbackCount:(o.fallbackCount??0)+1,fallbackReasons:[...new Set([...o.fallbackReasons??[],`required_action_${e.reason}`])],metadata:{...s,requiredActionDegradations:[...a,e]}});}catch{}finally{try{i?.close();}catch{}}}};var Re=1e4,bt=3e4,P=500,j=class{constructor(t){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=t?.apiUrl,this.cacheDir=t?.cacheDir??join$1(process.env.DEVFLOW_STATE_DIR??join$1(homedir$1(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join$1(homedir$1(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}async sendEvent(t){let e={...t,input:this.truncateInput(t.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),t.eventId):null}async sendExecutionStart(t,e,i,r,o=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:i,startedAt:r,projectRoot:o,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",i=Date.now(),r){let o={executionId:t,status:e,finishedAt:i,metadata:r},s=this.commitOrCache("execution_complete",o);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",o),s}async sendSessionStart(t,e,i){let r={id:t,projectRoot:e,startedAt:i,label:e.split("/").pop()??"unknown"},o=this.commitOrCache("session_start",r);return o&&this.postHttp("/api/telemetry/sessions",r),o}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let i={sessionId:t,finishedAt:e},r=this.commitOrCache("session_end",i);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),r}async flushCache(){try{let i=this.getDatabase(),r=i.listTelemetryFailures({unresolvedOnly:!0,limit:P}).reverse();for(let o of r)try{this.applyOperation(o.operation,o.payload),i.resolveTelemetryFailure(o.id);}catch{}i.trimTelemetryFailures(P);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(i=>!!i))].filter(i=>existsSync(i)).flatMap(i=>readdirSync(i).filter(r=>r.endsWith(".json")).map(r=>{let o=join$1(i,r);try{return {cacheFile:o,envelope:vt(JSON.parse(readFileSync(o,"utf8")),r)}}catch{return null}})).filter(i=>i!==null).sort((i,r)=>i.envelope.timestamp-r.envelope.timestamp||we(i.envelope.operation)-we(r.envelope.operation));for(let{cacheFile:i,envelope:r}of e)try{let o=this.getDatabase();o.insertTelemetryFailure({id:r.id,operation:r.operation,payload:r.payload,error:r.failure,createdAt:r.timestamp}),this.applyOperation(r.operation,r.payload),o.resolveTelemetryFailure(r.id),unlinkSync(i);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(i){return this.cacheOperation(t,e,i),false}}applyOperation(t,e){let i=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(i,e),i.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(i,e),i.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":i.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":i.ensureSession(e),i.insertRun({id:_e(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!i.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,failureCategory:e.failureCategory,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":i.closeSession(e.sessionId,e.finishedAt),i.updateRun(_e(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let i=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!i)throw new Error("Canonical session ID is required for telemetry");let r=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:i,projectRoot:r,label:r==="unknown"?void 0:r.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,i){let r=Date.now(),o={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:i instanceof Error?i.message:String(i),timestamp:r};try{let s=this.getDatabase();s.insertTelemetryFailure({id:o.id,operation:t,payload:e,error:o.failure,createdAt:r}),s.trimTelemetryFailures(P),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${r}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(o,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of t.slice(0,Math.max(0,t.length-P)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},bt).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(t,e){C(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=Re?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,Re)}...`}}};function we(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function _e(n){return `hook-run:${n}`}function vt(n,t){if(!n||typeof n!="object")throw new Error("Invalid telemetry cache envelope");let e=n;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let i=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!i)throw new Error("Unknown legacy telemetry cache operation");let r=e.payload??{},o=Number(r.timestamp??r.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:i,payload:r,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:o}}function Ee(n){return Buffer.from(n,"utf8").toString("base64url")}function It(n,t,e){let i=t?.trim();if(i){let r=/^[a-zA-Z0-9:._-]{1,192}$/.test(i)?i:`tool-${createHash("sha256").update(i.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${r}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function Te(n){return `${n}:legacy-journal`}var E=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(y(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let i=this.get(e);if(i)return i.lastActivityAt=Date.now(),this.persist(i),i;let r=Date.now(),o={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:r,lastActivityAt:r};return this.sessions.set(e,o),this.persist(o),o}startExecution(t,e,i){let r=this.registerSession(t);return (!r.executionId||r.skillName!==e)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=e,r.requiredMcpTools=[...new Set(i)],r.lastActivityAt=Date.now(),this.persist(r),r}bindTaskIdentity(t,e){let i=this.registerSession(t);return i.activeTurnId=e.turnId,i.activeRequestId=e.requestId,i.intentArtifactHash=e.intentArtifactHash,i.lastActivityAt=Date.now(),this.persist(i),i}get(t){let e=t.trim();if(!e)return null;let i=this.sessions.get(e);if(i)return this.replayEvidenceJournal(i),i;let r=this.snapshotPath(e);if(!existsSync(r))return null;try{let o=JSON.parse(readFileSync(r,"utf8"));return o.sessionId!==e||o.projectRoot!==this.projectRoot?null:(o.requiredMcpTools=Array.isArray(o.requiredMcpTools)?o.requiredMcpTools:[],o.evidenceObligations=Se(o.evidenceObligations),o.evidenceDegradations=Ae(o.evidenceDegradations),o.evidenceOutcomes=De(o.evidenceOutcomes),this.replayEvidenceJournal(o),this.sessions.set(e,o),o)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let i=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),i}addEvidenceObligation(t,e,i=Date.now(),r){let o=this.registerSession(t),a=(r?void 0:o.evidenceObligations.find(l=>l.contractId===e.id))?.obligationId??It(e.id,r,i);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:i,contract:e},`add\0${a}`),this.replayEvidenceJournal(o);let c=o.evidenceObligations.find(l=>l.obligationId===a);return c?(o.lastActivityAt=Date.now(),this.persist(o),structuredClone(c)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,i,r,o=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(r)?r:"";if(!c)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:o,fingerprint:c,violations:i.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=o,this.persist(s);let l=s.evidenceObligations.find(d=>d.obligationId===e);return l?structuredClone(l):null}resolveEvidenceObligation(t,e){let i=this.get(t);if(!i)return false;let r=i.evidenceObligations.find(s=>s.obligationId===e);if(!r)return false;let o=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:r.contractId,at:o},`resolve\0${e}`),this.replayEvidenceJournal(i),i.lastActivityAt=o,this.persist(i),true}degradeEvidenceObligation(t,e,i,r=Date.now()){let o=this.get(t),s=o?.evidenceObligations.find(c=>c.obligationId===e);if(!o||!s)return false;let a=i.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:r,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(o),o.lastActivityAt=r,this.persist(o),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${Ee(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Ee(t))}appendEvidenceEvent(t,e,i){let r=this.evidenceJournalDir(t);mkdirSync(r,{recursive:true,mode:448});let o=createHash("sha256").update(i).digest("hex"),s=join$1(r,`${e.kind}-${o}.json`);if(existsSync(s))return;let a=join$1(r,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Se(t.evidenceObligations),t.evidenceDegradations=Ae(t.evidenceDegradations),t.evidenceOutcomes=De(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let i;try{i=readdirSync(e).filter(o=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(o)).slice(0,4096);}catch{return}let r=i.flatMap(o=>{try{let s=readFileSync(join$1(e,o),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=xt(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((o,s)=>o.at-s.at||Ce(o.kind)-Ce(s.kind));for(let o of r)this.applyEvidenceEvent(t,o);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let i=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(i)return;let s=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let r=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!r||i||r.correctionFingerprint===e.fingerprint)return;r.attempt+=1,r.correctionRequested=true,r.correctionRequestedAt=e.at,r.correctionFingerprint=e.fingerprint,r.violations=e.violations;return}let o=r?.attempt??0;t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),!i&&(e.kind==="degrade"&&t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:o}),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:o,...e.kind==="degrade"?{reason:e.reason}:{}}));}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),i=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(i,JSON.stringify(t),{mode:384}),renameSync(i,e);}};function Se(n){return Array.isArray(n)?n.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!Pe(e.contract))return [];let i=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Te(e.contractId),r=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,o=e.correctionFingerprint??r;return o!==void 0&&!/^[a-f0-9]{64}$/.test(o)?[]:[{...e,obligationId:i,correctionFingerprint:o}]}).slice(-8):[]}function Ae(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function De(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function xt(n){if(!n||typeof n!="object")return null;let t=n,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let r={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:Te(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return Pe(t.contract)?{kind:e,...r,contract:t.contract}:null;if(e==="correction"){let o=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof o=="string"&&/^[a-f0-9]{64}$/.test(o)&&Array.isArray(t.violations)&&t.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:e,...r,fingerprint:o,violations:t.violations}:null}return e==="resolve"?{kind:e,...r}:typeof t.reason=="string"&&t.reason.length<=240?{kind:e,...r,reason:t.reason}:null}function Ce(n){return n==="add"?0:n==="correction"?1:2}function Pe(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,i=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(i)&&i.length<=16&&i.every(r=>typeof r=="string"&&r.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}var Dt=2,Ct=1;function Ot(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{return join$1(dirname(fileURLToPath(import.meta.url)),"..","..")}catch{return process.cwd()}}function je(n=Ot()){let t=[join$1(n,"dist","command-registry.json"),join$1(n,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let i=JSON.parse(readFileSync(e,"utf8"));if(i.version!==Dt&&i.version!==Ct||!Tt(i.commands)){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:"contract_mismatch",registryPath:e}});continue}return i.commands}catch(i){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:i.message,fallback:"next_registry_candidate"}});}return null}function Tt(n){return !n||typeof n!="object"||Array.isArray(n)?false:Object.values(n).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return F(e.mcpTools)&&F(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||F(e.runtimePackages))&&(e.hostTools===void 0||Pt(e.hostTools))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function Pt(n){return !!n&&typeof n=="object"&&!Array.isArray(n)&&Object.entries(n).every(([t,e])=>t.length>0&&F(e))}function F(n){return Array.isArray(n)&&n.every(t=>typeof t=="string"&&t.length>0)}function $e(n){let t=je();return t?t[n]?.mcpTools??[]:[]}function Fe(n){let t=n.trim().replace(/^\//,"");if(!t.startsWith("devflow:"))return null;let e=t.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(e)?`devflow:${e.toLowerCase()}`:null}function Me(n,t){return t?`evt_tool_${createHash("sha256").update(`${n}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var Ft=256*1024,Mt=48*1024;var Nt=5,M=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function qt(n){return n==="react_audit_performance"||n.endsWith("__react_audit_performance")}function Lt(n){let t=S(n,0,new Set);return t?Ut(t.contract,t.canonicalReport):null}function Ne(n){if(!n.sessionId||!qt(n.toolName))return null;let t=Lt(n.toolResponse);if(!t)return null;let e=Date.now(),i=n.runtimeStore.addEvidenceObligation(n.sessionId,t,e,n.toolUseId),r=n.runtimeStore.get(n.sessionId);if(i&&r){let o=openGlobalDevFlowDatabase();try{o.upsertSessionObligation({obligationId:`evidence:${i.obligationId}`,projectRoot:r.projectRoot,sessionId:n.sessionId,executionId:r.executionId,kind:"evidence_contract",state:"open",payload:{contract:t,runtimeObligationId:i.obligationId},createdAt:e,updatedAt:e});}finally{o.close();}}return Ht(t)}function Ht(n){return [`DevFlow performance evidence contract ${n.id} is active.`,`The final performance answer MUST contain these three sections exactly: ${n.requiredSections.join(" / ")}.`,n.runtimeProfilingOccurred?"Only claims directly supported by the returned runtime measurements may be stated as measured facts.":"No runtime profiling occurred. Treat every finding as a static candidate: do not assign P0/high-risk severity, claim a confirmed bottleneck/jank/frame drop/CPU hotspot, quantify performance or benefit, or recommend requestAnimationFrame as generic throttling without sampling evidence.",`samplingEvidenceOccurred=${n.samplingEvidenceOccurred}. RAF recommendations are permitted only when this structured contract field is true; answer text cannot self-declare sampling evidence.`,"Use the canonical report below directly or preserve its evidence boundaries. Stop will request one correction for unsupported claims, then fail open with degradation telemetry.",n.canonicalReport].join(`
|
|
1
|
+
import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,linkSync,readdirSync,renameSync,unlinkSync}from'fs';import {join as join$1,dirname as dirname$1}from'path';import {getLogWriter,emitSemanticControlLog}from'@devflow-tools/telemetry';import {request}from'node:http';import {mkdirSync as mkdirSync$1,appendFileSync,realpathSync,existsSync as existsSync$1,readFileSync as readFileSync$1,writeFileSync as writeFileSync$1,renameSync as renameSync$1,readdirSync as readdirSync$1}from'node:fs';import {join,dirname,relative,resolve,isAbsolute,sep}from'node:path';import {homedir}from'node:os';import {getLocalApiKey,appendTaskRuntimeBoundary,taskSpecFromImmutableIntent,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {homedir as homedir$1}from'os';import {randomUUID,createHash}from'crypto';import {fileURLToPath}from'url';import {createHash as createHash$1}from'node:crypto';import {classifyWorkflowFailure}from'@devflow-tools/workflow-engine/failure-classifier';function K(t,n,e){try{let i=openGlobalDevFlowDatabase();try{i.insertEvent({kind:t,timestamp:Date.now(),duration:e,success:n.success!==!1,metadata:n});}finally{i.close();}}catch{}}var bt=getLocalApiKey(),Y=join(homedir(),".devflow","errors");async function j(t,n,e={}){let i=e.endpoint??resolveRuntimeEndpoint().url,o=e.timeout??1500,r=e.durableMirror??true,s=e.maxRetries??(r?0:2),a=e.circuitBreaker??true,c=acquireRuntimeHttpCircuit(i,t);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let l;for(let u=0;u<=s;u+=1)try{return await vt(i,t,n,o),a&®isterRuntimeHttpSuccess(i,t).transitioned&&K("http_circuit_transition",{endpoint:i,path:new URL(t,i).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(f){l=f instanceof Error?f:new Error(String(f)),u<s&&await It(Math.min(100*2**u,1e3));}if(!l)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return he(t,l),{delivered:false,suppressed:false,fallbackReason:l.message};let d=registerRuntimeHttpFailure(i,t,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return d.transitioned&&(he(t,l),K("http_circuit_transition",{endpoint:i,path:new URL(t,i).pathname,previous:c.state.status,status:"open",failures:d.state.failures,openUntil:d.state.openUntil,fallbackReason:d.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:d.state.fallbackReason}}function vt(t,n,e,i){return new Promise((o,r)=>{let s=JSON.stringify(e),a=new URL(n,t),c=false,l=u=>{c||(c=true,u?r(u):o());},d=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":bt,"Content-Length":Buffer.byteLength(s)},timeout:i},u=>{u.on("error",l),u.on("end",()=>{let f=u.statusCode??0;l(f>=200&&f<300?void 0:new Error(`HTTP ${f}`));}),u.resume();});d.on("error",l),d.on("timeout",()=>d.destroy(new Error(`HTTP mirror timed out after ${i}ms`))),d.write(s),d.end();})}function he(t,n){try{existsSync$1(Y)||mkdirSync$1(Y,{recursive:!0}),appendFileSync(join(Y,"http-errors.log"),`${new Date().toISOString()} | ${t} | ${n.message}
|
|
2
|
+
`);}catch{}}function It(t){return new Promise(n=>setTimeout(n,t))}function Z(t){return t??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function b(t){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(Z(t))}function F(t){if(!t||typeof t!="object"||Array.isArray(t))return {};let n=t,e={};for(let i of ["lastMcpCall","bypassCount"])if(i in n){let o=n[i];if(o==null)continue;e[i]=typeof o=="number"&&Number.isFinite(o)&&o>=0?o:0;}return e}function xt(t,n){return t.lastMcpCall===n.lastMcpCall&&t.bypassCount===n.bypassCount}function St(t){try{return existsSync(t)?F(JSON.parse(readFileSync(t,"utf-8"))):{}}catch{return {}}}function kt(t,n,e){let i=e instanceof Error?e.message:String(e);emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:t},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:n,reason:i,fallback:"fail_open"}});}function ve(t){let n=b(t);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join$1(n,e))&&unlinkSync(join$1(n,e));}catch{}}function Et(t,n){if(t.getHookReceipt(n)){ve(n);return}let e=join$1(b(n),"receipt.json");if(!existsSync(e))return;let i=St(e);t.updateHookReceipt(n,()=>i),ve(n);}function _e(t,n,e){let i;try{i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),Et(i,t);let o={},r=i.updateHookReceipt(t,a=>(o=F(a),F(n(o)))),s=F(r);return {receipt:s,applied:!0,changed:!xt(o,s)}}catch(o){return kt(t,e,o),{receipt:{},applied:false,changed:false}}finally{try{i?.close();}catch{}}}function ee(t,n){return _e(t,()=>n,"write").applied}function te(t,n){return _e(t,n,"update")}var Ie={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},At=new Set(["Write","Edit","NotebookEdit"]),Dt=new Set(["failed","timeout","unavailable"]);function Tt(t){switch(t){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var P=class{constructor(n,e,i){this.projectRoot=n;this.sessionId=e;this.executionId=i;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=n.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(e&&e.expiresAt>Date.now())return "context_ready";e&&n.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{n?.close();}catch{}}return "context_gathering"}getContextReceipt(){if(!this.sessionId||!this.executionId)return null;let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=n.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);return e&&e.expiresAt>Date.now()?e:(e&&n.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId),null)}catch{return null}finally{try{n?.close();}catch{}}}evaluate(n,e){let i=this.getPhase();if(e||n==="Skill")return {permissionDecision:"allow"};if(i==="context_gathering"&&Ie[n])return {permissionDecision:"deny",reasonCode:"DEVFLOW_CONTEXT_REQUIRED",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${n}.`};if(i==="context_ready"){if(At.has(n)){let c=this.evaluateRequiredAction();if(c)return c}return {permissionDecision:"allow"}}let o=Ie[n];if(!o)return {permissionDecision:"allow"};let r=te(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!r.applied)return {permissionDecision:"allow"};let s=r.receipt.bypassCount??0,a=Tt(n);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${n}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${o} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){ee(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(n,e,i,o){if(!this.sessionId||!this.executionId)return false;let r;try{r=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let s=r.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(!s||s.expiresAt<=Date.now()||s.canonicalAction?.tool!==n)return !1;let a=Date.now(),c=o?.trim()?`${o.trim()}:${e}`:`${n}:${e}:${a}`,l=s.actionAttempts??[];return r.upsertContextReceipt({...s,actionAttempts:l.some(d=>d.id===c||o&&d.toolUseId===o&&d.status===e)?l:[...l,{id:c,tool:n,status:e,attemptedAt:a,toolUseId:o,reason:i?.slice(0,500)}].slice(-20),actionSatisfiedAt:e==="succeeded"?a:s.actionSatisfiedAt,actionDegradation:e==="succeeded"?void 0:s.actionDegradation}),!0}catch{return false}finally{try{r?.close();}catch{}}}evaluateRequiredAction(){let n=this.getContextReceipt(),e=n?.canonicalAction;if(!n||!e||!e.required||e.status!=="required")return null;let i=e.binding;if(i.requiredContextReceipt!==n.contextHash||i.projectRoot!==this.projectRoot||i.sessionId!==this.sessionId||i.requestId!==n.requestId||i.executionId&&i.executionId!==this.executionId)return {permissionDecision:"deny",reasonCode:"DEVFLOW_ACTION_BINDING_STALE",reason:"DevFlow canonical action binding is stale or mismatched. Call mcp__devflow__get_project_context again before writing."};if(n.actionSatisfiedAt)return null;if(n.actionDegradation?.authorizedByContextReceipt===n.contextHash)return {permissionDecision:"allow",additionalContext:`DevFlow degraded fallback authorized by context receipt ${n.contextHash}: ${n.actionDegradation.reason}`};let o=(n.actionAttempts??[]).filter(r=>r.tool===e.tool&&Dt.has(r.status));if(o.length>0){let r=o.at(-1),s={missedTool:e.tool,failedAttemptCount:o.length,reason:`${r.status}:${r.reason??"canonical domain action did not complete"}`,authorizedByContextReceipt:n.contextHash,authorizedAt:Date.now()};return this.persistDegradation(n,s),{permissionDecision:"allow",additionalContext:`DevFlow canonical tool mcp__devflow__${e.tool} ${r.status}; degraded direct write authorized by context receipt ${n.contextHash}. Preserve the action contract and verification plan.`}}return {permissionDecision:"deny",reasonCode:"DEVFLOW_REQUIRED_ACTION",reason:`DevFlow required action not completed. Call mcp__devflow__${e.tool} using context receipt ${n.contextHash}, then retry the write. Direct fallback is allowed only after unavailable, failed, or timeout evidence.`}}persistDegradation(n,e){let i;try{i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let o=i.getContextReceipt(n.projectRoot,n.sessionId,n.executionId);if(!o||o.contextHash!==n.contextHash||o.actionDegradation)return;i.upsertContextReceipt({...o,actionDegradation:e});let r=i.getSkillExecution(n.executionId);if(!r)return;let s=r.metadata&&typeof r.metadata=="object"?r.metadata:{},a=Array.isArray(s.requiredActionDegradations)?s.requiredActionDegradations:[];i.updateSkillExecution(n.executionId,{missedMcpTools:[...new Set([...r.missedMcpTools??[],e.missedTool])],failedToolCalls:Math.max(r.failedToolCalls??0,e.failedAttemptCount),fallbackCount:(r.fallbackCount??0)+1,fallbackReasons:[...new Set([...r.fallbackReasons??[],`required_action_${e.reason}`])],metadata:{...s,requiredActionDegradations:[...a,e]}});}catch{}finally{try{i?.close();}catch{}}}};var ke=1e4,Pt=3e4,$=500,q=class{constructor(n){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=n?.apiUrl,this.cacheDir=n?.cacheDir??join$1(process.env.DEVFLOW_STATE_DIR??join$1(homedir$1(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=n?.legacyCacheDir??(n?.cacheDir?null:join$1(homedir$1(),".devflow","telemetry-cache")),this.database=n?.database??null,this.ownsDatabase=!n?.database;let e=n?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}async sendEvent(n){let e={...n,input:this.truncateInput(n.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),n.eventId):null}async sendExecutionStart(n,e,i,o,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:n,sessionId:e,skillName:i,startedAt:o,projectRoot:r,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(n,e="completed",i=Date.now(),o){let r={executionId:n,status:e,finishedAt:i,metadata:o},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(n,e,i){let o={id:n,projectRoot:e,startedAt:i,label:e.split("/").pop()??"unknown"},r=this.commitOrCache("session_start",o);return r&&this.postHttp("/api/telemetry/sessions",o),r}async completeEvent(n){let e=this.commitOrCache("complete_event",n);return e&&(this.postHttp("/api/telemetry/tool-call/output",n),this.scheduleMetricAggregation()),e}async endSession(n,e=Date.now()){let i={sessionId:n,finishedAt:e},o=this.commitOrCache("session_end",i);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(n)}/close`,{finishedAt:e})),o}async flushCache(){try{let i=this.getDatabase(),o=i.listTelemetryFailures({unresolvedOnly:!0,limit:$}).reverse();for(let r of o)try{this.applyOperation(r.operation,r.payload),i.resolveTelemetryFailure(r.id);}catch{}i.trimTelemetryFailures($);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(i=>!!i))].filter(i=>existsSync(i)).flatMap(i=>readdirSync(i).filter(o=>o.endsWith(".json")).map(o=>{let r=join$1(i,o);try{return {cacheFile:r,envelope:$t(JSON.parse(readFileSync(r,"utf8")),o)}}catch{return null}})).filter(i=>i!==null).sort((i,o)=>i.envelope.timestamp-o.envelope.timestamp||Ee(i.envelope.operation)-Ee(o.envelope.operation));for(let{cacheFile:i,envelope:o}of e)try{let r=this.getDatabase();r.insertTelemetryFailure({id:o.id,operation:o.operation,payload:o.payload,error:o.failure,createdAt:o.timestamp}),this.applyOperation(o.operation,o.payload),r.resolveTelemetryFailure(o.id),unlinkSync(i);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(n,e){try{return this.applyOperation(n,e),!0}catch(i){return this.cacheOperation(n,e,i),false}}applyOperation(n,e){let i=this.getDatabase();switch(n){case "tool_call":this.ensureParentSession(i,e),i.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(i,e),i.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":i.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":i.ensureSession(e),i.insertRun({id:Ae(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!i.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,failureCategory:e.failureCategory,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":i.closeSession(e.sessionId,e.finishedAt),i.updateRun(Ae(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(n,e){let i=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!i)throw new Error("Canonical session ID is required for telemetry");let o=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";n.ensureSession({id:i,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(n,e,i){let o=Date.now(),r={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:n,payload:e,failure:i instanceof Error?i.message:String(i),timestamp:o};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:n,payload:e,error:r.failure,createdAt:o}),s.trimTelemetryFailures($),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(r,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let n=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of n.slice(0,Math.max(0,n.length-$)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},Pt).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(n,e){j(n,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(n){let e=JSON.stringify(n);return e===void 0||e.length<=ke?n:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ke)}...`}}};function Ee(t){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(t)}function Ae(t){return `hook-run:${t}`}function $t(t,n){if(!t||typeof t!="object")throw new Error("Invalid telemetry cache envelope");let e=t;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let i=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!i)throw new Error("Unknown legacy telemetry cache operation");let o=e.payload??{},r=Number(o.timestamp??o.startedAt??Date.now());return {id:`legacy-cache:${n}`,operation:i,payload:o,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:r}}function Oe(t){return Buffer.from(t,"utf8").toString("base64url")}function Nt(t,n,e){let i=n?.trim();if(i){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(i)?i:`tool-${createHash("sha256").update(i.slice(0,1024)).digest("hex").slice(0,32)}`;return `${t}:${o}`}return `${t}:legacy-${e}-${randomUUID().slice(0,8)}`}function Me(t){return `${t}:legacy-journal`}var D=class{constructor(n){this.projectRoot=n;this.sessions=new Map;this.sessionsDir=join$1(b(n),"hook-sessions");}registerSession(n){let e=n.trim();if(!e)throw new Error("session_id_required");let i=this.get(e);if(i)return i.lastActivityAt=Date.now(),this.persist(i),i;let o=Date.now(),r={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:o,lastActivityAt:o};return this.sessions.set(e,r),this.persist(r),r}startExecution(n,e,i){let o=this.registerSession(n);return (!o.executionId||o.skillName!==e)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=e,o.requiredMcpTools=[...new Set(i)],o.lastActivityAt=Date.now(),this.persist(o),o}bindTaskIdentity(n,e){let i=this.registerSession(n);return i.activeTurnId=e.turnId,i.activeRequestId=e.requestId,i.intentArtifactHash=e.intentArtifactHash,i.lastActivityAt=Date.now(),this.persist(i),i}get(n){let e=n.trim();if(!e)return null;let i=this.sessions.get(e);if(i)return this.replayEvidenceJournal(i),i;let o=this.snapshotPath(e);if(!existsSync(o))return null;try{let r=JSON.parse(readFileSync(o,"utf8"));return r.sessionId!==e||r.projectRoot!==this.projectRoot?null:(r.requiredMcpTools=Array.isArray(r.requiredMcpTools)?r.requiredMcpTools:[],r.evidenceObligations=je(r.evidenceObligations),r.evidenceDegradations=Fe(r.evidenceDegradations),r.evidenceOutcomes=Pe(r.evidenceOutcomes),this.replayEvidenceJournal(r),this.sessions.set(e,r),r)}catch{return null}}completeExecution(n){let e=this.get(n);if(!e)return null;let i=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),i}addEvidenceObligation(n,e,i=Date.now(),o){let r=this.registerSession(n),a=(o?void 0:r.evidenceObligations.find(l=>l.contractId===e.id))?.obligationId??Nt(e.id,o,i);this.appendEvidenceEvent(n,{kind:"add",obligationId:a,contractId:e.id,at:i,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let c=r.evidenceObligations.find(l=>l.obligationId===a);return c?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(c)):null}listEvidenceObligations(n){return (this.get(n)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(n,e,i,o,r=Date.now()){let s=this.get(n),a=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(o)?o:"";if(!c)return null;this.appendEvidenceEvent(n,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:c,violations:i.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let l=s.evidenceObligations.find(d=>d.obligationId===e);return l?structuredClone(l):null}resolveEvidenceObligation(n,e){let i=this.get(n);if(!i)return false;let o=i.evidenceObligations.find(s=>s.obligationId===e);if(!o)return false;let r=Date.now();return this.appendEvidenceEvent(n,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve\0${e}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}resolveDegradedEvidence(n,e){let i=this.get(n),o=i?.evidenceDegradations.find(s=>s.obligationId===e);if(!i||!o)return false;let r=Date.now();return this.appendEvidenceEvent(n,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve-degraded\0${e}\0${r}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}degradeEvidenceObligation(n,e,i,o=Date.now()){let r=this.get(n),s=r?.evidenceObligations.find(c=>c.obligationId===e);if(!r||!s)return false;let a=i.slice(0,240);return this.appendEvidenceEvent(n,{kind:"degrade",obligationId:e,contractId:s.contractId,at:o,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(r),r.lastActivityAt=o,this.persist(r),true}removeSession(n){let e=n.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(n){return join$1(this.sessionsDir,`${Oe(n)}.json`)}evidenceJournalDir(n){return join$1(this.sessionsDir,"evidence-journal",Oe(n))}appendEvidenceEvent(n,e,i){let o=this.evidenceJournalDir(n);mkdirSync(o,{recursive:true,mode:448});let r=createHash("sha256").update(i).digest("hex"),s=join$1(o,`${e.kind}-${r}.json`);if(existsSync(s))return;let a=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(n){n.evidenceObligations=je(n.evidenceObligations),n.evidenceDegradations=Fe(n.evidenceDegradations),n.evidenceOutcomes=Pe(n.evidenceOutcomes);let e=this.evidenceJournalDir(n.sessionId);if(!existsSync(e))return;let i;try{i=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let o=i.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=Ht(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||$e(r.kind)-$e(s.kind));for(let r of o)this.applyEvidenceEvent(n,r);n.evidenceObligations=n.evidenceObligations.slice(-8),n.evidenceDegradations=n.evidenceDegradations.slice(-20),n.evidenceOutcomes=n.evidenceOutcomes.slice(-20);}applyEvidenceEvent(n,e){let i=n.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(i)return;let s=n.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):n.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let o=n.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!o||i||o.correctionFingerprint===e.fingerprint)return;o.attempt+=1,o.correctionRequested=true,o.correctionRequestedAt=e.at,o.correctionFingerprint=e.fingerprint,o.violations=e.violations;return}let r=o?.attempt??i?.attempt??0;if(e.kind==="resolve"&&i?.status==="degraded")n.evidenceOutcomes=n.evidenceOutcomes.filter(s=>s.obligationId!==e.obligationId),n.evidenceDegradations=n.evidenceDegradations.filter(s=>s.obligationId!==e.obligationId);else if(i)return;e.kind==="degrade"?(n.evidenceObligations=n.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),n.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r,contract:o?.contract})):n.evidenceObligations=n.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),n.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}});}persist(n){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(n.sessionId),i=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(i,JSON.stringify(n),{mode:384}),renameSync(i,e);}};function je(t){return Array.isArray(t)?t.flatMap(n=>{if(!n||typeof n!="object")return [];let e=n;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!Le(e.contract))return [];let i=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Me(e.contractId),o=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,r=e.correctionFingerprint??o;return r!==void 0&&!/^[a-f0-9]{64}$/.test(r)?[]:[{...e,obligationId:i,correctionFingerprint:r}]}).slice(-8):[]}function Fe(t){return Array.isArray(t)?t.filter(n=>{if(!n||typeof n!="object")return false;let e=n;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function Pe(t){return Array.isArray(t)?t.filter(n=>{if(!n||typeof n!="object")return false;let e=n;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function Ht(t){if(!t||typeof t!="object")return null;let n=t,e=n.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof n.contractId!="string"||n.contractId.length>128||typeof n.at!="number")return null;let o={obligationId:typeof n.obligationId=="string"&&n.obligationId.length>0&&n.obligationId.length<=384?n.obligationId:Me(n.contractId),contractId:n.contractId,at:n.at};if(e==="add")return Le(n.contract)?{kind:e,...o,contract:n.contract}:null;if(e==="correction"){let r=typeof n.fingerprint=="string"?n.fingerprint:n.transcriptHash;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)&&Array.isArray(n.violations)&&n.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:e,...o,fingerprint:r,violations:n.violations}:null}return e==="resolve"?{kind:e,...o}:typeof n.reason=="string"&&n.reason.length<=240?{kind:e,...o,reason:n.reason}:null}function $e(t){return t==="add"?0:t==="correction"?1:2}function Le(t){if(!t||typeof t!="object")return false;let n=t,e=n.requiredSections,i=n.prohibitedClaims;return n.version==="1.0"&&typeof n.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(n.id)&&typeof n.runtimeProfilingOccurred=="boolean"&&typeof n.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(i)&&i.length<=16&&i.every(o=>typeof o=="string"&&o.length<=128)&&typeof n.canonicalReport=="string"&&Buffer.byteLength(n.canonicalReport,"utf8")<=48*1024&&!!n.correctionPolicy&&n.correctionPolicy.maxAttempts===1&&n.correctionPolicy.repeatedViolation==="fail_open"}var Jt=2,Bt=1;function Gt(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{return join$1(dirname$1(fileURLToPath(import.meta.url)),"..","..")}catch{return process.cwd()}}function Ne(t=Gt()){let n=[join$1(t,"dist","command-registry.json"),join$1(t,"command-registry.json")];for(let e of n)try{if(!existsSync(e))continue;let i=JSON.parse(readFileSync(e,"utf8"));if(i.version!==Jt&&i.version!==Bt||!Kt(i.commands)){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:"contract_mismatch",registryPath:e}});continue}return i.commands}catch(i){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:i.message,fallback:"next_registry_candidate"}});}return null}function Kt(t){return !t||typeof t!="object"||Array.isArray(t)?false:Object.values(t).every(n=>{if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return L(e.mcpTools)&&L(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||L(e.runtimePackages))&&(e.hostTools===void 0||Yt(e.hostTools))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function Yt(t){return !!t&&typeof t=="object"&&!Array.isArray(t)&&Object.entries(t).every(([n,e])=>n.length>0&&L(e))}function L(t){return Array.isArray(t)&&t.every(n=>typeof n=="string"&&n.length>0)}function He(t){let n=Ne();return n?n[t]?.mcpTools??[]:[]}function Ue(t){let n=t.trim().replace(/^\//,"");if(!n.startsWith("devflow:"))return null;let e=n.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(e)?`devflow:${e.toLowerCase()}`:null}function Ve(t,n){return n?`evt_tool_${createHash("sha256").update(`${t}\0${n}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}function k(t){let n=tn(t.projectRoot),e=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let i=nn(e,{...t,projectRoot:n});return i?appendTaskRuntimeBoundary({projectRoot:i.projectRoot,taskSpec:taskSpecFromImmutableIntent(on(i)),kind:t.kind,payload:t.payload,dedupeKey:t.dedupeKey,producer:t.producer,database:e})?.snapshot??null:null}catch(i){return emitSemanticControlLog({event:"task.runtime.shadow_mismatch",identity:{projectRoot:n,sessionId:t.sessionId,...t.turnId?{turnId:t.turnId}:{},...t.requestId?{requestId:t.requestId}:{}},level:"warn",timestamp:Date.now(),data:{stage:t.kind,reason:an(i),authority:"legacy"}}),null}finally{e.close();}}function tn(t){try{return realpathSync(t)}catch{return t}}function ze(t){if(!rn(t.legacyState))return;let n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:100});try{let e=n.getTaskRuntimeSnapshot(t.artifact.projectRoot,t.artifact.sessionId,t.artifact.turnId);if(!e)return;let i=sn(t.legacyState);if(e.terminal===i)return;emitSemanticControlLog({event:"task.runtime.shadow_mismatch",identity:Je(t.artifact),level:"warn",timestamp:Date.now(),data:{stage:"terminal_projection",legacyState:t.legacyState,shadowTerminal:e.terminal,expectedTerminal:i,authority:"legacy"}});}catch{}finally{n.close();}}function nn(t,n){return t.listLatestTaskIntentArtifacts(n.projectRoot,n.sessionId).find(e=>n.turnId?e.turnId===n.turnId:n.requestId?e.requestId===n.requestId:true)}function on(t){return {identity:Je(t),version:t.version,...t.supersedesHash?{supersedesHash:t.supersedesHash}:{},rawPrompt:t.rawPrompt,normalizedPrompt:t.normalizedPrompt,...t.command?{command:t.command}:{},slashArgs:t.slashArgs,...t.activeSkill?{activeSkill:t.activeSkill}:{},intent:t.intent,action:t.action,entities:t.entities,targetAnchors:t.targetAnchors,policyConstraints:t.policyConstraints,classificationEvidence:t.classificationEvidence,sourceEventIds:t.sourceEventIds,sourceHash:t.sourceHash,artifactHash:t.artifactHash,createdAt:t.createdAt}}function Je(t){return {projectRoot:t.projectRoot,projectId:t.projectId,hostId:t.hostId,sessionId:t.sessionId,turnId:t.turnId,requestId:t.requestId,...t.executionId?{executionId:t.executionId}:{}}}function rn(t){return t==="action_failed"||t==="closed"||t==="closed_with_degradation"||t==="closed_with_retry_work"}function sn(t){return t==="closed"?"completed":t==="closed_with_degradation"?"completed_with_degradation":t==="closed_with_retry_work"?"retry_pending":"failed"}function an(t){return t instanceof Error?t.message:String(t)}var dn=256*1024,ln=48*1024;var un=5,N=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function fn(t){return t==="react_audit_performance"||t.endsWith("__react_audit_performance")}function pn(t){let n=T(t,0,new Set);return n?mn(n.contract,n.canonicalReport):null}function Be(t){if(!t.sessionId||!fn(t.toolName))return null;let n=pn(t.toolResponse);if(!n)return null;let e=Date.now(),i=t.runtimeStore.addEvidenceObligation(t.sessionId,n,e,t.toolUseId),o=t.runtimeStore.get(t.sessionId);if(i&&o){let r=openGlobalDevFlowDatabase();try{r.upsertSessionObligation({obligationId:`evidence:${i.obligationId}`,projectRoot:o.projectRoot,sessionId:t.sessionId,executionId:o.executionId,kind:"evidence_contract",state:"open",payload:{contract:n,runtimeObligationId:i.obligationId},createdAt:e,updatedAt:e});}finally{r.close();}emitSemanticControlLog({event:"verification.completed",identity:{projectRoot:o.projectRoot,sessionId:t.sessionId,executionId:o.executionId},level:"info",timestamp:e,data:{stage:"performance_detector_coverage",status:"obligation_opened",contractId:n.id,obligationId:i.obligationId,detectorCoverage:H(t.toolResponse),runtimeProfilingOccurred:n.runtimeProfilingOccurred,samplingEvidenceOccurred:n.samplingEvidenceOccurred,toolUseId:t.toolUseId}});}return gn(n)}function gn(t){return [`DevFlow performance evidence contract ${t.id} is active.`,`The final performance answer MUST contain these three sections exactly: ${t.requiredSections.join(" / ")}.`,t.runtimeProfilingOccurred?"Only claims directly supported by the returned runtime measurements may be stated as measured facts.":"No runtime profiling occurred. Treat every finding as a static candidate: do not assign P0/high-risk severity, claim a confirmed bottleneck/jank/frame drop/CPU hotspot, quantify performance or benefit, or recommend requestAnimationFrame as generic throttling without sampling evidence.",`samplingEvidenceOccurred=${t.samplingEvidenceOccurred}. RAF recommendations are permitted only when this structured contract field is true; answer text cannot self-declare sampling evidence.`,"Use the canonical report below directly or preserve its evidence boundaries. Stop will request one correction for unsupported claims, then fail open with degradation telemetry.",t.canonicalReport].join(`
|
|
3
3
|
|
|
4
|
-
`)}function
|
|
5
|
-
`)||null}finally{e.close();}}function
|
|
4
|
+
`)}function H(t,n=0){if(n>6||t==null)return [];if(typeof t=="string")try{return H(JSON.parse(t),n+1)}catch{return []}if(Array.isArray(t)){for(let i of t){let o=H(i,n+1);if(o.length>0)return o}return []}if(typeof t!="object")return [];let e=t;if(Array.isArray(e.detectorCoverage))return e.detectorCoverage.filter(i=>typeof i=="string").slice(0,32);for(let i of Object.values(e)){let o=H(i,n+1);if(o.length>0)return o}return []}function T(t,n,e){if(n>un||t===null||t===void 0)return null;if(typeof t=="string"){if(Buffer.byteLength(t,"utf8")>dn)return null;try{return T(JSON.parse(t),n+1,e)}catch{return null}}if(typeof t!="object"||e.has(t))return null;if(e.add(t),Array.isArray(t)){for(let o of t.slice(0,16)){let r=T(o,n+1,e);if(r)return r}return null}let i=t;if("evidenceContract"in i)return {contract:i.evidenceContract,canonicalReport:i.canonicalReport};for(let o of ["structuredContent","data","result"])if(o in i){let r=T(i[o],n+1,e);if(r)return r}if(Array.isArray(i.content))for(let o of i.content.slice(0,16)){let r=o&&typeof o=="object"&&"text"in o?o.text:o,s=T(r,n+1,e);if(s)return s}return null}function mn(t,n){if(!t||typeof t!="object"||Array.isArray(t))return null;let e=t;if(e.version!=="1.0"||typeof e.id!="string"||!/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(e.id)||typeof e.runtimeProfilingOccurred!="boolean"||typeof e.samplingEvidenceOccurred!="boolean"||!Array.isArray(e.requiredSections)||e.requiredSections.length!==N.length)return null;let i=e.requiredSections.filter(c=>typeof c=="string");if(i.length!==N.length||N.some((c,l)=>i[l]!==c)||!Array.isArray(e.prohibitedClaims)||e.prohibitedClaims.length>16)return null;let o=e.prohibitedClaims.filter(c=>typeof c=="string"&&c.length<=128);if(o.length!==e.prohibitedClaims.length)return null;let r=e.correctionPolicy;if(!r||typeof r!="object"||Array.isArray(r))return null;let s=r;if(s.maxAttempts!==1||s.repeatedViolation!=="fail_open")return null;let a=typeof e.canonicalReport=="string"?e.canonicalReport:n;return typeof a!="string"||Buffer.byteLength(a,"utf8")>ln||N.some(c=>!a.includes(c))?null:{version:"1.0",id:e.id,runtimeProfilingOccurred:e.runtimeProfilingOccurred,samplingEvidenceOccurred:e.samplingEvidenceOccurred,requiredSections:i,prohibitedClaims:o,correctionPolicy:{maxAttempts:1,repeatedViolation:"fail_open"},canonicalReport:a}}function Ye(t){let n;try{if(Rn(t.toolResponse))return null;n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let e=n.getActiveContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!e)return null;let i=bn(t.toolInput,t.toolResponse);if(i.length===0)return null;let o=t.toolName==="Read"?vn(t.toolInput):void 0,r=o?e.selectedFiles?.find(d=>In(t.projectRoot,d,o)):void 0,s=_n(t.toolName),a=r?"code":e.canonicalNextAction===s?"action":null,c=r&&i.includes(r)?r:a==="action"&&i.includes(s)?s:void 0;if(a&&c){let d=[e.contextHash,e.requestId??"",a,c,t.toolUseId??`${t.sessionId}:${t.executionId??e.executionId}`].join("\0");n.recordContextSelectionEvent({id:`ctxsel:${createHash$1("sha256").update(d).digest("hex").slice(0,32)}`,projectRoot:t.projectRoot,sessionId:t.sessionId,executionId:e.executionId,requestId:e.requestId,selectionType:a,candidateId:c,toolName:t.toolName,toolUseId:t.toolUseId,selectedAt:Date.now()});}let l=n.listRetrievalLedgerEvents({projectRoot:t.projectRoot,sessionId:t.sessionId,executionId:e.executionId,requestId:e.requestId}).filter(d=>d.stage==="selected"&&i.includes(d.sourceId));for(let d of l)n.appendRetrievalLedgerEvent({...d,id:wn(d.id,"consumed",t.toolUseId??t.toolName),stage:"consumed",toolEvidence:[t.toolUseId??t.toolName],evidenceIds:i,actor:t.toolName,reasonCode:"structural_evidence_ref",payload:{...d.payload,consumedByTool:t.toolName},createdAt:Date.now()});return l.length>0&&Ge({event:"retrieval.attribution.transitioned",identity:{projectRoot:t.projectRoot,sessionId:t.sessionId,executionId:e.executionId,requestId:e.requestId,contextReceipt:e.contextHash},level:"info",timestamp:Date.now(),data:{stage:"consumed",actor:t.toolName,consumedCount:l.length,evidenceRefCount:i.length}}),a}catch(e){return Ge({event:"hook.runtime.degraded",identity:{projectRoot:t.projectRoot,sessionId:t.sessionId,executionId:t.executionId,requestId:t.requestId},level:"warn",timestamp:Date.now(),data:{stage:"retrieval_attribution",actor:t.toolName,reason:e instanceof Error?e.message:String(e)}}),null}finally{try{n?.close();}catch{}}}function bn(...t){let n=new Set,e=(i,o=0)=>{if(!(o>6||i==null)){if(typeof i=="string"){try{e(JSON.parse(i),o+1);}catch{}return}if(Array.isArray(i)){for(let r of i)e(r,o+1);return}if(typeof i=="object")for(let[r,s]of Object.entries(i))if((r==="evidenceRefs"||r==="_devflow_evidence_refs")&&Array.isArray(s))for(let a of s)typeof a=="string"&&a.trim()&&n.add(a.trim());else e(s,o+1);}};for(let i of t)e(i);return [...n]}function vn(t){for(let n of ["file_path","path"]){let e=t[n];if(typeof e=="string"&&e.trim())return e.trim()}}function In(t,n,e){let i=resolve(t,n),o=isAbsolute(e)?resolve(e):resolve(t,e);return i===o}function _n(t){return t.startsWith("mcp__")?t.split("__").at(-1)??t:t}function Rn(t){if(!t||typeof t!="object"||Array.isArray(t))return false;let n=t;return n.ok===false||n.success===false||n.isError===true||!!n.error||["failed","rejected","unavailable"].includes(String(n.status??""))}function wn(t,n,e){return `retrieval:${createHash$1("sha256").update(`${t}\0${n}\0${e}`).digest("hex")}`}function Ge(t){try{emitSemanticControlLog(t);}catch{}}var An=new Set(["Write","Edit","NotebookEdit"]);function Ze(t){if(!An.has(t.toolName)||On(t.toolResponse))return null;let n=Tn(t.projectRoot,t.toolInput);if(!n)return null;let e=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let i=e.getActiveContextReceipt(t.projectRoot,t.sessionId,t.executionId),o=i?.canonicalAction?.verificationPlan??[];if(!i||o.length===0)return null;let r=[],s=[];for(let c of o){let l=Dn({projectRoot:t.projectRoot,targetFile:n,kind:c.kind,mode:c.mode==="write"?"write":"check",required:c.required===!0,contextReceipt:i.contextHash}),d=`${i.contextHash}\0${t.toolUseId??n}\0${c.kind}\0${n}`,u=`policy-verification:${createHash$1("sha256").update(d).digest("hex")}`,f=Date.now();if(!l){let E=`verification_unavailable:${c.kind}`;e.upsertSessionObligation({obligationId:u,projectRoot:t.projectRoot,sessionId:t.sessionId,executionId:t.executionId,kind:"evidence_contract",state:"degraded",payload:{subtype:"policy_verification",status:"unknown",verificationKind:c.kind,targetFile:n,contextReceipt:i.contextHash},reason:E,createdAt:f,updatedAt:f,resolvedAt:f}),s.push(c.kind),c.required===!0&&k({projectRoot:t.projectRoot,sessionId:t.sessionId,requestId:i.requestId,executionId:t.executionId,kind:"verification.failed",payload:{receiptId:u,reasonCode:E},dedupeKey:`${u}:unavailable`,producer:"devflow-verification-scheduler"});continue}let V={...l,obligationId:u,sessionId:t.sessionId,executionId:t.executionId,requestId:i.requestId};e.upsertSessionObligation({obligationId:u,projectRoot:t.projectRoot,sessionId:t.sessionId,executionId:t.executionId,kind:"evidence_contract",state:"open",payload:{subtype:"policy_verification",status:"scheduled",verificationKind:c.kind,command:l.display,targetFile:n,contextReceipt:i.contextHash,required:c.required===!0},createdAt:f,updatedAt:f});let w=e.enqueueWork({idempotencyKey:u,kind:"verification.policy",projectRoot:t.projectRoot,sessionId:t.sessionId,payload:V,maxAttempts:2,nextAttemptAt:f});k({projectRoot:t.projectRoot,sessionId:t.sessionId,requestId:i.requestId,executionId:t.executionId,kind:"durable_work.owned",payload:{workId:w.id,obligation:"verification"},dedupeKey:`${w.id}:owned`,producer:"devflow-verification-scheduler"}),r.push(l.display);}return [r.length>0?`DevFlow scheduled policy verification: ${r.join(" && ")}`:"",s.length>0?`Verification unavailable and recorded as unknown: ${s.join(", ")}`:""].filter(Boolean).join(`
|
|
5
|
+
`)||null}finally{e.close();}}function Dn(t){let n=jn(t.projectRoot),e=Fn(t.projectRoot),i=n?.scripts??{},o={...n?.dependencies,...n?.devDependencies},r=null;if(t.kind==="formatter"&&(o.prettier||Pn(t.projectRoot)))r=U(e,"prettier",[t.mode==="write"?"--write":"--check",t.targetFile],6e4);else if(t.kind==="typecheck"){let s=ae(i,["typecheck","type-check","check:types"]);s?r=se(e,s,12e4):o.typescript&&existsSync$1(join(t.projectRoot,"tsconfig.json"))&&(r=U(e,"tsc",["--noEmit","--pretty","false"],12e4));}else if(t.kind==="lint"){let s=ae(i,["lint"]);s&&(r=se(e,s,12e4));}else if(t.kind==="test"){let s=$n(t.projectRoot,t.targetFile);s&&o.vitest?r=U(e,"vitest",["run",s],12e4):s&&(o.jest||o["@jest/core"])&&(r=U(e,"jest",["--runTestsByPath",s],12e4));}else if(t.kind==="build"){let s=ae(i,["build"]);s&&(r=se(e,s,18e4));}else t.kind==="generated_files"&&(r={command:"git",args:["diff","--check","--",t.targetFile],timeoutMs:3e4});return r?{kind:t.kind,...r,display:[r.command,...r.args].map(qn).join(" "),required:t.required,targetFile:t.targetFile,contextReceipt:t.contextReceipt}:null}function se(t,n,e){return t==="yarn"?{command:"yarn",args:["run",n],timeoutMs:e}:t==="pnpm"?{command:"pnpm",args:["run",n],timeoutMs:e}:t==="bun"?{command:"bun",args:["run",n],timeoutMs:e}:{command:"npm",args:["run",n],timeoutMs:e}}function U(t,n,e,i){return t==="pnpm"?{command:"pnpm",args:["exec",n,...e],timeoutMs:i}:t==="yarn"?{command:"yarn",args:[n,...e],timeoutMs:i}:t==="bun"?{command:"bunx",args:[n,...e],timeoutMs:i}:{command:"npx",args:["--no-install",n,...e],timeoutMs:i}}function Tn(t,n){let e=n.file_path??n.notebook_path;if(typeof e!="string"||!e.trim())return null;let i=isAbsolute(e)?resolve(e):resolve(t,e);return Cn(t,i)?relative(t,i).split(sep).join("/"):null}function Cn(t,n){let e=isAbsolute(n)?resolve(n):resolve(t,n),i=relative(resolve(t),e);return i!==""&&i!==".."&&!i.startsWith(`..${sep}`)&&!isAbsolute(i)}function On(t){if(!t||typeof t!="object"||Array.isArray(t))return false;let n=t;return n.ok===false||n.success===false||n.isError===true||!!n.error}function jn(t){try{return JSON.parse(readFileSync$1(join(t,"package.json"),"utf8"))}catch{return null}}function Fn(t){return existsSync$1(join(t,"pnpm-lock.yaml"))?"pnpm":existsSync$1(join(t,"yarn.lock"))?"yarn":existsSync$1(join(t,"bun.lockb"))||existsSync$1(join(t,"bun.lock"))?"bun":"npm"}function Pn(t){return [".prettierrc",".prettierrc.json",".prettierrc.js",".prettierrc.cjs","prettier.config.js","prettier.config.cjs"].some(n=>existsSync$1(join(t,n)))}function ae(t,n){return n.find(e=>typeof t[e]=="string"&&t[e].trim())??null}function $n(t,n){let e=n.replace(/\.[^.]+$/u,""),i=[".test.ts",".test.tsx",".spec.ts",".spec.tsx",".test.js",".spec.js"];for(let s of i){let a=`${e}${s}`;if(existsSync$1(join(t,a)))return a}let o=join(t,n.split("/").slice(0,-1).join("/")),r=n.split("/").at(-1)?.replace(/\.[^.]+$/u,"");if(!r||!existsSync$1(o))return null;try{return readdirSync$1(o).filter(s=>s.startsWith(`${r}.`)&&/\.(?:test|spec)\.[cm]?[jt]sx?$/u.test(s)).map(s=>relative(t,join(o,s)).split(sep).join("/"))[0]??null}catch{return null}}function qn(t){return /^[A-Za-z0-9_./:@=-]+$/u.test(t)?t:JSON.stringify(t)}function et(t){if(!t.toolUseId)return null;let n=Gn(t.projectRoot,t.toolUseId);if(!n||n.sessionId!==t.sessionId)return null;let e=Date.now(),i={...n,id:createHash$1("sha256").update(`${n.sessionId}\0${n.toolUseId}\0${n.path}\0${e}`).digest("hex"),phase:"completed",success:t.success,after:zn(n.path),completedAt:e,error:t.error?.slice(0,500)},o=Jn(t.projectRoot);return mkdirSync$1(dirname(o),{recursive:true}),appendFileSync(o,`${JSON.stringify(i)}
|
|
6
|
+
`,{encoding:"utf8",mode:384}),emitSemanticControlLog({event:"canonical.action.validated",identity:{projectRoot:t.projectRoot,sessionId:t.sessionId,executionId:n.executionId,contextReceipt:n.contextReceipt},level:t.success?"info":"warn",timestamp:e,data:{stage:"host_file_state_completed",valid:t.success,operation:n.operation,targetPath:relative(t.projectRoot,n.path),beforeHash:n.before.hash,afterHash:i.after.hash,beforeExists:n.before.exists,afterExists:i.after.exists,reason:i.error,toolUseId:n.toolUseId}}),i}function zn(t){if(!existsSync$1(t))return {exists:false};try{return {exists:!0,hash:createHash$1("sha256").update(readFileSync$1(t)).digest("hex")}}catch{return {exists:true}}}function tt(t){return join(b(t),"file-state")}function nt(t){return join(tt(t),"pending.json")}function Jn(t){return join(tt(t),"observations.jsonl")}function Bn(t){try{return JSON.parse(readFileSync$1(nt(t),"utf8"))}catch{return {}}}function Gn(t,n){let e=nt(t),i=Bn(t),o=i[n];if(o)return delete i[n],Kn(e,JSON.stringify(i)),o}function Kn(t,n){let e=`${t}.${process.pid}.${Date.now()}.tmp`;writeFileSync$1(e,n,{encoding:"utf8",mode:384}),renameSync$1(e,t);}var Zn={open:["intent_bound"],intent_bound:["context_ready","context_degraded"],context_ready:["action_required","action_not_required"],context_degraded:["action_required","action_not_required"],action_required:["action_satisfied","action_degraded","action_failed"],action_not_required:["memory_decided","memory_quarantined"],action_satisfied:["memory_decided","memory_quarantined"],action_degraded:["memory_decided","memory_quarantined"],action_failed:["action_satisfied","action_degraded"],memory_decided:["closed","closed_with_degradation","closed_with_retry_work"],memory_quarantined:["closed_with_degradation","closed_with_retry_work"],closed:[],closed_with_degradation:[],closed_with_retry_work:[]};function Xn(t){let n=Qn(t);return ze({artifact:t.artifact,legacyState:n.toState}),n}function Qn(t){let n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=ii(n,t.artifact);if(oi(e.toState))return e;let i=n.getContextReceiptForRequest(t.artifact.projectRoot,t.artifact.sessionId,t.artifact.requestId),o=t.artifact.intent==="memory";if(!i&&!o)return e;let r=i?ei(t.artifact,i):"context_ready";e.toState==="intent_bound"&&(e=y(n,e,t,r,o?"task_context_not_required":r==="context_ready"?"canonical_context_receipt_ready":"canonical_context_receipt_degraded"));let s=i?ti(t.artifact,i):"action_not_required";if((e.toState==="context_ready"||e.toState==="context_degraded")&&(s==="action_not_required"?e=y(n,e,t,"action_not_required","task_action_not_required"):e=y(n,e,t,"action_required","canonical_action_obligation_present")),e.toState==="action_required"){if(s==="action_required")return e;if(s==="action_failed")return y(n,e,t,"action_failed","canonical_action_attempt_failed");s==="action_degraded"?e=y(n,e,t,"action_degraded","canonical_action_unavailable_or_degraded"):s==="action_satisfied"&&(e=y(n,e,t,"action_satisfied","canonical_action_succeeded"));}if(e.toState==="action_failed")if(s==="action_satisfied")e=y(n,e,t,"action_satisfied","canonical_action_retry_succeeded");else if(s==="action_degraded")e=y(n,e,t,"action_degraded","canonical_action_retry_degraded");else return e;let a=r==="context_degraded"||s==="action_degraded";return ["action_not_required","action_satisfied","action_degraded"].includes(e.toState)&&(e=y(n,e,t,t.memoryStatus==="pending"?"memory_quarantined":"memory_decided",t.memoryStatus==="pending"?t.reason:`canonical_memory_${t.memoryStatus}`)),e.toState==="memory_decided"?y(n,e,t,a?"closed_with_degradation":"closed",t.reason):e.toState==="memory_quarantined"?y(n,e,t,t.retryOwned?"closed_with_retry_work":"closed_with_degradation",t.retryOwned?"durable_retry_owner_confirmed":"terminal_obligation_unowned"):e}finally{n.close();}}function ot(t){let n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=n.getActiveContextReceipt(t.projectRoot,t.sessionId,t.executionId),i=typeof e?.canonicalAction?.binding.turnId=="string"?e.canonicalAction.binding.turnId:void 0;if(!i)return null;let o=n.listLatestTaskIntentArtifacts(t.projectRoot,t.sessionId).find(s=>s.turnId===i),r=n.getMemoryTurn(i);return !o||!r?null:Xn({artifact:o,memoryStatus:r.status,memoryReceiptId:r.receiptId,reason:t.reason})}finally{n.close();}}function ei(t,n){return t.intent==="memory"||t.intent==="knowledge"||(n.selectedFiles?.length??0)>0?"context_ready":"context_degraded"}function ti(t,n){let e=n.canonicalAction,o=(e?(n.actionAttempts??[]).filter(r=>r.tool===e.tool):[]).at(-1);return n.actionSatisfiedAt||o?.status==="succeeded"?"action_satisfied":o&&["failed","timeout","unavailable"].includes(o.status)?"action_failed":n.actionDegradation||e?.status==="degraded"||e?.status==="unsupported"?"action_degraded":e?.required||ni(t)?"action_required":"action_not_required"}function ni(t){return ["create","modify","debug","test","format"].includes(t.action)||["feature","refactor","performance"].includes(t.intent)}function ii(t,n){let e=t.getLatestTerminalTransition(n.projectRoot,n.sessionId,n.turnId);if(!e)throw new Error(`TERMINAL_INTENT_STATE_MISSING:${n.turnId}`);return e}function y(t,n,e,i,o){if(!Zn[n.toState]?.includes(i))throw new Error(`TERMINAL_PATH_UNAVAILABLE:${n.toState}->${i}`);let r=n.sequence+1,s=`terminal:${createHash$1("sha256").update(`${e.artifact.artifactHash}\0${r}\0${i}`).digest("hex").slice(0,24)}`,a=t.appendTerminalTransition({projectRoot:e.artifact.projectRoot,projectId:e.artifact.projectId,hostId:e.artifact.hostId,sessionId:e.artifact.sessionId,turnId:e.artifact.turnId,requestId:e.artifact.requestId,executionId:e.artifact.executionId,sequence:r,fromState:n.toState,toState:i,receiptId:s,sourceReceiptId:e.memoryReceiptId??n.receiptId,reason:o,payload:{memoryStatus:e.memoryStatus,retryOwned:e.retryOwned??false,sourceIntentHash:e.artifact.artifactHash},createdAt:Date.now()});return emitSemanticControlLog({event:"terminal.state.transitioned",identity:{projectRoot:e.artifact.projectRoot,projectId:e.artifact.projectId,hostId:e.artifact.hostId,sessionId:e.artifact.sessionId,turnId:e.artifact.turnId,requestId:e.artifact.requestId,...e.artifact.executionId?{executionId:e.artifact.executionId}:{}},level:i==="closed"?"info":i.includes("degradation")||i.includes("retry")||i==="action_failed"?"warn":"info",timestamp:Date.now(),data:{fromState:n.toState,nextState:i,receiptId:s,reason:o}}),a}function oi(t){return t==="closed"||t==="closed_with_degradation"||t==="closed_with_retry_work"}var fi=new Set(["Agent","Bash","Glob","Grep","WebSearch","WebFetch"]);function rt(t){if(!t)return;let n=typeof t.status=="string"?t.status:void 0;if(!(t.ok===false||t.success===false||t.isError===true||n==="failed"||n==="rejected"||!!t.error))return;let i=t.error;if(typeof i=="string"&&i.trim())return i;if(i&&typeof i=="object"){let o=i;if(typeof o.message=="string"&&o.message.trim())return o.message;if(typeof o.code=="string"&&o.code.trim())return o.code}return n?`Tool response status: ${n}`:"Tool response reported failure"}function pi(t,n,e,i){try{let o=join$1(b(t),"event-map.json");if(!existsSync(o))return null;let r=JSON.parse(readFileSync(o,"utf-8")),s=r.filter(l=>l.toolName===e&&(!l.sessionId||l.sessionId===n));if(s.length===0)return null;let a=i?s.find(l=>l.toolUseId===i):s.sort((l,d)=>l.timestamp-d.timestamp)[0];if(!a)return null;let c=r.findIndex(l=>l.eventId===a.eventId);return c!==-1&&r.splice(c,1),writeFileSync(o,JSON.stringify(r)),{eventId:a.eventId,timestamp:a.timestamp}}catch{return null}}function st(t){if(!t)return 0;let n=t;if(typeof t=="string")try{n=JSON.parse(t);}catch{return 1}let e=n,i=["files","results","data","result","memories","nodes","chunks","findings","symbols","keySymbols"],o=["reasoning","riskHints","nextActions"],r=Array.isArray(e.data)?e.data:e.structuredContent??e;if(Array.isArray(r))return r.length;if(typeof r=="object"&&r!==null){let s=r,a=0,c=false;for(let d of i)Array.isArray(s[d])&&(c=true,a+=s[d].length);for(let d of o)Array.isArray(s[d])&&(a+=s[d].length);for(let[,d]of Object.entries(s))d&&typeof d=="object"&&!Array.isArray(d)&&(a+=st(d));let l=!!(s._devflow||s._devflow_unique||s.taskType);return a===0&&l&&!c?1:a>0?a:c?0:Object.keys(s).length>0?1:0}return 0}function gi(t,n){if(!fi.has(n))return null;let e=te(t,o=>({...o,bypassCount:(o.bypassCount??0)+1}));if(!e.applied)return null;let i=e.receipt.bypassCount??0;return i>20&&i%10===0?`MCP \u5DE5\u5177\u4F7F\u7528\u7387\u4F4E\uFF1A${i} \u6B21\u76F4\u63A5\u5DE5\u5177\u8C03\u7528\u3002\u5EFA\u8BAE\u4F7F\u7528 get_project_context \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`:null}async function mi(t){if(!t)return null;let n;try{n=JSON.parse(t);}catch{return null}let e=n.tool_name||"",i=Z(),o=n.tool_input||{},r=n.tool_response||{},s=n.session_id?.trim()||null,a=new D(i);if(s&&a.registerSession(s),e==="Skill"){let p=typeof o=="object"&&o.skill?o.skill:"",g=Ue(p);s&&g&&(a.startExecution(s,g,He(g)),ee(i,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0}));}let c=s?a.get(s):null;if(e.startsWith("mcp__")){let p=new P(i,s??void 0,c?.executionId??s??void 0);p.recordMcpCall();let g=rt(typeof r=="object"&&r!==null?r:null),h=e.replace(/^mcp__[^_]+__/,""),G=p.getContextReceipt?.()?.canonicalAction?.tool===h;if((p.recordDomainActionOutcome(h,g?yi(g):"succeeded",g,n.tool_use_id)||G)&&s){k({projectRoot:i,sessionId:s,executionId:c?.executionId??s,kind:g?"action.failed":"action.succeeded",payload:{receiptId:n.tool_use_id??`${h}:${g?"failed":"succeeded"}`,reasonCode:g?"canonical_action_failed":"canonical_action_succeeded",tool:h},dedupeKey:`${n.tool_use_id??h}:${g?"failed":"succeeded"}`,producer:"devflow-post-tool-use"});try{ot({projectRoot:i,sessionId:s,executionId:c?.executionId??s,reason:g?"post_tool_action_failed":"post_tool_action_succeeded"});}catch{}}}s&&Ye({projectRoot:i,sessionId:s,executionId:c?.executionId,toolName:e,toolInput:o,toolResponse:r,toolUseId:n.tool_use_id});let l=s?pi(i,s,e,n.tool_use_id):null,d=s&&n.tool_use_id&&!l?(()=>{try{let p=openGlobalDevFlowDatabase();try{return p.getToolCallEventByToolUseId(s,n.tool_use_id)}finally{p.close();}}catch{return null}})():null,u=l??d,f=typeof r=="object"&&r!==null?r:null,V=JSON.stringify(r),w=Buffer.byteLength(V,"utf8"),E=st(r),W=rt(f);if(s&&et({projectRoot:i,sessionId:s,toolUseId:n.tool_use_id,success:!W,error:W}),c?.executionId!==void 0||e.startsWith("mcp__devflow__")||e==="Skill"){let p=getLogWriter(i),g=c?.executionId??`auto-${s??Date.now()}`;p.toolCall({tool:e,runId:g,stepId:`step-${g}`,input:o,output:r,duration:u?Math.max(0,Date.now()-u.timestamp):0,success:!f?.error,resultCount:E,resultSizeBytes:w,error:f?.error});}if(u&&s){let p=typeof r=="string"?r:JSON.stringify(r),g=p.length>5e3?{_truncated:true,_originalSize:p.length,text:p.slice(0,5e3)}:r,h=W,G=h?classifyWorkflowFailure({stepId:e,toolName:e,output:r,error:new Error(h),errorStack:h}).category:void 0;await new q().completeEvent({eventId:u.eventId,sessionId:s,output:g,error:h,failureCategory:G,duration:u?Math.max(0,Date.now()-u.timestamp):0,completedAt:Date.now()});}let z=typeof o=="object"&&o.command?o.command:"",O=f?.exitCode,fe=f?.stderr,at=/^\s*(ls|cat|pwd|cd|echo|head|tail|wc|which|whoami|date|env|printenv|id|hostname|uname)\b/,_,R,J=true;if(e.startsWith("mcp__"))_="mcp_call",R={mcpTool:e.replace(/^mcp__[^_]+__/,""),query:typeof o=="object"&&o.query?o.query:null,resultCount:E,resultSizeBytes:w};else if(e==="Read"||e==="Write"||e==="Edit")_=e==="Read"?"file_read":"file_write",R={filePath:typeof o=="object"&&o.file_path?o.file_path:null,fileContentSize:w};else if(e==="Bash"){let p=at.test(z),g=O!==void 0&&O!==0;J=!p||g,_=g?"bash_error":"bash_command",R={command:z||e,exitCode:O??null,stderr:fe??null};}else e==="Agent"?(_="subagent",R={subagentType:typeof o=="object"&&o.subagent_type?o.subagent_type:null,description:typeof o=="object"&&o.description?String(o.description).slice(0,200):null}):e==="WebSearch"||e==="WebFetch"?(_=e==="WebSearch"?"web_search":"web_fetch",R={query:typeof o=="object"&&o.query?String(o.query).slice(0,200):null}):(J=false,_="tool_use",R={});if(J){let p={id:n.tool_use_id?`memory:${Ve(s??"",n.tool_use_id)}`:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:s??"",tool:e,kind:_,payload:R,command:z||void 0,exitCode:O,stderr:fe??void 0,durationMs:u?Math.max(0,Date.now()-u.timestamp):0,createdAt:Date.now()};s&&j(`/api/memory/session-events?rootPath=${encodeURIComponent(i)}`,p);}let ct=Be({toolName:e,toolResponse:r,sessionId:s,toolUseId:n.tool_use_id,runtimeStore:a}),dt=s?Ze({projectRoot:i,sessionId:s,executionId:c?.executionId,toolName:e,toolInput:o,toolResponse:r,toolUseId:n.tool_use_id}):null,B=gi(i,e);return B&&emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:i,sessionId:s,executionId:c?.executionId},level:"warn",timestamp:Date.now(),data:{stage:"post_tool_enforcement",tool:e,reason:B}}),[ct,dt,B].filter(p=>!!p).join(`
|
|
6
7
|
|
|
7
|
-
`)||null}function
|
|
8
|
+
`)||null}function yi(t){return /timeout|timed out|deadline|warming/i.test(t)?"timeout":/unavailable|not active|unknown tool|not found|not registered|route not found/i.test(t)?"unavailable":"failed"}if(process.argv[1]?.endsWith("post-tool-use")||process.argv[1]?.endsWith("post-tool-use.js")){let t=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let n="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{n+=e;}),process.stdin.on("end",async()=>{let e=await mi(n.trim()||process.argv[2]||"");t(JSON.stringify(e?{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:e}}:{status:"ok"}));}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),5e3).unref();}export{mi as handlePostToolUse};
|