@devflow-tools/cli 0.16.34 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync,rmSync,linkSync,renameSync}from'fs';import {join as join$1,dirname as dirname$1}from'path';import {homedir as homedir$1}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {request}from'node:http';import {mkdirSync as mkdirSync$1,existsSync as existsSync$1,statSync,appendFileSync,chmodSync,rmSync as rmSync$1,renameSync as renameSync$1}from'node:fs';import {join,resolve,basename,relative,sep,dirname,isAbsolute}from'node:path';import {homedir}from'node:os';import {getLocalApiKey,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir}from'@devflow-tools/sdk';import {fileURLToPath}from'url';import {createHash as createHash$1}from'node:crypto';import {randomUUID,createHash}from'crypto';function k(o,t,e){try{let n=openGlobalDevFlowDatabase();try{n.insertEvent({kind:o,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{n.close();}}catch{}}var Ve=getLocalApiKey(),M=join(homedir(),".devflow","errors");async function X(o,t,e={}){let n=e.endpoint??resolveRuntimeEndpoint().url,i=e.timeout??1500,r=e.durableMirror??true,s=e.maxRetries??(r?0:2),a=e.circuitBreaker??true,c=acquireRuntimeHttpCircuit(n,o);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 Ke(n,o,t,i),a&&registerRuntimeHttpSuccess(n,o).transitioned&&k("http_circuit_transition",{endpoint:n,path:new URL(o,n).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(p){l=p instanceof Error?p:new Error(String(p)),u<s&&await Ye(Math.min(100*2**u,1e3));}if(!l)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return K(o,l),{delivered:false,suppressed:false,fallbackReason:l.message};let d=registerRuntimeHttpFailure(n,o,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return d.transitioned&&(K(o,l),k("http_circuit_transition",{endpoint:n,path:new URL(o,n).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 Ke(o,t,e,n){return new Promise((i,r)=>{let s=JSON.stringify(e),a=new URL(t,o),c=false,l=u=>{c||(c=true,u?r(u):i());},d=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":Ve,"Content-Length":Buffer.byteLength(s)},timeout:n},u=>{u.on("error",l),u.on("end",()=>{let p=u.statusCode??0;l(p>=200&&p<300?void 0:new Error(`HTTP ${p}`));}),u.resume();});d.on("error",l),d.on("timeout",()=>d.destroy(new Error(`HTTP mirror timed out after ${n}ms`))),d.write(s),d.end();})}function K(o,t){try{existsSync$1(M)||mkdirSync$1(M,{recursive:!0}),appendFileSync(join(M,"http-errors.log"),`${new Date().toISOString()} | ${o} | ${t.message}
2
- `);}catch{}}function Ye(o){return new Promise(t=>setTimeout(t,o))}var ne=1e4,tt=3e4,S=500,O=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:S}).reverse();for(let r of i)try{this.applyOperation(r.operation,r.payload),n.resolveTelemetryFailure(r.id);}catch{}n.trimTelemetryFailures(S);}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:nt(JSON.parse(readFileSync(r,"utf8")),i)}}catch{return null}})).filter(n=>n!==null).sort((n,i)=>n.envelope.timestamp-i.envelope.timestamp||oe(n.envelope.operation)-oe(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:ie(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(ie(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(S),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-S)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},tt).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){X(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ne?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ne)}...`}}};function oe(o){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(o)}function ie(o){return `hook-run:${o}`}function nt(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 j(o){return o??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function g(o){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(j(o))}var ct=2,lt=1;function dt(){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 re(o=dt()){let t=[join$1(o,"dist","command-registry.json"),join$1(o,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let n=JSON.parse(readFileSync(e,"utf8"));if(n.version!==ct&&n.version!==lt||!ut(n.commands)){console.error(`[devflow] command registry contract mismatch: ${e}`);continue}return n.commands}catch(n){console.error(`[devflow] command registry load failed: ${n.message}`);}return null}function ut(o){return !o||typeof o!="object"||Array.isArray(o)?false:Object.values(o).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return $(e.mcpTools)&&$(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||$(e.runtimePackages))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function $(o){return Array.isArray(o)&&o.every(t=>typeof t=="string"&&t.length>0)}function se(o){let t=re();return t?t[o]?.mcpTools??[]:[]}function E(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 gt(o,t){return o.lastMcpCall===t.lastMcpCall&&o.bypassCount===t.bypassCount}function ft(o){try{return existsSync(o)?E(JSON.parse(readFileSync(o,"utf-8"))):{}}catch{return {}}}function le(o,t){let e=t instanceof Error?t.message:String(t);console.error(`[devflow] Receipt ${o} skipped: ${e}`);}function ae(o){let t=g(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 de(o,t){if(o.getHookReceipt(t)){ae(t);return}let e=join$1(g(t),"receipt.json");if(!existsSync(e))return;let n=ft(e);o.updateHookReceipt(t,()=>n),ae(t);}function ue(o,t,e){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),de(n,o);let i={},r=n.updateHookReceipt(o,a=>(i=E(a),E(t(i)))),s=E(r);return {receipt:s,applied:!0,changed:!gt(i,s)}}catch(i){return le(e,i),{receipt:{},applied:false,changed:false}}finally{try{n?.close();}catch{}}}function pe(o){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),de(t,o),E(t.getHookReceipt(o))}catch(e){return le("update",e),{}}finally{try{t?.close();}catch{}}}function ht(o,t){return ue(o,()=>t,"write").applied}function yt(o,t){return ue(o,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"},vt=new Set(["Write","Edit","NotebookEdit"]),bt=new Set(["failed","timeout","unavailable"]);function _t(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 C=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"&&ce[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(vt.has(t)){let c=this.evaluateRequiredAction();if(c)return c}return {permissionDecision:"allow"}}let i=ce[t];if(!i)return {permissionDecision:"allow"};let r=yt(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!r.applied)return {permissionDecision:"allow"};let s=r.receipt.bypassCount??0,a=_t(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(){ht(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}`,l=s.actionAttempts??[];return r.upsertContextReceipt({...s,actionAttempts:l.some(d=>d.id===c||i&&d.toolUseId===i&&d.status===e)?l:[...l,{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&&bt.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 Ot=10*1024*1024,Ct=5;function At(o){return createHash$1("sha256").update(o).digest("hex").slice(0,16)}function fe(o){return join(homedir(),".devflow","logs","hook-debug",`${At(o)}.jsonl`)}function he(o,t,e={}){let n=e.maxBytes??Ot,i=e.maxFiles??Ct;mkdirSync$1(dirname(o),{recursive:true,mode:448});let r=Buffer.byteLength(t),s=existsSync$1(o)?statSync(o).size:0;s>0&&s+r>n&&Tt(o,i),appendFileSync(o,t,{mode:384}),chmodSync(o,384);}function Tt(o,t){if(t<=1){rmSync$1(o,{force:true});return}rmSync$1(`${o}.${t-1}`,{force:true});for(let e=t-2;e>=1;e-=1){let n=`${o}.${e}`;existsSync$1(n)&&renameSync$1(n,`${o}.${e+1}`);}existsSync$1(o)&&renameSync$1(o,`${o}.1`);}var q="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function ye(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function Re(o){return Buffer.from(o,"utf8").toString("base64url")}function $t(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 ke(o){return `${o}:legacy-journal`}var T=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(g(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}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=Ee(r.evidenceObligations),r.evidenceDegradations=De(r.evidenceDegradations),r.evidenceOutcomes=we(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(l=>l.contractId===e.id))?.obligationId??$t(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(l=>l.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(d=>d.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(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(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,`${Re(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Re(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=Ee(t.evidenceObligations),t.evidenceDegradations=De(t.evidenceDegradations),t.evidenceOutcomes=we(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=Nt(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||Ie(r.kind)-Ie(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 Ee(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)||!Se(e.contract))return [];let n=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:ke(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 De(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 we(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 Nt(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:ke(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return Se(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 Ie(o){return o==="add"?0:o==="correction"?1:2}function Se(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 Oe(o){let t=o.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 Ce(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)}`}var qt=new Set(["Write","Edit","NotebookEdit"]),Ae="Claude native memory writes are disabled for this project. Use DevFlow explicit memory or mcp__devflow__memory_commit_turn so a canonical receipt is created.";function $e(o){if(!qt.has(o.toolName))return null;let t=Ut(o.toolInput);if(!t)return null;let e=Wt(t,o.projectRoot),n=resolve(o.projectRoot,".claude");if(Te(e,n)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return Ae;let i=resolve(o.home??homedir(),".claude","projects");return Te(e,i)&&relative(i,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?Ae:null}function Ut(o){for(let t of ["file_path","notebook_path","path"]){let e=o[t];if(typeof e=="string"&&e.trim())return e.trim()}return null}function Wt(o,t){return resolve(isAbsolute(o)?o:resolve(t,o))}function Te(o,t){let e=relative(t,o);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function D(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function Ne(o){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:o}}}function Vt(o){let t=g(o);return existsSync(t)||mkdirSync(t,{recursive:true}),t}function Kt(o,t,e,n,i,r){let s=join$1(Vt(o),"event-map.json"),a=[];try{existsSync(s)&&(a=JSON.parse(readFileSync(s,"utf-8")));}catch{}a.push({sessionId:t,toolName:e,toolUseId:n,eventId:i,timestamp:r}),writeFileSync(s,JSON.stringify(a));}function Yt(o){switch(o){case "Read":case "Glob":return "file_read";case "Write":case "Edit":case "NotebookEdit":return "file_write";case "Bash":return "bash_command";case "Agent":return "subagent";case "Skill":return "skill_invoke";default:return "tool_use"}}async function Xt(o){let t=ye();try{if(!o||o.trim()==="")return D();let e=JSON.parse(o),n=Date.now(),i=j(),r=new O;e.tool_name.startsWith("mcp__devflow__")&&(typeof e.tool_input.projectRoot!="string"||!e.tool_input.projectRoot.trim())&&(e.tool_input.projectRoot=i);let s=e.session_id?.trim();if(!s)return Ne(q);let a=new T(i),c=a.get(s)!==null;if(a.registerSession(s),c||await r.sendSessionStart(s,i,Date.now()),e.tool_name==="Skill"){let x=e.tool_input?.skill,h=x?Oe(x):null;if(h){let He=a.get(s)?.executionId,R=a.startExecution(s,h,se(h));R.executionId&&R.executionId!==He&&await r.sendExecutionStart(R.executionId,s,h,R.lastActivityAt,i,R.requiredMcpTools);}}let l=a.get(s);e.tool_name.startsWith("mcp__devflow__")&&(e.tool_input._devflow_session_id=s,e.tool_input._devflow_execution_id=l?.executionId??s,l?.skillName&&(e.tool_input._devflow_active_skill=l.skillName),e.tool_use_id&&(e.tool_input._devflow_tool_use_id=e.tool_use_id));let d=e.tool_name.startsWith("mcp__"),u=d?e.tool_name.replace(/^mcp__[^_]+__/,""):void 0,p=new C(i,s,l?.executionId),J=p.getPhase(),m,w=$e({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:i}),f=w?{permissionDecision:"deny",reason:w}:p.evaluate(e.tool_name,d);f.permissionDecision==="deny"?m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:f.reason??"MCP context required"}}:f.additionalContext?m=Ne(f.additionalContext):m=D(),e.tool_name.startsWith("mcp__devflow__")&&(m.hookSpecificOutput.updatedInput=e.tool_input),t&&m.hookSpecificOutput.permissionDecision==="allow"&&(m.hookSpecificOutput.additionalContext=q);let Le=l?.executionId??s,_={eventId:Ce(s,e.tool_use_id),executionId:Le,sessionId:s,projectRoot:i,toolUseId:e.tool_use_id,timestamp:Date.now(),toolName:e.tool_name,toolType:d?"mcp":e.tool_name==="Agent"?"subagent":"direct",isMcpTool:d,mcpToolName:u,mcpEnforced:d&&J==="context_gathering",mcpFallback:!d&&J==="context_gathering",kind:Yt(e.tool_name),input:e.tool_input,duration:0,blocked:m.hookSpecificOutput.permissionDecision==="deny",blockReason:m.hookSpecificOutput.permissionDecision==="deny"?w?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":f.reasonCode??"DEVFLOW_CONTEXT_REQUIRED":void 0},I=await r.sendEvent(_);I&&!_.blocked&&Kt(i,s,e.tool_name,e.tool_use_id,I,_.timestamp),I&&_.blocked&&await r.completeEvent({eventId:I,sessionId:s,error:w?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":f.reasonCode??"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-_.timestamp,completedAt:Date.now()});try{let x=pe(i),h={ts:n,tool:e.tool_name,sessionId:s,skill:l?.skillName??"(none)",requiredTools:l?.requiredMcpTools??[],isMcp:d,enforce:l?.executionId!==void 0,stateless:l?.executionId===void 0&&!d&&e.tool_name!=="Skill",bypassCount:x.bypassCount??0,decision:m.hookSpecificOutput.permissionDecision,env_CLAUDE_PLUGIN_ROOT:process.env.CLAUDE_PLUGIN_ROOT??"(unset)",cwd:process.cwd()};he(fe(i),`${JSON.stringify(h)}
3
- `);}catch{}return m}catch{return D()}}if(process.argv[1]?.endsWith("pre-tool-use")||process.argv[1]?.endsWith("pre-tool-use.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()=>{let e=await Xt(t);o(JSON.stringify(e));}),process.stdin.on("error",()=>{o(JSON.stringify(D())),process.exit(0);}),setTimeout(()=>{o(JSON.stringify(D())),process.exit(0);},4e3).unref();}export{Xt as handlePreToolUse};
1
+ import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync,rmSync,linkSync,renameSync}from'fs';import {join as join$1,dirname as dirname$1}from'path';import {homedir as homedir$1}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {request}from'node:http';import {mkdirSync as mkdirSync$1,existsSync as existsSync$1,statSync,appendFileSync,chmodSync,rmSync as rmSync$1,renameSync as renameSync$1}from'node:fs';import {join,resolve,basename,relative,sep,dirname,isAbsolute}from'node:path';import {homedir}from'node:os';import {getLocalApiKey,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir}from'@devflow-tools/sdk';import {fileURLToPath}from'url';import {emitSemanticControlLog}from'@devflow-tools/telemetry';import {createHash as createHash$1}from'node:crypto';import {randomUUID,createHash}from'crypto';function S(i,t,e){try{let n=openGlobalDevFlowDatabase();try{n.insertEvent({kind:i,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{n.close();}}catch{}}var Ke=getLocalApiKey(),N=join(homedir(),".devflow","errors");async function Q(i,t,e={}){let n=e.endpoint??resolveRuntimeEndpoint().url,o=e.timeout??1500,r=e.durableMirror??true,s=e.maxRetries??(r?0:2),a=e.circuitBreaker??true,l=acquireRuntimeHttpCircuit(n,i);if(a&&!l.allowed)return {delivered:false,suppressed:true,fallbackReason:l.state.fallbackReason};let c;for(let u=0;u<=s;u+=1)try{return await Ye(n,i,t,o),a&&registerRuntimeHttpSuccess(n,i).transitioned&&S("http_circuit_transition",{endpoint:n,path:new URL(i,n).pathname,previous:l.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(p){c=p instanceof Error?p:new Error(String(p)),u<s&&await Xe(Math.min(100*2**u,1e3));}if(!c)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return Y(i,c),{delivered:false,suppressed:false,fallbackReason:c.message};let d=registerRuntimeHttpFailure(n,i,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return d.transitioned&&(Y(i,c),S("http_circuit_transition",{endpoint:n,path:new URL(i,n).pathname,previous:l.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 Ye(i,t,e,n){return new Promise((o,r)=>{let s=JSON.stringify(e),a=new URL(t,i),l=false,c=u=>{l||(l=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":Ke,"Content-Length":Buffer.byteLength(s)},timeout:n},u=>{u.on("error",c),u.on("end",()=>{let p=u.statusCode??0;c(p>=200&&p<300?void 0:new Error(`HTTP ${p}`));}),u.resume();});d.on("error",c),d.on("timeout",()=>d.destroy(new Error(`HTTP mirror timed out after ${n}ms`))),d.write(s),d.end();})}function Y(i,t){try{existsSync$1(N)||mkdirSync$1(N,{recursive:!0}),appendFileSync(join(N,"http-errors.log"),`${new Date().toISOString()} | ${i} | ${t.message}
2
+ `);}catch{}}function Xe(i){return new Promise(t=>setTimeout(t,i))}var ie=1e4,nt=3e4,O=500,C=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,o,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:n,startedAt:o,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(),o){let r={executionId:t,status:e,finishedAt:n,metadata:o},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(t,e,n){let o={id:t,projectRoot:e,startedAt:n,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 n={sessionId:t,finishedAt:e},o=this.commitOrCache("session_end",n);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),o}async flushCache(){try{let n=this.getDatabase(),o=n.listTelemetryFailures({unresolvedOnly:!0,limit:O}).reverse();for(let r of o)try{this.applyOperation(r.operation,r.payload),n.resolveTelemetryFailure(r.id);}catch{}n.trimTelemetryFailures(O);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync(n)).flatMap(n=>readdirSync(n).filter(o=>o.endsWith(".json")).map(o=>{let r=join$1(n,o);try{return {cacheFile:r,envelope:it(JSON.parse(readFileSync(r,"utf8")),o)}}catch{return null}})).filter(n=>n!==null).sort((n,o)=>n.envelope.timestamp-o.envelope.timestamp||oe(n.envelope.operation)-oe(o.envelope.operation));for(let{cacheFile:n,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(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:re(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(re(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 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:n,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,n){let o=Date.now(),r={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:o};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:o}),s.trimTelemetryFailures(O),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 t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of t.slice(0,Math.max(0,t.length-O)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},nt).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){Q(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ie?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ie)}...`}}};function oe(i){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(i)}function re(i){return `hook-run:${i}`}function it(i,t){if(!i||typeof i!="object")throw new Error("Invalid telemetry cache envelope");let e=i;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 o=e.payload??{},r=Number(o.timestamp??o.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:n,payload:o,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:r}}function $(i){return i??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function g(i){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir($(i))}var lt=2,dt=1;function ut(){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 se(i=ut()){let t=[join$1(i,"dist","command-registry.json"),join$1(i,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let n=JSON.parse(readFileSync(e,"utf8"));if(n.version!==lt&&n.version!==dt||!pt(n.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 n.commands}catch(n){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:n.message,fallback:"next_registry_candidate"}});}return null}function pt(i){return !i||typeof i!="object"||Array.isArray(i)?false:Object.values(i).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return A(e.mcpTools)&&A(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||A(e.runtimePackages))&&(e.hostTools===void 0||mt(e.hostTools))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function mt(i){return !!i&&typeof i=="object"&&!Array.isArray(i)&&Object.entries(i).every(([t,e])=>t.length>0&&A(e))}function A(i){return Array.isArray(i)&&i.every(t=>typeof t=="string"&&t.length>0)}function ae(i){let t=se();return t?t[i]?.mcpTools??[]:[]}function D(i){if(!i||typeof i!="object"||Array.isArray(i))return {};let t=i,e={};for(let n of ["lastMcpCall","bypassCount"])if(n in t){let o=t[n];if(o==null)continue;e[n]=typeof o=="number"&&Number.isFinite(o)&&o>=0?o:0;}return e}function ht(i,t){return i.lastMcpCall===t.lastMcpCall&&i.bypassCount===t.bypassCount}function yt(i){try{return existsSync(i)?D(JSON.parse(readFileSync(i,"utf-8"))):{}}catch{return {}}}function de(i,t,e){let n=e instanceof Error?e.message:String(e);emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:i},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:n,fallback:"fail_open"}});}function ce(i){let t=g(i);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 ue(i,t){if(i.getHookReceipt(t)){ce(t);return}let e=join$1(g(t),"receipt.json");if(!existsSync(e))return;let n=yt(e);i.updateHookReceipt(t,()=>n),ce(t);}function pe(i,t,e){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),ue(n,i);let o={},r=n.updateHookReceipt(i,a=>(o=D(a),D(t(o)))),s=D(r);return {receipt:s,applied:!0,changed:!ht(o,s)}}catch(o){return de(i,e,o),{receipt:{},applied:false,changed:false}}finally{try{n?.close();}catch{}}}function me(i){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),ue(t,i),D(t.getHookReceipt(i))}catch(e){return de("update",e),{}}finally{try{t?.close();}catch{}}}function vt(i,t){return pe(i,()=>t,"write").applied}function bt(i,t){return pe(i,t,"update")}var le={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},_t=new Set(["Write","Edit","NotebookEdit"]),Rt=new Set(["failed","timeout","unavailable"]);function Et(i){switch(i){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,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"&&le[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(_t.has(t)){let l=this.evaluateRequiredAction();if(l)return l}return {permissionDecision:"allow"}}let o=le[t];if(!o)return {permissionDecision:"allow"};let r=bt(this.projectRoot,l=>({...l,bypassCount:(l.bypassCount??0)+1}));if(!r.applied)return {permissionDecision:"allow"};let s=r.receipt.bypassCount??0,a=Et(t);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \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(){vt(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(t,e,n,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!==t)return !1;let a=Date.now(),l=o?.trim()?`${o.trim()}:${e}`:`${t}:${e}:${a}`,c=s.actionAttempts??[];return r.upsertContextReceipt({...s,actionAttempts:c.some(d=>d.id===l||o&&d.toolUseId===o&&d.status===e)?c:[...c,{id:l,tool:t,status:e,attemptedAt:a,toolUseId:o,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 o=(t.actionAttempts??[]).filter(r=>r.tool===e.tool&&Rt.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: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 o=n.getContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!o||o.contextHash!==t.contextHash||o.actionDegradation)return;n.upsertContextReceipt({...o,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 At=10*1024*1024,Tt=5;function jt(i){return createHash$1("sha256").update(i).digest("hex").slice(0,16)}function he(i){return join(homedir(),".devflow","logs","hook-debug",`${jt(i)}.jsonl`)}function ye(i,t,e={}){let n=e.maxBytes??At,o=e.maxFiles??Tt;mkdirSync$1(dirname(i),{recursive:true,mode:448});let r=Buffer.byteLength(t),s=existsSync$1(i)?statSync(i).size:0;s>0&&s+r>n&&Ft(i,o),appendFileSync(i,t,{mode:384}),chmodSync(i,384);}function Ft(i,t){if(t<=1){rmSync$1(i,{force:true});return}rmSync$1(`${i}.${t-1}`,{force:true});for(let e=t-2;e>=1;e-=1){let n=`${i}.${e}`;existsSync$1(n)&&renameSync$1(n,`${i}.${e+1}`);}existsSync$1(i)&&renameSync$1(i,`${i}.1`);}var U="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function ve(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function Ee(i){return Buffer.from(i,"utf8").toString("base64url")}function Pt(i,t,e){let n=t?.trim();if(n){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(n)?n:`tool-${createHash("sha256").update(n.slice(0,1024)).digest("hex").slice(0,32)}`;return `${i}:${o}`}return `${i}:legacy-${e}-${randomUUID().slice(0,8)}`}function Se(i){return `${i}:legacy-journal`}var F=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(g(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 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,n){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(n)],o.lastActivityAt=Date.now(),this.persist(o),o}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 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=De(r.evidenceObligations),r.evidenceDegradations=we(r.evidenceDegradations),r.evidenceOutcomes=Ie(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(),o){let r=this.registerSession(t),a=(o?void 0:r.evidenceObligations.find(c=>c.contractId===e.id))?.obligationId??Pt(e.id,o,n);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:n,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let l=r.evidenceObligations.find(c=>c.obligationId===a);return l?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(l)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,n,o,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!a)return null;let l=/^[a-f0-9]{64}$/.test(o)?o:"";if(!l)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:l,violations:n.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${l}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let c=s.evidenceObligations.find(d=>d.obligationId===e);return c?structuredClone(c):null}resolveEvidenceObligation(t,e){let n=this.get(t);if(!n)return false;let o=n.evidenceObligations.find(s=>s.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(n),n.lastActivityAt=r,this.persist(n),true}degradeEvidenceObligation(t,e,n,o=Date.now()){let r=this.get(t),s=r?.evidenceObligations.find(l=>l.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:o,reason:a},`degrade\0${e}\0${a}`),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,`${Ee(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Ee(t))}appendEvidenceEvent(t,e,n){let o=this.evidenceJournalDir(t);mkdirSync(o,{recursive:true,mode:448});let r=createHash("sha256").update(n).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(l){if(l.code!=="EEXIST")throw l}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=De(t.evidenceObligations),t.evidenceDegradations=we(t.evidenceDegradations),t.evidenceOutcomes=Ie(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 o=n.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=Lt(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||ke(r.kind)-ke(s.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 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 o=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!o||n||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??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 De(i){return Array.isArray(i)?i.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)||!Oe(e.contract))return [];let n=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Se(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:n,correctionFingerprint:r}]}).slice(-8):[]}function we(i){return Array.isArray(i)?i.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 Ie(i){return Array.isArray(i)?i.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 Lt(i){if(!i||typeof i!="object")return null;let t=i,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:Se(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return Oe(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(s=>typeof s=="string"&&s.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 ke(i){return i==="add"?0:i==="correction"?1:2}function Oe(i){if(!i||typeof i!="object")return false;let t=i,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(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 Ce(i){let t=i.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 Ae(i,t){return t?`evt_tool_${createHash("sha256").update(`${i}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var Jt=new Set(["Write","Edit","NotebookEdit"]),Te="Claude native memory writes are disabled for this project. Use DevFlow explicit memory or mcp__devflow__memory_commit_turn so a canonical receipt is created.";function $e(i){if(!Jt.has(i.toolName))return null;let t=Wt(i.toolInput);if(!t)return null;let e=Bt(t,i.projectRoot),n=resolve(i.projectRoot,".claude");if(je(e,n)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return Te;let o=resolve(i.home??homedir(),".claude","projects");return je(e,o)&&relative(o,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?Te:null}function Wt(i){for(let t of ["file_path","notebook_path","path"]){let e=i[t];if(typeof e=="string"&&e.trim())return e.trim()}return null}function Bt(i,t){return resolve(isAbsolute(i)?i:resolve(t,i))}function je(i,t){let e=relative(t,i);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function w(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function Pe(i){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:i}}}function Yt(i){let t=g(i);return existsSync(t)||mkdirSync(t,{recursive:true}),t}function Xt(i,t,e,n,o,r){let s=join$1(Yt(i),"event-map.json"),a=[];try{existsSync(s)&&(a=JSON.parse(readFileSync(s,"utf-8")));}catch{}a.push({sessionId:t,toolName:e,toolUseId:n,eventId:o,timestamp:r}),writeFileSync(s,JSON.stringify(a));}function Qt(i){switch(i){case "Read":case "Glob":return "file_read";case "Write":case "Edit":case "NotebookEdit":return "file_write";case "Bash":return "bash_command";case "Agent":return "subagent";case "Skill":return "skill_invoke";default:return "tool_use"}}async function Zt(i){let t=ve();try{if(!i||i.trim()==="")return w();let e=JSON.parse(i),n=Date.now(),o=$(),r=new C;e.tool_name.startsWith("mcp__devflow__")&&(typeof e.tool_input.projectRoot!="string"||!e.tool_input.projectRoot.trim())&&(e.tool_input.projectRoot=o);let s=e.session_id?.trim();if(!s)return Pe(U);let a=new F(o),l=a.get(s)!==null;if(a.registerSession(s),l||await r.sendSessionStart(s,o,Date.now()),e.tool_name==="Skill"){let x=e.tool_input?.skill,h=x?Ce(x):null;if(h){let qe=a.get(s)?.executionId,R=a.startExecution(s,h,ae(h));R.executionId&&R.executionId!==qe&&await r.sendExecutionStart(R.executionId,s,h,R.lastActivityAt,o,R.requiredMcpTools);}}let c=a.get(s);e.tool_name.startsWith("mcp__devflow__")&&(e.tool_input._devflow_session_id=s,e.tool_input._devflow_execution_id=c?.executionId??s,c?.activeTurnId&&(e.tool_input._devflow_turn_id=c.activeTurnId),c?.activeRequestId&&(e.tool_input._devflow_request_id=c.activeRequestId),c?.intentArtifactHash&&(e.tool_input._devflow_intent_artifact_hash=c.intentArtifactHash),c?.skillName&&(e.tool_input._devflow_active_skill=c.skillName),e.tool_use_id&&(e.tool_input._devflow_tool_use_id=e.tool_use_id));let d=e.tool_name.startsWith("mcp__"),u=d?e.tool_name.replace(/^mcp__[^_]+__/,""):void 0,p=new T(o,s,c?.executionId),B=p.getPhase(),m,I=$e({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:o}),f=I?{permissionDecision:"deny",reason:I}:p.evaluate(e.tool_name,d);f.permissionDecision==="deny"?m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:f.reason??"MCP context required"}}:f.additionalContext?m=Pe(f.additionalContext):m=w(),e.tool_name.startsWith("mcp__devflow__")&&(m.hookSpecificOutput.updatedInput=e.tool_input),t&&m.hookSpecificOutput.permissionDecision==="allow"&&(m.hookSpecificOutput.additionalContext=U);let He=c?.executionId??s,_={eventId:Ae(s,e.tool_use_id),executionId:He,sessionId:s,projectRoot:o,toolUseId:e.tool_use_id,timestamp:Date.now(),toolName:e.tool_name,toolType:d?"mcp":e.tool_name==="Agent"?"subagent":"direct",isMcpTool:d,mcpToolName:u,mcpEnforced:d&&B==="context_gathering",mcpFallback:!d&&B==="context_gathering",kind:Qt(e.tool_name),input:e.tool_input,duration:0,blocked:m.hookSpecificOutput.permissionDecision==="deny",blockReason:m.hookSpecificOutput.permissionDecision==="deny"?I?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":f.reasonCode??"DEVFLOW_CONTEXT_REQUIRED":void 0},k=await r.sendEvent(_);k&&!_.blocked&&Xt(o,s,e.tool_name,e.tool_use_id,k,_.timestamp),k&&_.blocked&&await r.completeEvent({eventId:k,sessionId:s,error:I?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":f.reasonCode??"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-_.timestamp,completedAt:Date.now()});try{let x=me(o),h={ts:n,tool:e.tool_name,sessionId:s,skill:c?.skillName??"(none)",requiredTools:c?.requiredMcpTools??[],isMcp:d,enforce:c?.executionId!==void 0,stateless:c?.executionId===void 0&&!d&&e.tool_name!=="Skill",bypassCount:x.bypassCount??0,decision:m.hookSpecificOutput.permissionDecision,env_CLAUDE_PLUGIN_ROOT:process.env.CLAUDE_PLUGIN_ROOT??"(unset)",cwd:process.cwd()};ye(he(o),`${JSON.stringify(h)}
3
+ `);}catch{}return m}catch{return w()}}if(process.argv[1]?.endsWith("pre-tool-use")||process.argv[1]?.endsWith("pre-tool-use.js")){let i=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()=>{let e=await Zt(t);i(JSON.stringify(e));}),process.stdin.on("error",()=>{i(JSON.stringify(w())),process.exit(0);}),setTimeout(()=>{i(JSON.stringify(w())),process.exit(0);},4e3).unref();}export{Zt as handlePreToolUse};
@@ -1,6 +1,6 @@
1
- import {spawn,execFileSync}from'node:child_process';import {randomUUID}from'node:crypto';import {mkdirSync,writeFileSync,existsSync}from'node:fs';import {request}from'node:http';import {createRequire}from'node:module';import {homedir}from'node:os';import {join}from'node:path';import {writeRuntimeEndpointState,readRuntimeEndpointState,updateRuntimeEndpointStatus,resolveRuntimeEndpoint}from'@devflow-tools/sdk';var{DatabaseSync:B}=createRequire(import.meta.url)("node:sqlite"),V=75,Q=400,z=2e3,$=300*1e3,q=1e3,K=1e3,j=15e3,Y=["--yes","@devflow-tools/server","--devflow-instance-token"];function g(e){let n=e instanceof Error?e.message:String(e);console.error(`[devflow] Server bootstrap skipped: ${n}`);}function X(e){let n=new B(e);n.exec(`PRAGMA busy_timeout = ${V}`);let t=n.prepare(`
1
+ import {spawn,execFileSync}from'node:child_process';import {randomUUID,createHash}from'node:crypto';import {mkdirSync,writeFileSync,existsSync}from'node:fs';import {request}from'node:http';import {createRequire}from'node:module';import {homedir}from'node:os';import {join}from'node:path';import {writeRuntimeEndpointState,readRuntimeEndpointState,updateRuntimeEndpointStatus,resolveRuntimeEndpoint}from'@devflow-tools/sdk';import {emitSemanticControlLog}from'@devflow-tools/telemetry';var{DatabaseSync:q}=createRequire(import.meta.url)("node:sqlite"),K=75,j=400,$=2e3,Y=300*1e3,X=1e3,J=1e3,Z=15e3,ee=["--yes","@devflow-tools/server","--devflow-instance-token"],C=process.env.CLAUDE_PROJECT_DIR||process.cwd();function v(e){let n=e instanceof Error?e.message:String(e);emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:C},level:"warn",timestamp:Date.now(),data:{stage:"server_bootstrap",reason:n,fallback:"mcp_stdio_or_existing_server"}});}function d(e,n,t){emitSemanticControlLog({event:e==="warn"?"hook.runtime.degraded":"hook.runtime.completed",identity:{projectRoot:C},level:e,timestamp:Date.now(),data:{stage:n,...t}});}function re(e){return createHash("sha256").update(e).digest("hex").slice(0,16)}function te(e){let n=new q(e);n.exec(`PRAGMA busy_timeout = ${K}`);let t=n.prepare(`
2
2
  SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'server_bootstrap_state'
3
- `).get();if(t?.sql&&!t.sql.includes("'terminating'")){n.exec("BEGIN IMMEDIATE");try{n.exec("ALTER TABLE server_bootstrap_state RENAME TO server_bootstrap_state_legacy"),I(n),n.exec(`
3
+ `).get();if(t?.sql&&!t.sql.includes("'terminating'")){n.exec("BEGIN IMMEDIATE");try{n.exec("ALTER TABLE server_bootstrap_state RENAME TO server_bootstrap_state_legacy"),A(n),n.exec(`
4
4
  INSERT INTO server_bootstrap_state (
5
5
  id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
6
6
  created_at, updated_at
@@ -9,7 +9,7 @@ import {spawn,execFileSync}from'node:child_process';import {randomUUID}from'node
9
9
  id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
10
10
  created_at, updated_at
11
11
  FROM server_bootstrap_state_legacy
12
- `),n.exec("DROP TABLE server_bootstrap_state_legacy"),n.exec("COMMIT");}catch(r){try{n.exec("ROLLBACK");}catch{}throw r}}else t||I(n);return n}function I(e){e.exec(`
12
+ `),n.exec("DROP TABLE server_bootstrap_state_legacy"),n.exec("COMMIT");}catch(r){try{n.exec("ROLLBACK");}catch{}throw r}}else t||A(n);return n}function A(e){e.exec(`
13
13
  CREATE TABLE IF NOT EXISTS server_bootstrap_state (
14
14
  id INTEGER PRIMARY KEY CHECK (id = 1),
15
15
  token TEXT NOT NULL,
@@ -21,7 +21,7 @@ import {spawn,execFileSync}from'node:child_process';import {randomUUID}from'node
21
21
  created_at INTEGER NOT NULL,
22
22
  updated_at INTEGER NOT NULL
23
23
  )
24
- `);}function J(e){return e.prepare(`
24
+ `);}function ne(e){return e.prepare(`
25
25
  SELECT
26
26
  token,
27
27
  state,
@@ -33,46 +33,46 @@ import {spawn,execFileSync}from'node:child_process';import {randomUUID}from'node
33
33
  updated_at AS updatedAt
34
34
  FROM server_bootstrap_state
35
35
  WHERE id = 1
36
- `).get()}function c(e){return Number(e.changes)}function Z(e){if(!Number.isSafeInteger(e)||e<=1)return false;try{return process.kill(e,0),!0}catch{return false}}function M(){let e=execFileSync("ps",["-axo","pid=,pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:500}),n=[];for(let t of e.split(`
37
- `)){let r=t.match(/^\s*(\d+)\s+(\d+)\s+(.+)$/);if(!r)continue;let o=Number(r[1]),a=Number(r[2]);!Number.isSafeInteger(o)||!Number.isSafeInteger(a)||n.push({pid:o,processGroupId:a,command:r[3]});}return n}function ee(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function G(e,n){let t=ee(n);return new RegExp(`(?:^|\\s)--devflow-instance-token(?:=|\\s+)${t}(?:\\s|$)`).test(e)}function v(e){return /(?:@devflow-tools\/server|devflow-server|[\\/]apps[\\/]server[\\/]dist[\\/]main\.js|[\\/]@devflow-tools[\\/]server[\\/]dist[\\/]main\.js)/.test(e)}function P(e){return /(?:^|\s)(?:\S*[\\/])?devflow-server(?:-child)?(?:\s|$)|[\\/]apps[\\/]server[\\/]dist[\\/]main\.js|[\\/]@devflow-tools[\\/]server[\\/]dist[\\/]main\.js/.test(e)}function re(e){let n=M().filter(r=>v(r.command)&&G(r.command,e)),t=new Map;for(let r of n){let o=t.get(r.processGroupId)??[];o.push(r),t.set(r.processGroupId,o);}return [...t.entries()].map(([r,o])=>({processGroupId:r,processes:o})).sort((r,o)=>o.processes.length-r.processes.length)}function S(e,n){return re(e).find(t=>n===void 0||t.processGroupId===n)}function f(e,n){let t=h(e,n);if(!t)return;let r=t.processes.find(o=>o.pid!==t.wrapperPid&&P(o.command))??t.processes.find(o=>o.pid===t.wrapperPid&&P(o.command));if(r)return {wrapperPid:t.wrapperPid,processGroupId:t.processGroupId,serverPid:r.pid,processes:t.processes}}function h(e,n){let t=S(e,n);if(!t)return;let r=t.processes.find(o=>o.pid===t.processGroupId&&v(o.command));if(r)return {wrapperPid:r.pid,processGroupId:r.processGroupId,processes:t.processes}}function T(e){if(!Z(e))return false;try{return execFileSync("ps",["-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:250}).trim().includes("server-bootstrap")}catch{return false}}function y(){return new Promise(e=>{let n=false,t=r=>{n||(n=true,e(r));};try{let r=process.env.DEVFLOW_SERVER_BOOTSTRAP_HEALTH_URL??new URL("/api/health",R()).toString(),o=request(r,{method:"GET",timeout:Q},a=>{a.resume(),t((a.statusCode??500)>=200&&(a.statusCode??500)<300);});o.on("timeout",()=>o.destroy(new Error("health timeout"))),o.on("error",()=>t(!1)),o.end();}catch{t(false);}})}async function te(e){let n=false;try{e.exec("BEGIN IMMEDIATE"),n=!0;let t=await y(),r=J(e);if(t){if(r?.state==="running"||r?.state==="launching"){let s=f(r.token,r.processGroupId??void 0);if(s){e.prepare(`
36
+ `).get()}function c(e){return Number(e.changes)}function oe(e){if(!Number.isSafeInteger(e)||e<=1)return false;try{return process.kill(e,0),!0}catch{return false}}function y(){let e=execFileSync("ps",["-axo","pid=,pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:500}),n=[];for(let t of e.split(`
37
+ `)){let r=t.match(/^\s*(\d+)\s+(\d+)\s+(.+)$/);if(!r)continue;let o=Number(r[1]),p=Number(r[2]);!Number.isSafeInteger(o)||!Number.isSafeInteger(p)||n.push({pid:o,processGroupId:p,command:r[3]});}return n}function se(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function x(e,n){let t=se(n);return new RegExp(`(?:^|\\s)--devflow-instance-token(?:=|\\s+)${t}(?:\\s|$)`).test(e)}function S(e){return /(?:@devflow-tools\/server|devflow-server|[\\/]apps[\\/]server[\\/]dist[\\/]main\.js|[\\/]@devflow-tools[\\/]server[\\/]dist[\\/]main\.js)/.test(e)}function L(e){return /(?:^|\s)(?:\S*[\\/])?devflow-server(?:-child)?(?:\s|$)|[\\/]apps[\\/]server[\\/]dist[\\/]main\.js|[\\/]@devflow-tools[\\/]server[\\/]dist[\\/]main\.js/.test(e)}function ie(e){let n=y().filter(r=>S(r.command)&&x(r.command,e)),t=new Map;for(let r of n){let o=t.get(r.processGroupId)??[];o.push(r),t.set(r.processGroupId,o);}return [...t.entries()].map(([r,o])=>({processGroupId:r,processes:o})).sort((r,o)=>o.processes.length-r.processes.length)}function R(e,n){return ie(e).find(t=>n===void 0||t.processGroupId===n)}function E(e,n){let t=D(e,n);if(!t)return;let r=t.processes.find(o=>o.pid!==t.wrapperPid&&L(o.command))??t.processes.find(o=>o.pid===t.wrapperPid&&L(o.command));if(r)return {wrapperPid:t.wrapperPid,processGroupId:t.processGroupId,serverPid:r.pid,processes:t.processes}}function D(e,n){let t=R(e,n);if(!t)return;let r=t.processes.find(o=>o.pid===t.processGroupId&&S(o.command));if(r)return {wrapperPid:r.pid,processGroupId:r.processGroupId,processes:t.processes}}function h(e){if(!oe(e))return false;try{return execFileSync("ps",["-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:250}).trim().includes("server-bootstrap")}catch{return false}}function U(){return new Promise(e=>{let n=false,t=r=>{n||(n=true,e(r));};try{let r=process.env.DEVFLOW_SERVER_BOOTSTRAP_HEALTH_URL??new URL("/api/health",P()).toString(),o=request(r,{method:"GET",timeout:j},p=>{p.resume(),t((p.statusCode??500)>=200&&(p.statusCode??500)<300);});o.on("timeout",()=>o.destroy(new Error("health timeout"))),o.on("error",()=>t(!1)),o.end();}catch{t(false);}})}async function ae(e){let n=false;try{e.exec("BEGIN IMMEDIATE"),n=!0;let t=await U(),r=ne(e);if(t){if(r?.state==="running"||r?.state==="launching"){let s=E(r.token,r.processGroupId??void 0);if(s){e.prepare(`
38
38
  UPDATE server_bootstrap_state
39
39
  SET state = 'running', owner_pid = ?, wrapper_pid = ?, process_group_id = ?, server_pid = ?,
40
40
  updated_at = ?
41
41
  WHERE id = 1 AND token = ? AND state = ?
42
- `).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token,r.state);let i=R();writeRuntimeEndpointState({url:i,port:Number(new URL(i).port||13337),pid:s.serverPid,processGroupId:s.processGroupId,ownerToken:r.token,status:"healthy"});}else r.state==="running"&&e.prepare(`
42
+ `).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token,r.state);let i=P();writeRuntimeEndpointState({url:i,port:Number(new URL(i).port||13337),pid:s.serverPid,processGroupId:s.processGroupId,ownerToken:r.token,status:"healthy"});}else r.state==="running"&&e.prepare(`
43
43
  DELETE FROM server_bootstrap_state
44
44
  WHERE id = 1 AND token = ? AND state = 'running'
45
- `).run(r.token);}return e.exec("COMMIT"),n=!1,{action:"skip"}}if(r?.state==="launching"){if(T(r.ownerPid))return e.exec("COMMIT"),n=!1,{action:"skip"};let s=r.processGroupId??void 0,i=f(r.token,s);if(i){let d=e.prepare(`
45
+ `).run(r.token);}return e.exec("COMMIT"),n=!1,{action:"skip"}}if(r?.state==="launching"){if(h(r.ownerPid))return e.exec("COMMIT"),n=!1,{action:"skip"};let s=r.processGroupId??void 0,i=E(r.token,s);if(i){let u=e.prepare(`
46
46
  UPDATE server_bootstrap_state
47
47
  SET state = 'running', owner_pid = ?, wrapper_pid = ?, process_group_id = ?,
48
48
  server_pid = ?, updated_at = ?
49
49
  WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
50
- `).run(process.pid,i.wrapperPid,i.processGroupId,i.serverPid,Date.now(),r.token,r.ownerPid);if(c(d)!==1)throw new Error("launch intent changed before adoption");return e.exec("COMMIT"),n=!1,console.error(`[devflow] Adopted server process group ${i.processGroupId}`),{action:"skip"}}let p=h(r.token,s);if(p&&Date.now()-r.createdAt<$)return e.exec("COMMIT"),n=!1,{action:"skip"};if(p){let d=e.prepare(`
50
+ `).run(process.pid,i.wrapperPid,i.processGroupId,i.serverPid,Date.now(),r.token,r.ownerPid);if(c(u)!==1)throw new Error("launch intent changed before adoption");return e.exec("COMMIT"),n=!1,d("info","server_process_adopted",{processGroupId:i.processGroupId}),{action:"skip"}}let a=D(r.token,s);if(a&&Date.now()-r.createdAt<Y)return e.exec("COMMIT"),n=!1,{action:"skip"};if(a){let u=e.prepare(`
51
51
  UPDATE server_bootstrap_state
52
52
  SET state = 'terminating', owner_pid = ?, process_group_id = ?, updated_at = ?
53
53
  WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
54
- `).run(process.pid,p.processGroupId,Date.now(),r.token,r.ownerPid);if(c(d)!==1)throw new Error("launch intent changed before cleanup claim");return e.exec("COMMIT"),n=!1,{action:"cleanup",token:r.token,processGroupId:p.processGroupId}}e.prepare(`
54
+ `).run(process.pid,a.processGroupId,Date.now(),r.token,r.ownerPid);if(c(u)!==1)throw new Error("launch intent changed before cleanup claim");return e.exec("COMMIT"),n=!1,{action:"cleanup",token:r.token,processGroupId:a.processGroupId}}e.prepare(`
55
55
  DELETE FROM server_bootstrap_state
56
56
  WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
57
- `).run(r.token,r.ownerPid);}else if(r?.state==="terminating"){if(T(r.ownerPid))return e.exec("COMMIT"),n=!1,{action:"skip"};let s=S(r.token);if(s){let i=e.prepare(`
57
+ `).run(r.token,r.ownerPid);}else if(r?.state==="terminating"){if(h(r.ownerPid))return e.exec("COMMIT"),n=!1,{action:"skip"};let s=R(r.token);if(s){let i=e.prepare(`
58
58
  UPDATE server_bootstrap_state
59
59
  SET owner_pid = ?, process_group_id = ?, updated_at = ?
60
60
  WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
61
61
  `).run(process.pid,s.processGroupId,Date.now(),r.token,r.ownerPid);if(c(i)!==1)throw new Error("cleanup ownership changed during recovery");return e.exec("COMMIT"),n=!1,{action:"cleanup",token:r.token,processGroupId:s.processGroupId}}e.prepare(`
62
62
  DELETE FROM server_bootstrap_state
63
63
  WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
64
- `).run(r.token,r.ownerPid);}else if(r?.state==="running"){let s=f(r.token);if(s)return e.prepare(`
64
+ `).run(r.token,r.ownerPid);}else if(r?.state==="running"){let s=E(r.token);if(s)return e.prepare(`
65
65
  UPDATE server_bootstrap_state
66
66
  SET owner_pid = ?, wrapper_pid = ?, process_group_id = ?, server_pid = ?, updated_at = ?
67
67
  WHERE id = 1 AND token = ? AND state = 'running'
68
- `).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token),e.exec("COMMIT"),n=!1,{action:"skip"};let i=S(r.token);if(i&&!T(r.ownerPid)){let p=e.prepare(`
68
+ `).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token),e.exec("COMMIT"),n=!1,{action:"skip"};let i=R(r.token);if(i&&!h(r.ownerPid)){let a=e.prepare(`
69
69
  UPDATE server_bootstrap_state
70
70
  SET state = 'terminating', owner_pid = ?, process_group_id = ?, updated_at = ?
71
71
  WHERE id = 1 AND token = ? AND state = 'running' AND owner_pid = ?
72
- `).run(process.pid,i.processGroupId,Date.now(),r.token,r.ownerPid);if(c(p)!==1)throw new Error("running cleanup ownership changed");return e.exec("COMMIT"),n=!1,{action:"cleanup",token:r.token,processGroupId:i.processGroupId}}e.prepare(`
72
+ `).run(process.pid,i.processGroupId,Date.now(),r.token,r.ownerPid);if(c(a)!==1)throw new Error("running cleanup ownership changed");return e.exec("COMMIT"),n=!1,{action:"cleanup",token:r.token,processGroupId:i.processGroupId}}e.prepare(`
73
73
  DELETE FROM server_bootstrap_state
74
74
  WHERE id = 1 AND token = ? AND state = 'running' AND owner_pid = ?
75
- `).run(r.token,r.ownerPid);}let o=randomUUID(),a=Date.now();return e.prepare(`
75
+ `).run(r.token,r.ownerPid);}let o=randomUUID(),p=Date.now();return e.prepare(`
76
76
  INSERT INTO server_bootstrap_state (
77
77
  id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
78
78
  created_at, updated_at
@@ -86,24 +86,24 @@ import {spawn,execFileSync}from'node:child_process';import {randomUUID}from'node
86
86
  server_pid = NULL,
87
87
  created_at = excluded.created_at,
88
88
  updated_at = excluded.updated_at
89
- `).run(o,process.pid,a,a),e.exec("COMMIT"),n=!1,{action:"launch",token:o}}finally{if(n)try{e.exec("ROLLBACK");}catch{}}}function ne(e){return new Promise((n,t)=>{let r;try{let o=oe(e);r=spawn(o.command,o.args,{detached:!0,env:{...process.env,DEVFLOW_INSTANCE_TOKEN:e},stdio:["ignore","inherit","inherit"]});}catch(o){t(o);return}r.once("spawn",()=>n(r)),r.once("error",t);})}function oe(e){if(!se()){let n=createRequire(import.meta.url),r=[process.env.DEVFLOW_SERVER_ENTRY,ie(()=>n.resolve("@devflow-tools/server/dist/main.js")),join(process.cwd(),"apps","server","dist","main.js"),join(process.cwd(),"node_modules","@devflow-tools","server","dist","main.js")].filter(o=>!!o).find(o=>existsSync(o));if(r)return {command:process.execPath,args:[r,"--devflow-instance-token",e]}}return {command:"npx",args:[...Y,e]}}function se(){return process.env.DEVFLOW_SERVER_BOOTSTRAP_FORCE_NPX==="1"||!!process.env.DEVFLOW_TEST_NPX_TRACE||Object.keys(process.env).some(e=>e.startsWith("DEVFLOW_SERVER_BOOTSTRAP_TEST_"))}function ie(e){try{return e()}catch{return}}function R(){let e=resolveRuntimeEndpoint();return e.source==="environment"?e.url:readRuntimeEndpointState()?.url??e.url}async function _(e,n){let t=Date.now()+n;for(;Date.now()<t;){if(e())return true;await new Promise(r=>setTimeout(r,10));}return e()}async function A(e){let n=process.env[e];if(!n)return;writeFileSync(n,`${process.pid}
90
- `);let t=process.env.DEVFLOW_SERVER_BOOTSTRAP_TEST_CONTINUE_FILE;if(!t)return;if(!await _(()=>existsSync(t),j))throw new Error(`test checkpoint timed out: ${e}`)}async function pe(e,n){let t;return await _(()=>{let o=f(e,n);return o?(t=o,true):false},z)?t:void 0}function ae(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
89
+ `).run(o,process.pid,p,p),e.exec("COMMIT"),n=!1,{action:"launch",token:o}}finally{if(n)try{e.exec("ROLLBACK");}catch{}}}function pe(e){return new Promise((n,t)=>{let r;try{let o=ce(e);r=spawn(o.command,o.args,{detached:!0,env:{...process.env,DEVFLOW_INSTANCE_TOKEN:e},stdio:["ignore","inherit","inherit"]});}catch(o){t(o);return}r.once("spawn",()=>n(r)),r.once("error",t);})}function ce(e){if(!de()){let n=createRequire(import.meta.url),r=[process.env.DEVFLOW_SERVER_ENTRY,ue(()=>n.resolve("@devflow-tools/server/dist/main.js")),join(process.cwd(),"apps","server","dist","main.js"),join(process.cwd(),"node_modules","@devflow-tools","server","dist","main.js")].filter(o=>!!o).find(o=>existsSync(o));if(r)return {command:process.execPath,args:[r,"--devflow-instance-token",e]}}return {command:"npx",args:[...ee,e]}}function de(){return process.env.DEVFLOW_SERVER_BOOTSTRAP_FORCE_NPX==="1"||!!process.env.DEVFLOW_TEST_NPX_TRACE||Object.keys(process.env).some(e=>e.startsWith("DEVFLOW_SERVER_BOOTSTRAP_TEST_"))}function ue(e){try{return e()}catch{return}}function P(){let e=resolveRuntimeEndpoint();return e.source==="environment"?e.url:readRuntimeEndpointState()?.url??e.url}async function m(e,n){let t=Date.now()+n;for(;Date.now()<t;){if(e())return true;await new Promise(r=>setTimeout(r,10));}return e()}async function N(e){let n=process.env[e];if(!n)return;writeFileSync(n,`${process.pid}
90
+ `);let t=process.env.DEVFLOW_SERVER_BOOTSTRAP_TEST_CONTINUE_FILE;if(!t)return;if(!await m(()=>existsSync(t),Z))throw new Error(`test checkpoint timed out: ${e}`)}async function le(e,n){let t;return await m(()=>{let o=E(e,n);return o?(t=o,true):false},$)?t:void 0}function _e(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
91
91
  UPDATE server_bootstrap_state
92
92
  SET wrapper_pid = ?, process_group_id = ?, server_pid = NULL, updated_at = ?
93
93
  WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
94
- `).run(t.wrapperPid,t.processGroupId,Date.now(),n,process.pid);if(c(o)!==1)throw new Error("launch intent ownership changed before wrapper persistence");e.exec("COMMIT"),r=!1;}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function ce(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
94
+ `).run(t.wrapperPid,t.processGroupId,Date.now(),n,process.pid);if(c(o)!==1)throw new Error("launch intent ownership changed before wrapper persistence");e.exec("COMMIT"),r=!1;}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function Ee(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
95
95
  UPDATE server_bootstrap_state
96
96
  SET state = 'running', wrapper_pid = ?, process_group_id = ?, server_pid = ?,
97
97
  updated_at = ?
98
98
  WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
99
- `).run(t.wrapperPid,t.processGroupId,t.serverPid,Date.now(),n,process.pid);if(c(o)!==1)throw new Error("launch intent ownership changed before promotion");e.exec("COMMIT"),r=!1;}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function de(e,n){let t=false;try{e.exec("BEGIN IMMEDIATE"),t=!0,e.prepare(`
99
+ `).run(t.wrapperPid,t.processGroupId,t.serverPid,Date.now(),n,process.pid);if(c(o)!==1)throw new Error("launch intent ownership changed before promotion");e.exec("COMMIT"),r=!1;}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function fe(e,n){let t=false;try{e.exec("BEGIN IMMEDIATE"),t=!0,e.prepare(`
100
100
  DELETE FROM server_bootstrap_state
101
101
  WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
102
- `).run(n,process.pid),e.exec("COMMIT"),t=!1;}finally{if(t)try{e.exec("ROLLBACK");}catch{}}}function ue(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
102
+ `).run(n,process.pid),e.exec("COMMIT"),t=!1;}finally{if(t)try{e.exec("ROLLBACK");}catch{}}}function me(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
103
103
  UPDATE server_bootstrap_state
104
104
  SET state = 'terminating', owner_pid = ?, updated_at = ?
105
105
  WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
106
- `).run(process.pid,Date.now(),n,t);return e.exec("COMMIT"),r=!1,c(o)===1}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function le(e,n){let t=false;try{e.exec("BEGIN IMMEDIATE"),t=!0;let r=e.prepare(`
106
+ `).run(process.pid,Date.now(),n,t);return e.exec("COMMIT"),r=!1,c(o)===1}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function we(e,n){let t=false;try{e.exec("BEGIN IMMEDIATE"),t=!0;let r=e.prepare(`
107
107
  DELETE FROM server_bootstrap_state
108
108
  WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
109
- `).run(n,process.pid);return e.exec("COMMIT"),t=!1,c(r)===1}finally{if(t)try{e.exec("ROLLBACK");}catch{}}}function m(e){return M().filter(n=>n.processGroupId===e)}function N(e,n){return m(e).some(t=>v(t.command)&&G(t.command,n))}async function fe(e,n){if(!N(e,n))return false;console.error(`[devflow] Terminating untracked server process group ${e}`);try{process.kill(-e,"SIGTERM");}catch{}if(await _(()=>m(e).length===0,q))return true;if(!N(e,n))return false;try{process.kill(-e,"SIGKILL");}catch{}return _(()=>m(e).length===0,K)}async function L(e,n,t){return m(t).length===0||await fe(t,n)?le(e,n):false}async function Ee(){let e=join(homedir(),".devflow");mkdirSync(e,{recursive:true});let n=X(join(e,"server-bootstrap.sqlite")),t,r,o=false;try{for(;;){let p=await te(n);if(p.action==="skip")return;if(p.action==="cleanup"){if(!await L(n,p.token,p.processGroupId))throw new Error("claimed server process group cleanup did not complete");continue}t=p.token;break}if(await A("DEVFLOW_SERVER_BOOTSTRAP_TEST_INTENT_READY_FILE"),r=await ne(t),!r.pid)throw new Error("server launcher returned no PID");let a=r.pid,s=R();writeRuntimeEndpointState({url:s,port:Number(new URL(s).port||13337),pid:r.pid,processGroupId:a,ownerToken:t,status:"launching"});let i=await pe(t,a);if(!i){let p=h(t,a);if(!p)throw new Error("npx process group ownership could not be validated");ae(n,t,p),r.unref(),console.error(`[devflow] Server package launch still warming (PID ${p.wrapperPid})`);return}await A("DEVFLOW_SERVER_BOOTSTRAP_TEST_AFTER_SPAWN_READY_FILE"),ce(n,t,i),o=!0,writeRuntimeEndpointState({url:s,port:Number(new URL(s).port||13337),pid:i.serverPid,processGroupId:i.processGroupId,ownerToken:t,status:await y()?"healthy":"launching"}),r.unref(),console.error(`[devflow] Server starting in background (PID ${i.wrapperPid})`);}catch(a){if(t&&r?.pid&&!o){let s=false;try{s=ue(n,t,process.pid);}catch(i){g(i);}s?(await L(n,t,r.pid)||console.error(`[devflow] Server process group ${r.pid} cleanup did not complete`),readRuntimeEndpointState()?.ownerToken===t&&updateRuntimeEndpointStatus("stopped")):(console.error(`[devflow] Server cleanup claim lost for token ${t}`),r.unref());}else if(t&&!r){try{de(n,t);}catch(i){g(i);}readRuntimeEndpointState()?.ownerToken===t&&updateRuntimeEndpointStatus("stopped");}throw a}finally{try{n.close();}catch{}}}Ee().catch(g).then(()=>{process.exitCode=0;},()=>{process.exitCode=0;});
109
+ `).run(n,process.pid);return e.exec("COMMIT"),t=!1,c(r)===1}finally{if(t)try{e.exec("ROLLBACK");}catch{}}}function w(e){return y().filter(n=>n.processGroupId===e)}function k(e,n){return w(e).some(t=>S(t.command)&&x(t.command,n))}async function Te(e,n){if(!k(e,n))return false;d("warn","server_process_cleanup",{processGroupId:e});try{process.kill(-e,"SIGTERM");}catch{}if(await m(()=>w(e).length===0,X))return true;if(!k(e,n))return false;try{process.kill(-e,"SIGKILL");}catch{}return m(()=>w(e).length===0,J)}async function O(e,n,t){return w(t).length===0||await Te(t,n)?we(e,n):false}async function ge(){let e=join(homedir(),".devflow");mkdirSync(e,{recursive:true});let n=te(join(e,"server-bootstrap.sqlite")),t,r,o=false;try{for(;;){let a=await ae(n);if(a.action==="skip")return;if(a.action==="cleanup"){if(!await O(n,a.token,a.processGroupId))throw new Error("claimed server process group cleanup did not complete");continue}t=a.token;break}if(await N("DEVFLOW_SERVER_BOOTSTRAP_TEST_INTENT_READY_FILE"),r=await pe(t),!r.pid)throw new Error("server launcher returned no PID");let p=r.pid,s=P();writeRuntimeEndpointState({url:s,port:Number(new URL(s).port||13337),pid:r.pid,processGroupId:p,ownerToken:t,status:"launching"});let i=await le(t,p);if(!i){let a=D(t,p);if(!a)throw new Error("npx process group ownership could not be validated");_e(n,t,a),r.unref(),d("warn","server_launch_warming",{wrapperPid:a.wrapperPid});return}await N("DEVFLOW_SERVER_BOOTSTRAP_TEST_AFTER_SPAWN_READY_FILE"),Ee(n,t,i),o=!0,writeRuntimeEndpointState({url:s,port:Number(new URL(s).port||13337),pid:i.serverPid,processGroupId:i.processGroupId,ownerToken:t,status:await U()?"healthy":"launching"}),r.unref(),d("info","server_launch_background",{wrapperPid:i.wrapperPid,serverPid:i.serverPid});}catch(p){if(t&&r?.pid&&!o){let s=false;try{s=me(n,t,process.pid);}catch(i){v(i);}s?(await O(n,t,r.pid)||d("warn","server_cleanup_incomplete",{processGroupId:r.pid}),readRuntimeEndpointState()?.ownerToken===t&&updateRuntimeEndpointStatus("stopped")):(d("warn","server_cleanup_claim_lost",{tokenHash:re(t)}),r.unref());}else if(t&&!r){try{fe(n,t);}catch(i){v(i);}readRuntimeEndpointState()?.ownerToken===t&&updateRuntimeEndpointStatus("stopped");}throw p}finally{try{n.close();}catch{}}}ge().catch(v).then(()=>{process.exitCode=0;},()=>{process.exitCode=0;});
@@ -1,4 +1,6 @@
1
- import {getLocalApiKey,getProjectStateDir,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {MemoryGate}from'@devflow-tools/memory-engine';import {existsSync as existsSync$1,readFileSync,rmSync as rmSync$1,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1,unlinkSync as unlinkSync$1}from'fs';import {join as join$1}from'path';import {homedir as homedir$1}from'os';import {request}from'node:http';import {mkdirSync,existsSync,writeFileSync,renameSync,unlinkSync,rmSync,lstatSync,openSync,constants,fstatSync,readSync,closeSync,appendFileSync}from'node:fs';import {join}from'node:path';import {homedir}from'node:os';import {createHash}from'node:crypto';import {randomUUID,createHash as createHash$1}from'crypto';function B(i){return i??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function k(i){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(B(i))}function Q(i,t,e){try{let n=openGlobalDevFlowDatabase();try{n.insertEvent({kind:i,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{n.close();}}catch{}}var Ze=getLocalApiKey(),ee=join(homedir(),".devflow","errors");async function j(i,t,e={}){let n=e.endpoint??resolveRuntimeEndpoint().url,o=e.timeout??1500,r=e.durableMirror??true,s=e.maxRetries??(r?0:2),a=e.circuitBreaker??true,c=acquireRuntimeHttpCircuit(n,i);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let u;for(let g=0;g<=s;g+=1)try{return await Xe(n,i,t,o),a&&registerRuntimeHttpSuccess(n,i).transitioned&&Q("http_circuit_transition",{endpoint:n,path:new URL(i,n).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(y){u=y instanceof Error?y:new Error(String(y)),g<s&&await Ye(Math.min(100*2**g,1e3));}if(!u)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return de(i,u),{delivered:false,suppressed:false,fallbackReason:u.message};let p=registerRuntimeHttpFailure(n,i,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return p.transitioned&&(de(i,u),Q("http_circuit_transition",{endpoint:n,path:new URL(i,n).pathname,previous:c.state.status,status:"open",failures:p.state.failures,openUntil:p.state.openUntil,fallbackReason:p.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:p.state.fallbackReason}}function Xe(i,t,e,n){return new Promise((o,r)=>{let s=JSON.stringify(e),a=new URL(t,i),c=false,u=g=>{c||(c=true,g?r(g):o());},p=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":Ze,"Content-Length":Buffer.byteLength(s)},timeout:n},g=>{g.on("error",u),g.on("end",()=>{let y=g.statusCode??0;u(y>=200&&y<300?void 0:new Error(`HTTP ${y}`));}),g.resume();});p.on("error",u),p.on("timeout",()=>p.destroy(new Error(`HTTP mirror timed out after ${n}ms`))),p.write(s),p.end();})}function de(i,t){try{existsSync(ee)||mkdirSync(ee,{recursive:!0}),appendFileSync(join(ee,"http-errors.log"),`${new Date().toISOString()} | ${i} | ${t.message}
2
- `);}catch{}}function Ye(i){return new Promise(t=>setTimeout(t,i))}var ye=1e4,nt=3e4,W=500,G=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,o,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:n,startedAt:o,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(),o){let r={executionId:t,status:e,finishedAt:n,metadata:o},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(t,e,n){let o={id:t,projectRoot:e,startedAt:n,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 n={sessionId:t,finishedAt:e},o=this.commitOrCache("session_end",n);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),o}async flushCache(){try{let n=this.getDatabase(),o=n.listTelemetryFailures({unresolvedOnly:!0,limit:W}).reverse();for(let r of o)try{this.applyOperation(r.operation,r.payload),n.resolveTelemetryFailure(r.id);}catch{}n.trimTelemetryFailures(W);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync$1(n)).flatMap(n=>readdirSync(n).filter(o=>o.endsWith(".json")).map(o=>{let r=join$1(n,o);try{return {cacheFile:r,envelope:it(JSON.parse(readFileSync(r,"utf8")),o)}}catch{return null}})).filter(n=>n!==null).sort((n,o)=>n.envelope.timestamp-o.envelope.timestamp||he(n.envelope.operation)-he(o.envelope.operation));for(let{cacheFile:n,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$1(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:be(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(be(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 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:n,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,n){let o=Date.now(),r={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:o};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:o}),s.trimTelemetryFailures(W),this.scheduleRetry();return}catch{}try{existsSync$1(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync$1(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-W)))unlinkSync$1(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},nt).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){j(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ye?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ye)}...`}}};function he(i){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(i)}function be(i){return `hook-run:${i}`}function it(i,t){if(!i||typeof i!="object")throw new Error("Invalid telemetry cache envelope");let e=i;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 o=e.payload??{},r=Number(o.timestamp??o.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:n,payload:o,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:r}}async function ve(i){let t=!i.memory,e=i.memory??new MemoryGate(i.projectRoot),n=0,o=0;try{await e.forceWarmUp(),i.trigger==="session_end"&&(n=await e.releasePendingDistillLeases(i.sessionId)),o=e.getPendingEventCount(i.sessionId,i.trigger!=="session_end");}finally{t&&e.close();}let r=Date.now(),s=i.trigger==="session_end"&&i.sessionId?`distill:session_end:${createHash("sha256").update(`${i.projectRoot}\0${i.sessionId}`).digest("hex").slice(0,24)}`:`distill:${r}:${Math.random().toString(36).slice(2,10)}`,a={id:s,pendingEvents:o,releasedLeases:n,trigger:i.trigger,sessionId:i.sessionId,details:i.details};try{let c=openGlobalDevFlowDatabase();try{c.recordMemoryDistillCheckpoint({id:s,projectRoot:i.projectRoot,sessionId:i.sessionId,trigger:i.trigger,pendingEvents:o,releasedLeases:n,details:i.details,createdAt:r}),c.insertEvent({kind:"memory_distill_requested",timestamp:r,success:!0,metadata:{...a,projectRoot:i.projectRoot}});}finally{c.close();}}catch(c){throw c}return a}function _e(i){return Buffer.from(i,"utf8").toString("base64url")}function dt(i,t,e){let n=t?.trim();if(n){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(n)?n:`tool-${createHash$1("sha256").update(n.slice(0,1024)).digest("hex").slice(0,32)}`;return `${i}:${o}`}return `${i}:legacy-${e}-${randomUUID().slice(0,8)}`}function De(i){return `${i}:legacy-journal`}var L=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(k(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 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,n){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(n)],o.lastActivityAt=Date.now(),this.persist(o),o}get(t){let e=t.trim();if(!e)return null;let n=this.sessions.get(e);if(n)return this.replayEvidenceJournal(n),n;let o=this.snapshotPath(e);if(!existsSync$1(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=Re(r.evidenceObligations),r.evidenceDegradations=Ee(r.evidenceDegradations),r.evidenceOutcomes=ke(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(),o){let r=this.registerSession(t),a=(o?void 0:r.evidenceObligations.find(u=>u.contractId===e.id))?.obligationId??dt(e.id,o,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(u=>u.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,o,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(p=>p.obligationId===e);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(o)?o:"";if(!c)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:c,violations:n.slice(0,16).map(p=>p.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let u=s.evidenceObligations.find(p=>p.obligationId===e);return u?structuredClone(u):null}resolveEvidenceObligation(t,e){let n=this.get(t);if(!n)return false;let o=n.evidenceObligations.find(s=>s.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(n),n.lastActivityAt=r,this.persist(n),true}degradeEvidenceObligation(t,e,n,o=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:o,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(r),r.lastActivityAt=o,this.persist(r),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync$1(this.snapshotPath(e),{force:true}),rmSync$1(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${_e(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",_e(t))}appendEvidenceEvent(t,e,n){let o=this.evidenceJournalDir(t);mkdirSync$1(o,{recursive:true,mode:448});let r=createHash$1("sha256").update(n).digest("hex"),s=join$1(o,`${e.kind}-${r}.json`);if(existsSync$1(s))return;let a=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync$1(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Re(t.evidenceObligations),t.evidenceDegradations=Ee(t.evidenceDegradations),t.evidenceOutcomes=ke(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync$1(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 o=n.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=ut(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||Ae(r.kind)-Ae(s.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 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 o=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!o||n||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??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$1(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),n=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(n,JSON.stringify(t),{mode:384}),renameSync$1(n,e);}};function Re(i){return Array.isArray(i)?i.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)||!Oe(e.contract))return [];let n=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:De(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:n,correctionFingerprint:r}]}).slice(-8):[]}function Ee(i){return Array.isArray(i)?i.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 ke(i){return Array.isArray(i)?i.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 ut(i){if(!i||typeof i!="object")return null;let t=i,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:De(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return Oe(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(s=>typeof s=="string"&&s.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 Ae(i){return i==="add"?0:i==="correction"?1:2}function Oe(i){if(!i||typeof i!="object")return false;let t=i,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(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 $e(i,t){let e=yt(i);mkdirSync(e,{recursive:true,mode:448});let n=join(e,`${t.receiptId}.json`);if(existsSync(n))return t.receiptId;let o=`${n}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384});try{renameSync(o,n);}catch(r){try{unlinkSync(o);}catch{}if(!existsSync(n))throw r}return t.receiptId}function yt(i){return join(k(i),"session-finalize-pending")}var wt=512*1024,_t=500;var Rt=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function Et(i){let t=false,e=[],n=[];for(let o of i){if(/^\s*```/.test(o)){t=!t,e.push(""),n.push(o.replace(/^\s*```+[^\s`]*/,"").replace(/```+\s*$/,"").trim());continue}e.push(t?"":o.replace(/`[^`]*`/g,"").trim()),n.push(o.replace(/`([^`]*)`/g,(r,s)=>kt(s)?"":s).trim());}return {headingLines:e,claimLines:n}}function kt(i){let t=i.trim().slice(0,256);return !t||/\s/.test(t)||i.trim().length>256?false:/^[A-Za-z_$][\w$.-]*$/.test(t)||/^(['"])[^'"`]*\1$/.test(t)}function At(i,t){if(!i||i.length>4096)return {degradationReason:"transcript_path_missing"};let e;try{let n=lstatSync(i);if(!n.isFile()||n.isSymbolicLink())return {degradationReason:"transcript_path_unsafe"};e=openSync(i,constants.O_RDONLY|(constants.O_NOFOLLOW??0));let o=fstatSync(e);if(!o.isFile()||o.dev!==n.dev||o.ino!==n.ino)return {degradationReason:"transcript_path_changed"};let r=Math.min(o.size,wt),s=Buffer.alloc(r),a=0;for(;a<r;){let h=readSync(e,s,a,r-a,o.size-r+a);if(h===0)break;a+=h;}let c=s.subarray(0,a).toString("utf8");o.size>r&&(c=c.slice(Math.max(0,c.indexOf(`
3
- `)+1)));let u=c.split(/\r?\n/).slice(-_t),p=t.length>0?Math.min(...t.map(h=>h.promptedAt)):0,g=Dt(u,p),b=[...g].reverse().find(h=>xt(h.text,t))??g.at(-1);return b?.text?{answer:b.text,fingerprint:b.fingerprint}:{degradationReason:"transcript_answer_unavailable"}}catch{return {degradationReason:"transcript_unreadable"}}finally{e!==void 0&&closeSync(e);}}function xt(i,t){let e=new Set(t.flatMap(o=>o.contract.requiredSections)),n=Ct(Et(i.split(/\r?\n/u)).headingLines);return [...e].every(o=>n.found.has(o))}function Fe(i){return At(i,[]).answer}function Dt(i,t){let e=[];for(let n=0;n<i.length;n++){let o=i[n];if(o.trim())try{let r=JSON.parse(o),s=r.message;if(!s||typeof s!="object"||s.role!=="assistant")continue;let a=s,c=Ot(r.timestamp);if(c>0&&c+5e3<t)continue;let u=s.content,p=typeof u=="string"?u:Array.isArray(u)?u.filter(g=>g&&typeof g=="object"&&g.type==="text").map(g=>g.text).filter(g=>typeof g=="string").join(`
4
- `):"";if(p.trim()){let g=p.trim(),y=typeof a.id=="string"&&a.id?`message:${a.id}`:typeof r.uuid=="string"&&r.uuid?`uuid:${r.uuid}`:`record:${String(r.timestamp??"")}:${n}:${createHash("sha256").update(o).digest("hex")}`,b=createHash("sha256").update(g).digest("hex"),h=createHash("sha256").update(`${y}\0${b}`).digest("hex");e.push({text:g,timestamp:c,fingerprint:h});}}catch{continue}}return e}function Ot(i){if(typeof i=="number"&&Number.isFinite(i))return i;if(typeof i!="string")return 0;let t=Date.parse(i);return Number.isFinite(t)?t:0}function Ct(i){let t=new Set,e=new Map,n;for(let o=0;o<i.length;o++){let r=i[o].trim().replace(/^#{1,6}\s*/,"").replace(/^\*\*(.*)\*\*$/,"$1").replace(/^(?:[一二三123][、..]\s*)/,"").replace(/[::]\s*$/,"").trim(),s=Rt.find(a=>r===a);s&&(n=s,t.add(s)),e.set(o,n);}return {found:t,byLine:e}}function ze(i){let t=openGlobalDevFlowDatabase();try{let e=t.listRetrievalLedgerEvents(i),n=new Map(e.filter(c=>c.stage==="selected").map(c=>[Me(c),c])),o=new Map(e.filter(c=>c.stage==="adopted").map(c=>[Me(c),c])),r=0,s=0,a=0;for(let[c,u]of n){let p=o.get(c),g=p&&i.verificationReceipt&&i.outcome!=="unknown"?i.outcome:"unknown",y=g==="positive"?"positive_outcome":g==="negative"?"negative_outcome":"unknown";t.appendRetrievalLedgerEvent({...u,id:Pt(u.id,y,i.verificationReceipt??i.sessionId),stage:y,reason:p?i.outcomeReason:"selected_not_adopted",toolEvidence:p?.toolEvidence??[],verificationReceipt:g==="unknown"?void 0:i.verificationReceipt,payload:{...u.payload,adopted:!!p},createdAt:i.finishedAt??Date.now()}),y==="positive_outcome"?r+=1:y==="negative_outcome"?s+=1:a+=1;}return {adopted:o.size,positive:r,negative:s,unknown:a}}finally{t.close();}}function Pt(i,t,e){return `retrieval:${createHash("sha256").update(`${i}\0${t}\0${e}`).digest("hex")}`}function Me(i){return [i.requestId,i.contextReceipt,i.sourceType,i.sourceId].join("\0")}function jt(i){let t={committed:0,skipped:0,pending:0},e=[];for(let n of i)t[n.status]+=1,n.receiptId&&e.push(n.receiptId);return {memoryReceiptIds:[...new Set(e)],missingMemoryDecisionCount:t.pending,memoryTurnOutcomes:t}}function D(i){return (i instanceof Error?i.message:String(i)).trim().slice(0,240)||"memory_lifecycle_unavailable"}var w=class extends Error{constructor(t,e){super(`session_finalize_${t}:${e}`),this.name="SessionFinalizationRetryableError",this.category=`session_finalize_${t}`;}};function N(i){let t;try{t=openGlobalDevFlowDatabase();let e=(i.executionId?t.getSkillExecution(i.executionId):null)??t.getLatestSkillExecutionForSession(i.sessionId),n={stage:i.stage,reason:i.reason,degradedAt:Date.now()};e&&t.mergeSkillExecutionMetadata(e.executionId,{...i.metadata,sessionFinalizationDegradations:[n]}),t.insertEvent({kind:"session_finalize_degraded",timestamp:n.degradedAt,success:!1,metadata:{projectRoot:i.projectRoot,sessionId:i.sessionId,executionId:e?.executionId,...n}});}catch{}finally{t?.close();}}function Lt(i,t=B(),e=true,n,o=true){let r;try{r=JSON.parse(i);}catch{return null}let s=r.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${t}\0${s}`).digest("hex").slice(0,24)}`,c={inputJson:i,sessionId:s,cleanupSharedState:e,executionId:n},u;try{u=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let p=u.requestSessionClosure({receiptId:a,projectRoot:t,sessionId:s,payload:c}),g=u.getWorkByIdempotencyKey(a);return {status:p.state==="closed"||p.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:g?.state??"pending",closureState:p.state,pendingWorkCount:p.pendingWorkCount}}catch(p){if(!o)throw p;return $e(t,{receiptId:a,...c}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{u?.close();}}async function ri(i,t=B(),e=true,n){let o;try{o=JSON.parse(i);}catch{return}let r=o.session_id?.trim();if(!r)return;let s=new L(t),a=s.get(r),c={evidenceDegradations:a?.evidenceDegradations??[],evidenceContractOutcomes:a?.evidenceOutcomes??[],pendingEvidenceContractIds:a?.evidenceObligations.map(b=>b.contractId)??[]},u=n?.telemetry??new G,p=!n?.telemetry,g=false,y;try{try{await u.flushAndAggregate();}catch{}let b=Date.now(),h=n?.executionId??a?.executionId,C;try{let m=openGlobalDevFlowDatabase();try{C=m.listSessionMemoryTurnsForReconciliation(t,r);for(let l of C){let f=`memory:${l.turnId}`,d=m.getSessionObligation(t,r,f);d?d.state==="open"&&l.status!=="pending"&&m.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:f,state:"satisfied",receiptId:l.receiptId,reason:l.reason,resolvedAt:l.decidedAt}):m.upsertSessionObligation({obligationId:f,projectRoot:t,sessionId:r,turnId:l.turnId,kind:"memory_decision",state:l.status==="pending"?"open":"satisfied",payload:{eventId:l.eventId,promptHash:l.promptHash},receiptId:l.receiptId,reason:l.reason,createdAt:l.createdAt,updatedAt:l.decidedAt??l.createdAt,resolvedAt:l.decidedAt});}}finally{m.close();}}catch(m){let l=D(m),f={...c,memoryEventReconciliation:{status:"degraded",stage:"turn_load",reason:l,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw N({projectRoot:t,sessionId:r,executionId:h,stage:"turn_load",reason:l,metadata:f}),new w("turn_load",l)}let T=jt(C),_=n?.memory??(y=new MemoryGate(t)),q={status:"completed"};try{q=typeof _.reconcileTurnObservationLineage=="function"?{status:"completed",...await _.reconcileTurnObservationLineage(C)}:{status:"unsupported_adapter",committed:0,skipped:0,quarantined:0,unlinked:0};}catch(m){let l=D(m);throw q={status:"degraded",reason:l},N({projectRoot:t,sessionId:r,executionId:h,stage:"memory_lineage",reason:l,metadata:{...T,...c,memoryLineageReconciliation:q}}),new w("memory_lineage",l)}let H={status:"unknown",selected:0,adopted:0,unknown:0,positive:0,negative:0};try{let m=Fe(o.transcript_path),l=openGlobalDevFlowDatabase(),f="unknown",d="no_terminal_host_action_evidence",U,F,M,Z=[];try{let X=l.listHostActionsForSession(t,r,h),oe=X.filter(v=>v.state==="verified"),Y=X.filter(v=>["failed","cancelled","degraded"].includes(v.state));Y.length>0?(f="negative",d=`terminal_host_action_${Y[0].state}`):oe.length>0&&(f="positive",d="host_action_verified");let J=Y[0]??oe.at(-1);if(U=J?.runId,F=J?.contextReceipt,M=J?.evidenceHash,Z=X.flatMap(v=>{let E=v.report.toolUseIds;return Array.isArray(E)?E.filter(z=>typeof z=="string"):[]}),!J&&h){let v=l.getSkillExecution(h),E=v?.metadata&&typeof v.metadata=="object"&&Array.isArray(v.metadata.policyVerificationOutcomes)?v.metadata.policyVerificationOutcomes:[],z=E.find(I=>I.status==="failed"),K=E.filter(I=>I.status==="passed");z?(f="negative",d="policy_verification_failed",M=typeof z.receiptId=="string"?z.receiptId:void 0):K.length>0&&(f="positive",d="policy_verification_passed",M=typeof K.at(-1)?.receiptId=="string"?String(K.at(-1).receiptId):void 0),F=l.getActiveContextReceipt(t,r,h)?.contextHash,Z=E.map(I=>I.command).filter(I=>typeof I=="string");}}finally{l.close();}let Le=ze({projectRoot:t,sessionId:r,executionId:h,outcome:f,outcomeReason:d,verificationReceipt:M,finishedAt:b}),Ne=await _.attributeRetrievalBenefits({sessionId:r,executionId:h,finalAnswer:m,outcome:f,outcomeReason:d,workflowRunId:U,contextReceipt:F,toolEvidence:Z,verificationReceipt:M});H={status:m?"evaluated":"unknown",...Ne,retrievalLedger:Le};}catch(m){H={...H,status:"degraded",reason:D(m)};}let R;try{R=await _.reconcileDecidedTurnEventWindows(r,C,b);}catch(m){let l=D(m),f={...T,...c,memoryEventReconciliation:{status:"degraded",stage:"event_reconciliation",reason:l,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw N({projectRoot:t,sessionId:r,executionId:h,stage:"event_reconciliation",reason:l,metadata:f}),new w("event_reconciliation",l)}let $;try{$=await ve({projectRoot:t,sessionId:r,trigger:"session_end",memory:_,details:{eventReconciliation:R},strictPersistence:!0});}catch(m){let l=D(m),f={...T,...c,memoryEventReconciliation:{status:"completed",...R,checkpointPending:null},memoryCheckpointDegradation:l};throw N({projectRoot:t,sessionId:r,executionId:h,stage:"checkpoint",reason:l,metadata:f}),new w("checkpoint",l)}let re={memoryLineageReconciliation:q,memoryBenefitAttribution:H,memoryEventReconciliation:{status:"completed",...R,checkpointPending:$.pendingEvents},memoryDistillCheckpoint:$};try{let m=openGlobalDevFlowDatabase();try{let l=`session-finalize:${r}:events`,f=Math.max(Number($.pendingEvents??0),Number(R.remainingUndecided??0)),d=m.getSessionObligation(t,r,l);f>0?m.upsertSessionObligation({obligationId:l,projectRoot:t,sessionId:r,executionId:h,kind:"session_finalize",state:"open",payload:{pendingEvents:f,reconciliation:R,checkpointId:$.id},reason:"active_unprocessed_session_events",createdAt:d?.createdAt??b,updatedAt:b}):d?.state==="open"&&m.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:l,state:"satisfied",reason:"session_events_reconciled",resolvedAt:b});}finally{m.close();}}catch(m){console.error("[devflow] Session finalization obligation persistence failed:",m.message);}try{await _.closeSession(r),y&&(y.close(),y=void 0);}catch(m){let l=D(m),f={...T,...c,...re,memorySessionCloseDegradation:l};throw N({projectRoot:t,sessionId:r,executionId:h,stage:"memory_close",reason:l,metadata:f}),new w("memory_close",l)}let P={...T,...c,...re};g=!0;let S;try{S=openGlobalDevFlowDatabase();let m=h;if(m)try{S.reconcileSkillExecution(m,"completed",b,P);let d=S.getSkillExecution(m);await j("/api/telemetry/skill-execution/complete",{executionId:m,finishedAt:b,status:"completed",summary:{totalToolCalls:d?.totalToolCalls??0,mcpToolCalls:d?.mcpToolCalls??0,directToolCalls:d?.directToolCalls??0,subagentCount:d?.subagentCount??0,totalDuration:d?.totalDuration??0,mcpComplianceRate:d?.mcpComplianceRate??0,missedTools:d?.missedMcpTools??[],actualFailureCount:d?.failedToolCalls??0,fallbackCount:d?.fallbackCount??0,fallbackReasons:d?.fallbackReasons??[]},metadata:P},{fallbackReason:"skill_execution_already_reconciled_locally"});}catch{}let l=S.reconcileRunningSkillExecutionsForSession(r,b,{closureReason:"session_finalize",...P});for(let d of l)await j("/api/telemetry/skill-execution/complete",{executionId:d.executionId,finishedAt:d.finishedAt,status:d.status,summary:{totalToolCalls:d.totalToolCalls??0,mcpToolCalls:d.mcpToolCalls??0,directToolCalls:d.directToolCalls??0,subagentCount:d.subagentCount??0,totalDuration:d.totalDuration??0,mcpComplianceRate:d.mcpComplianceRate??0,missedTools:d.missedMcpTools??[],actualFailureCount:d.failedToolCalls??0,fallbackCount:d.fallbackCount??0,fallbackReasons:d.fallbackReasons??[]},metadata:P},{fallbackReason:"skill_execution_already_reconciled_locally"});let f=S.getLatestSkillExecutionForSession(r);if(f&&!l.some(d=>d.executionId===f.executionId)&&S.mergeSkillExecutionMetadata(f.executionId,P),e){S.deleteHookReceipt(t);let d=k(t),U=createHash("sha256").update(t).digest("hex").slice(0,12);for(let F of [`session-id-${U}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join(d,F),{force:!0});}S.deleteContextReceipt(t,r);}catch{}finally{S?.close();}try{await u.endSession(r),await u.flushAndAggregate();}catch{}}finally{if(y)try{y.close();}catch{}p&&u.close(),g&&s.removeSession(r);}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let i=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()=>{let e=Lt(t.trim()||process.argv[2]||"");e&&i(JSON.stringify(e)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}export{jt as buildMemoryTurnOutcomeMetadata,Lt as enqueueSessionEndFinalization,ri as handleSessionEnd};
1
+ import {getLocalApiKey,getProjectStateDir,claudeCodeRuntimeAdapter,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {MemoryGate}from'@devflow-tools/memory-engine';import {existsSync as existsSync$1,readFileSync,rmSync as rmSync$1,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1,unlinkSync as unlinkSync$1}from'fs';import {join as join$1}from'path';import {homedir as homedir$1}from'os';import {request}from'node:http';import {mkdirSync,existsSync,writeFileSync,renameSync,unlinkSync,rmSync,statSync,openSync,readSync,closeSync,lstatSync,constants,fstatSync,appendFileSync}from'node:fs';import {join}from'node:path';import {homedir}from'node:os';import {createHash}from'node:crypto';import {randomUUID,createHash as createHash$1}from'crypto';import {emitSemanticControlLog}from'@devflow-tools/telemetry';function V(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function q(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(V(n))}function ne(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 rt=getLocalApiKey(),ie=join(homedir(),".devflow","errors");async function J(n,t,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,n);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let m;for(let f=0;f<=s;f+=1)try{return await ot(i,n,t,o),a&&registerRuntimeHttpSuccess(i,n).transitioned&&ne("http_circuit_transition",{endpoint:i,path:new URL(n,i).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(y){m=y instanceof Error?y:new Error(String(y)),f<s&&await st(Math.min(100*2**f,1e3));}if(!m)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return ge(n,m),{delivered:false,suppressed:false,fallbackReason:m.message};let p=registerRuntimeHttpFailure(i,n,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return p.transitioned&&(ge(n,m),ne("http_circuit_transition",{endpoint:i,path:new URL(n,i).pathname,previous:c.state.status,status:"open",failures:p.state.failures,openUntil:p.state.openUntil,fallbackReason:p.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:p.state.fallbackReason}}function ot(n,t,e,i){return new Promise((o,r)=>{let s=JSON.stringify(e),a=new URL(t,n),c=false,m=f=>{c||(c=true,f?r(f):o());},p=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":rt,"Content-Length":Buffer.byteLength(s)},timeout:i},f=>{f.on("error",m),f.on("end",()=>{let y=f.statusCode??0;m(y>=200&&y<300?void 0:new Error(`HTTP ${y}`));}),f.resume();});p.on("error",m),p.on("timeout",()=>p.destroy(new Error(`HTTP mirror timed out after ${i}ms`))),p.write(s),p.end();})}function ge(n,t){try{existsSync(ie)||mkdirSync(ie,{recursive:!0}),appendFileSync(join(ie,"http-errors.log"),`${new Date().toISOString()} | ${n} | ${t.message}
2
+ `);}catch{}}function st(n){return new Promise(t=>setTimeout(t,n))}var Ie=1e4,ut=3e4,Z=500,X=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(),s=[]){let a={executionId:t,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(t,e="completed",i=Date.now(),o){let r={executionId:t,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(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:Z}).reverse();for(let r of o)try{this.applyOperation(r.operation,r.payload),i.resolveTelemetryFailure(r.id);}catch{}i.trimTelemetryFailures(Z);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(i=>!!i))].filter(i=>existsSync$1(i)).flatMap(i=>readdirSync(i).filter(o=>o.endsWith(".json")).map(o=>{let r=join$1(i,o);try{return {cacheFile:r,envelope:mt(JSON.parse(readFileSync(r,"utf8")),o)}}catch{return null}})).filter(i=>i!==null).sort((i,o)=>i.envelope.timestamp-o.envelope.timestamp||we(i.envelope.operation)-we(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$1(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:Se(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(Se(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 s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:o}),s.trimTelemetryFailures(Z),this.scheduleRetry();return}catch{}try{existsSync$1(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync$1(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-Z)))unlinkSync$1(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},ut).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){J(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=Ie?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,Ie)}...`}}};function we(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function Se(n){return `hook-run:${n}`}function mt(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}}async function Re(n){let t=!n.memory,e=n.memory??new MemoryGate(n.projectRoot),i=0,o=0;try{await e.forceWarmUp(),n.trigger==="session_end"&&(i=await e.releasePendingDistillLeases(n.sessionId)),o=e.getPendingEventCount(n.sessionId,n.trigger!=="session_end");}finally{t&&e.close();}let r=Date.now(),s=n.trigger==="session_end"&&n.sessionId?`distill:session_end:${createHash("sha256").update(`${n.projectRoot}\0${n.sessionId}`).digest("hex").slice(0,24)}`:`distill:${r}:${Math.random().toString(36).slice(2,10)}`,a={id:s,pendingEvents:o,releasedLeases:i,trigger:n.trigger,sessionId:n.sessionId,details:n.details};try{let c=openGlobalDevFlowDatabase();try{c.recordMemoryDistillCheckpoint({id:s,projectRoot:n.projectRoot,sessionId:n.sessionId,trigger:n.trigger,pendingEvents:o,releasedLeases:i,details:n.details,createdAt:r}),c.insertEvent({kind:"memory_distill_requested",timestamp:r,success:!0,metadata:{...a,projectRoot:n.projectRoot}});}finally{c.close();}}catch(c){throw c}return a}function xe(n){return Buffer.from(n,"utf8").toString("base64url")}function vt(n,t,e){let i=t?.trim();if(i){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(i)?i:`tool-${createHash$1("sha256").update(i.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${o}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function Pe(n){return `${n}:legacy-journal`}var B=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(q(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$1(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=Te(r.evidenceObligations),r.evidenceDegradations=Ce(r.evidenceDegradations),r.evidenceOutcomes=De(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),a=(o?void 0:r.evidenceObligations.find(m=>m.contractId===e.id))?.obligationId??vt(e.id,o,i);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:i,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let c=r.evidenceObligations.find(m=>m.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,i,o,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(p=>p.obligationId===e);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(o)?o:"";if(!c)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:c,violations:i.slice(0,16).map(p=>p.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let m=s.evidenceObligations.find(p=>p.obligationId===e);return m?structuredClone(m):null}resolveEvidenceObligation(t,e){let i=this.get(t);if(!i)return false;let o=i.evidenceObligations.find(s=>s.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}degradeEvidenceObligation(t,e,i,o=Date.now()){let r=this.get(t),s=r?.evidenceObligations.find(c=>c.obligationId===e);if(!r||!s)return false;let a=i.slice(0,240);return this.appendEvidenceEvent(t,{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(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync$1(this.snapshotPath(e),{force:true}),rmSync$1(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${xe(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",xe(t))}appendEvidenceEvent(t,e,i){let o=this.evidenceJournalDir(t);mkdirSync$1(o,{recursive:true,mode:448});let r=createHash$1("sha256").update(i).digest("hex"),s=join$1(o,`${e.kind}-${r}.json`);if(existsSync$1(s))return;let a=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync$1(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Te(t.evidenceObligations),t.evidenceDegradations=Ce(t.evidenceDegradations),t.evidenceOutcomes=De(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync$1(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=_t(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||Oe(r.kind)-Oe(s.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(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 o=t.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??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: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$1(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),i=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(i,JSON.stringify(t),{mode:384}),renameSync$1(i,e);}};function Te(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)||!Me(e.contract))return [];let i=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Pe(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 Ce(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 _t(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:Pe(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return Me(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(s=>typeof s=="string"&&s.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 Oe(n){return n==="add"?0:n==="correction"?1:2}function Me(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 qe(n,t){let e=kt(n);mkdirSync(e,{recursive:true,mode:448});let i=join(e,`${t.receiptId}.json`);if(existsSync(i))return t.receiptId;let o=`${i}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384});try{renameSync(o,i);}catch(r){try{unlinkSync(o);}catch{}if(!existsSync(i))throw r}return t.receiptId}function kt(n){return join(q(n),"session-finalize-pending")}var Dt=512*1024,Ot=500;var $t=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function Pt(n){let t=false,e=[],i=[];for(let o of n){if(/^\s*```/.test(o)){t=!t,e.push(""),i.push(o.replace(/^\s*```+[^\s`]*/,"").replace(/```+\s*$/,"").trim());continue}e.push(t?"":o.replace(/`[^`]*`/g,"").trim()),i.push(o.replace(/`([^`]*)`/g,(r,s)=>Mt(s)?"":s).trim());}return {headingLines:e,claimLines:i}}function Mt(n){let t=n.trim().slice(0,256);return !t||/\s/.test(t)||n.trim().length>256?false:/^[A-Za-z_$][\w$.-]*$/.test(t)||/^(['"])[^'"`]*\1$/.test(t)}function Ft(n,t){if(!n||n.length>4096)return {degradationReason:"transcript_path_missing"};let e;try{let i=lstatSync(n);if(!i.isFile()||i.isSymbolicLink())return {degradationReason:"transcript_path_unsafe"};e=openSync(n,constants.O_RDONLY|(constants.O_NOFOLLOW??0));let o=fstatSync(e);if(!o.isFile()||o.dev!==i.dev||o.ino!==i.ino)return {degradationReason:"transcript_path_changed"};let r=Math.min(o.size,Dt),s=Buffer.alloc(r),a=0;for(;a<r;){let h=readSync(e,s,a,r-a,o.size-r+a);if(h===0)break;a+=h;}let c=s.subarray(0,a).toString("utf8");o.size>r&&(c=c.slice(Math.max(0,c.indexOf(`
3
+ `)+1)));let m=c.split(/\r?\n/).slice(-Ot),p=t.length>0?Math.min(...t.map(h=>h.promptedAt)):0,f=qt(m,p),_=[...f].reverse().find(h=>jt(h.text,t))??f.at(-1);return _?.text?{answer:_.text,fingerprint:_.fingerprint}:{degradationReason:"transcript_answer_unavailable"}}catch{return {degradationReason:"transcript_unreadable"}}finally{e!==void 0&&closeSync(e);}}function jt(n,t){let e=new Set(t.flatMap(o=>o.contract.requiredSections)),i=zt(Pt(n.split(/\r?\n/u)).headingLines);return [...e].every(o=>i.found.has(o))}function ze(n){return Ft(n,[]).answer}function qt(n,t){let e=[];for(let i=0;i<n.length;i++){let o=n[i];if(o.trim())try{let r=JSON.parse(o),s=r.message;if(!s||typeof s!="object"||s.role!=="assistant")continue;let a=s,c=Lt(r.timestamp);if(c>0&&c+5e3<t)continue;let m=s.content,p=typeof m=="string"?m:Array.isArray(m)?m.filter(f=>f&&typeof f=="object"&&f.type==="text").map(f=>f.text).filter(f=>typeof f=="string").join(`
4
+ `):"";if(p.trim()){let f=p.trim(),y=typeof a.id=="string"&&a.id?`message:${a.id}`:typeof r.uuid=="string"&&r.uuid?`uuid:${r.uuid}`:`record:${String(r.timestamp??"")}:${i}:${createHash("sha256").update(o).digest("hex")}`,_=createHash("sha256").update(f).digest("hex"),h=createHash("sha256").update(`${y}\0${_}`).digest("hex");e.push({text:f,timestamp:c,fingerprint:h});}}catch{continue}}return e}function Lt(n){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n!="string")return 0;let t=Date.parse(n);return Number.isFinite(t)?t:0}function zt(n){let t=new Set,e=new Map,i;for(let o=0;o<n.length;o++){let r=n[o].trim().replace(/^#{1,6}\s*/,"").replace(/^\*\*(.*)\*\*$/,"$1").replace(/^(?:[一二三123][、..]\s*)/,"").replace(/[::]\s*$/,"").trim(),s=$t.find(a=>r===a);s&&(i=s,t.add(s)),e.set(o,i);}return {found:t,byLine:e}}function He(n){let t=openGlobalDevFlowDatabase();try{let e=t.listRetrievalLedgerEvents(n),i=new Map(e.filter(c=>c.stage==="selected").map(c=>[Ne(c),c])),o=new Map(e.filter(c=>c.stage==="adopted").map(c=>[Ne(c),c])),r=0,s=0,a=0;for(let[c,m]of i){let p=o.get(c),f=p&&n.verificationReceipt&&n.outcome!=="unknown"?n.outcome:"unknown",y=f==="positive"?"positive_outcome":f==="negative"?"negative_outcome":"unknown";t.appendRetrievalLedgerEvent({...m,id:Ut(m.id,y,n.verificationReceipt??n.sessionId),stage:y,reason:p?n.outcomeReason:"selected_not_adopted",toolEvidence:p?.toolEvidence??[],verificationReceipt:f==="unknown"?void 0:n.verificationReceipt,payload:{...m.payload,adopted:!!p},createdAt:n.finishedAt??Date.now()}),y==="positive_outcome"?r+=1:y==="negative_outcome"?s+=1:a+=1;}return {adopted:o.size,positive:r,negative:s,unknown:a}}finally{t.close();}}function Ut(n,t,e){return `retrieval:${createHash("sha256").update(`${n}\0${t}\0${e}`).digest("hex")}`}function Ne(n){return [n.requestId,n.contextReceipt,n.sourceType,n.sourceId].join("\0")}var Yt=8*1024*1024;function Je(n){if(!n.transcriptPath||!existsSync(n.transcriptPath))return {status:"unavailable",eventsRead:0,failuresFound:0,failuresRecorded:0,reason:"transcript_path_unavailable"};let t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=t.getLatestTranscriptCheckpoint({projectRoot:n.projectRoot,hostId:"claude-code",sessionId:n.sessionId,sourcePath:n.transcriptPath}),i=statSync(n.transcriptPath).size,o=Math.min(e?.byteOffset??0,i),r=Math.min(Yt,i-o);if(r<=0)return {status:"completed",eventsRead:0,failuresFound:0,failuresRecorded:0,checkpointId:e?.id};let s=Buffer.alloc(r),a=openSync(n.transcriptPath,"r");try{readSync(a,s,0,r,o);}finally{closeSync(a);}let c=s.toString("utf8").split(/\r?\n/u).filter(Boolean),m=t.listLatestTaskIntentArtifacts(n.projectRoot,n.sessionId),p=new Map,f=0,y=0;for(let b of c){let R;try{R=JSON.parse(b);}catch{continue}for(let x of ae(R,p)){let v=claudeCodeRuntimeAdapter.normalizeToolResult(x,{projectRoot:n.projectRoot});if(v.success||!v.error)continue;f++;let T=[...m].reverse().find(E=>E.createdAt<=v.timestamp)??m.at(-1),M=`host-failure:${v.sourceHash}`;t.insertEvent({kind:"host_transcript_tool_failure",timestamp:v.timestamp,success:!1,toolName:v.canonicalName??v.requestedName,metadata:{projectRoot:n.projectRoot,sessionId:n.sessionId,turnId:T?.turnId,requestId:T?.requestId,sourceId:M,requestedName:v.requestedName,canonicalName:v.canonicalName,failureCategory:v.failureCategory,error:v.error.slice(0,1e3)}}),y++;}}let _=createHash("sha256").update(s).digest("hex"),h=`transcript:${createHash("sha256").update(`${n.projectRoot}\0${n.sessionId}\0${n.transcriptPath}\0${o+r}\0${_}`).digest("hex").slice(0,24)}`;return t.appendTranscriptCheckpoint({id:h,projectRoot:n.projectRoot,hostId:"claude-code",sessionId:n.sessionId,sourcePath:n.transcriptPath,sourceHash:_,byteOffset:o+r,eventCount:c.length,createdAt:Date.now()}),emitSemanticControlLog({event:"session.reconciled",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId},level:f>0?"warn":"info",timestamp:Date.now(),data:{stage:"transcript",eventsRead:c.length,failuresFound:f,failuresRecorded:y,checkpointId:h}}),{status:"completed",eventsRead:c.length,failuresFound:f,failuresRecorded:y,checkpointId:h}}catch(e){return {status:"degraded",eventsRead:0,failuresFound:0,failuresRecorded:0,reason:e instanceof Error?e.message:String(e)}}finally{t.close();}}function ae(n,t,e=0){if(e>7||n===null||n===void 0)return [];if(Array.isArray(n))return n.flatMap(s=>ae(s,t,e+1));if(typeof n!="object")return [];let i=n,o=typeof i.type=="string"?i.type:"";o==="tool_use"&&typeof i.id=="string"&&typeof i.name=="string"&&t.set(i.id,i.name);let r=[];if(o==="tool_result"){let s=typeof i.tool_use_id=="string"?i.tool_use_id:void 0;r.push({tool_name:s?t.get(s)??"unknown":"unknown",tool_use_id:s,tool_response:i.content,is_error:i.is_error===true,...i.is_error===true?{error:ce(i.content)||"host tool result failed"}:{},timestamp:i.timestamp});}else (i.tool_name||i.toolName)&&(i.tool_response!==void 0||i.output!==void 0||i.error!==void 0)&&r.push(i);for(let[s,a]of Object.entries(i))s==="content"&&o==="tool_result"||r.push(...ae(a,t,e+1));return r}function ce(n){if(typeof n=="string")return n.slice(0,4e3);if(Array.isArray(n))return n.map(ce).filter(Boolean).join(`
5
+ `).slice(0,4e3);if(!n||typeof n!="object")return "";let t=n;return [t.text,t.content,t.message].map(ce).filter(Boolean).join(`
6
+ `).slice(0,4e3)}var Be={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:["memory_decided","memory_quarantined"],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 We(n){let t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=t.getLatestTerminalTransition(n.artifact.projectRoot,n.artifact.sessionId,n.artifact.turnId);if(!e)throw new Error(`TERMINAL_INTENT_STATE_MISSING:${n.artifact.turnId}`);let i=n.memoryStatus==="pending"?n.retryOwned?"closed_with_retry_work":"closed_with_degradation":"closed";for(let o of en(e.toState,i,n.memoryStatus)){let r=e.sequence+1,s=`terminal:${createHash("sha256").update(`${n.artifact.artifactHash}\0${r}\0${o}`).digest("hex").slice(0,24)}`;e=t.appendTerminalTransition({projectRoot:n.artifact.projectRoot,projectId:n.artifact.projectId,hostId:n.artifact.hostId,sessionId:n.artifact.sessionId,turnId:n.artifact.turnId,requestId:n.artifact.requestId,executionId:n.artifact.executionId,sequence:r,fromState:e.toState,toState:o,receiptId:s,sourceReceiptId:n.memoryReceiptId??e.receiptId,reason:tn(o,n),payload:{memoryStatus:n.memoryStatus,retryOwned:n.retryOwned??!1,sourceIntentHash:n.artifact.artifactHash},createdAt:Date.now()}),emitSemanticControlLog({event:"terminal.state.transitioned",identity:{projectRoot:n.artifact.projectRoot,projectId:n.artifact.projectId,hostId:n.artifact.hostId,sessionId:n.artifact.sessionId,turnId:n.artifact.turnId,requestId:n.artifact.requestId,...n.artifact.executionId?{executionId:n.artifact.executionId}:{}},level:o==="closed"?"info":o.includes("degradation")||o.includes("retry")?"warn":"info",timestamp:Date.now(),data:{fromState:e.fromState,nextState:o,receiptId:s,reason:e.reason}});}return e}finally{t.close();}}function en(n,t,e){if(n===t||Be[n].length===0)return [];let i=e==="pending"?["context_degraded","action_not_required","action_degraded","memory_quarantined",t]:["context_degraded","action_not_required","action_degraded","memory_decided",t],o=[],r=n;for(let s of i)r!==s&&Be[r].includes(s)&&(o.push(s),r=s);if(r!==t)throw new Error(`TERMINAL_PATH_UNAVAILABLE:${n}->${t}`);return o}function tn(n,t){return n==="context_degraded"?"terminal_reconciliation_without_context_transition":n==="action_not_required"?"no_outstanding_canonical_action_receipt":n==="memory_decided"?`canonical_memory_${t.memoryStatus}`:n==="memory_quarantined"?t.reason:n==="closed_with_retry_work"?"durable_retry_owner_confirmed":n==="closed_with_degradation"?"terminal_obligation_unowned":t.reason}function sn(n){let t={committed:0,skipped:0,pending:0},e=[];for(let i of n)t[i.status]+=1,i.receiptId&&e.push(i.receiptId);return {memoryReceiptIds:[...new Set(e)],missingMemoryDecisionCount:t.pending,memoryTurnOutcomes:t}}function w(n){return (n instanceof Error?n.message:String(n)).trim().slice(0,240)||"memory_lifecycle_unavailable"}var P=class extends Error{constructor(t,e){super(`session_finalize_${t}:${e}`),this.name="SessionFinalizationRetryableError",this.category=`session_finalize_${t}`;}};function W(n){let t;try{t=openGlobalDevFlowDatabase();let e=(n.executionId?t.getSkillExecution(n.executionId):null)??t.getLatestSkillExecutionForSession(n.sessionId),i={stage:n.stage,reason:n.reason,degradedAt:Date.now()};e&&t.mergeSkillExecutionMetadata(e.executionId,{...n.metadata,sessionFinalizationDegradations:[i]}),t.insertEvent({kind:"session_finalize_degraded",timestamp:i.degradedAt,success:!1,metadata:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:e?.executionId,...i}}),emitSemanticControlLog({event:"hook.session_end.degraded",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:e?.executionId},level:"warn",timestamp:i.degradedAt,data:{stage:n.stage,reason:n.reason}});}catch{}finally{t?.close();}}function an(n,t=V(),e=true,i,o=true){let r;try{r=JSON.parse(n);}catch{return null}let s=r.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${t}\0${s}`).digest("hex").slice(0,24)}`,c={inputJson:n,sessionId:s,cleanupSharedState:e,executionId:i},m;try{m=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let p=m.requestSessionClosure({receiptId:a,projectRoot:t,sessionId:s,payload:c}),f=m.getWorkByIdempotencyKey(a),y={status:p.state==="closed"||p.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:f?.state??"pending",closureState:p.state,pendingWorkCount:p.pendingWorkCount};return emitSemanticControlLog({event:"hook.session_end.completed",identity:{projectRoot:t,sessionId:s,executionId:i,terminalReceipt:a},level:y.status==="completed"?"info":"debug",timestamp:Date.now(),data:{stage:"enqueue",...y}}),y}catch(p){if(!o)throw p;return qe(t,{receiptId:a,...c}),emitSemanticControlLog({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:s,executionId:i,terminalReceipt:a},level:"warn",timestamp:Date.now(),data:{stage:"enqueue",reason:w(p),fallback:"durable_spool"}}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{m?.close();}}async function zi(n,t=V(),e=true,i){let o;try{o=JSON.parse(n);}catch{return}let r=o.session_id?.trim();if(!r)return;let s=new B(t),a=s.get(r),c=Je({projectRoot:t,sessionId:r,transcriptPath:o.transcript_path}),m={evidenceDegradations:a?.evidenceDegradations??[],evidenceContractOutcomes:a?.evidenceOutcomes??[],pendingEvidenceContractIds:a?.evidenceObligations.map(h=>h.contractId)??[],transcriptReconciliation:c},p=i?.telemetry??new X,f=!i?.telemetry,y=false,_;try{try{await p.flushAndAggregate();}catch{}let h=Date.now(),b=i?.executionId??a?.executionId,R;try{let u=openGlobalDevFlowDatabase();try{R=u.listSessionMemoryTurnsForReconciliation(t,r);for(let d of R){let g=`memory:${d.turnId}`,l=u.getSessionObligation(t,r,g);l?l.state==="open"&&d.status!=="pending"&&u.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:g,state:"satisfied",receiptId:d.receiptId,reason:d.reason,resolvedAt:d.decidedAt}):u.upsertSessionObligation({obligationId:g,projectRoot:t,sessionId:r,turnId:d.turnId,kind:"memory_decision",state:d.status==="pending"?"open":"satisfied",payload:{eventId:d.eventId,promptHash:d.promptHash},receiptId:d.receiptId,reason:d.reason,createdAt:d.createdAt,updatedAt:d.decidedAt??d.createdAt,resolvedAt:d.decidedAt});}}finally{u.close();}}catch(u){let d=w(u),g={...m,memoryEventReconciliation:{status:"degraded",stage:"turn_load",reason:d,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw W({projectRoot:t,sessionId:r,executionId:b,stage:"turn_load",reason:d,metadata:g}),new P("turn_load",d)}let x=sn(R),v=i?.memory??(_=new MemoryGate(t)),T={status:"completed"};try{T=typeof v.reconcileTurnObservationLineage=="function"?{status:"completed",...await v.reconcileTurnObservationLineage(R)}:{status:"unsupported_adapter",committed:0,skipped:0,quarantined:0,unlinked:0};}catch(u){let d=w(u);throw T={status:"degraded",reason:d},W({projectRoot:t,sessionId:r,executionId:b,stage:"memory_lineage",reason:d,metadata:{...x,...m,memoryLineageReconciliation:T}}),new P("memory_lineage",d)}let M={status:"unknown",selected:0,adopted:0,unknown:0,positive:0,negative:0};try{let u=ze(o.transcript_path),d=openGlobalDevFlowDatabase(),g="unknown",l="no_terminal_host_action_evidence",H,C,A,D=[];try{let Q=d.listHostActionsForSession(t,r,b),le=Q.filter(S=>S.state==="verified"),ee=Q.filter(S=>["failed","cancelled","degraded"].includes(S.state));ee.length>0?(g="negative",l=`terminal_host_action_${ee[0].state}`):le.length>0&&(g="positive",l="host_action_verified");let G=ee[0]??le.at(-1);if(H=G?.runId,C=G?.contextReceipt,A=G?.evidenceHash,D=Q.flatMap(S=>{let j=S.report.toolUseIds;return Array.isArray(j)?j.filter(U=>typeof U=="string"):[]}),!G&&b){let S=d.getSkillExecution(b),j=S?.metadata&&typeof S.metadata=="object"&&Array.isArray(S.metadata.policyVerificationOutcomes)?S.metadata.policyVerificationOutcomes:[],U=j.find(O=>O.status==="failed"),te=j.filter(O=>O.status==="passed");U?(g="negative",l="policy_verification_failed",A=typeof U.receiptId=="string"?U.receiptId:void 0):te.length>0&&(g="positive",l="policy_verification_passed",A=typeof te.at(-1)?.receiptId=="string"?String(te.at(-1).receiptId):void 0),C=d.getActiveContextReceipt(t,r,b)?.contextHash,D=j.map(O=>O.command).filter(O=>typeof O=="string");}}finally{d.close();}let Ve=He({projectRoot:t,sessionId:r,executionId:b,outcome:g,outcomeReason:l,verificationReceipt:A,finishedAt:h}),Ze=await v.attributeRetrievalBenefits({sessionId:r,executionId:b,finalAnswer:u,outcome:g,outcomeReason:l,workflowRunId:H,contextReceipt:C,toolEvidence:D,verificationReceipt:A});M={status:u?"evaluated":"unknown",...Ze,retrievalLedger:Ve};}catch(u){M={...M,status:"degraded",reason:w(u)};}let E;try{E=await v.reconcileDecidedTurnEventWindows(r,R,h);}catch(u){let d=w(u),g={...x,...m,memoryEventReconciliation:{status:"degraded",stage:"event_reconciliation",reason:d,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw W({projectRoot:t,sessionId:r,executionId:b,stage:"event_reconciliation",reason:d,metadata:g}),new P("event_reconciliation",d)}let N;try{N=await Re({projectRoot:t,sessionId:r,trigger:"session_end",memory:v,details:{eventReconciliation:E},strictPersistence:!0});}catch(u){let d=w(u),g={...x,...m,memoryEventReconciliation:{status:"completed",...E,checkpointPending:null},memoryCheckpointDegradation:d};throw W({projectRoot:t,sessionId:r,executionId:b,stage:"checkpoint",reason:d,metadata:g}),new P("checkpoint",d)}let de={memoryLineageReconciliation:T,memoryBenefitAttribution:M,memoryEventReconciliation:{status:"completed",...E,checkpointPending:N.pendingEvents},memoryDistillCheckpoint:N};try{let u=openGlobalDevFlowDatabase();try{let d=`session-finalize:${r}:events`,g=Math.max(Number(N.pendingEvents??0),Number(E.remainingUndecided??0)),l=u.getSessionObligation(t,r,d);g>0?u.upsertSessionObligation({obligationId:d,projectRoot:t,sessionId:r,executionId:b,kind:"session_finalize",state:"open",payload:{pendingEvents:g,reconciliation:E,checkpointId:N.id},reason:"active_unprocessed_session_events",createdAt:l?.createdAt??h,updatedAt:h}):l?.state==="open"&&u.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:d,state:"satisfied",reason:"session_events_reconciled",resolvedAt:h});}finally{u.close();}}catch(u){emitSemanticControlLog({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:b},level:"warn",timestamp:Date.now(),data:{stage:"obligation_persistence",reason:w(u)}});}try{await v.closeSession(r),_&&(_.close(),_=void 0);}catch(u){let d=w(u),g={...x,...m,...de,memorySessionCloseDegradation:d};throw W({projectRoot:t,sessionId:r,executionId:b,stage:"memory_close",reason:d,metadata:g}),new P("memory_close",d)}let F={...x,...m,...de},K=[];try{let u=openGlobalDevFlowDatabase();try{let d=new Map(u.listLatestTaskIntentArtifacts(t,r).map(g=>[g.turnId,g]));for(let g of R){let l=d.get(g.turnId);if(!l)continue;let C=[u.getWorkByIdempotencyKey(`memory-turn:capture_prompt:${g.turnId}`),u.getWorkByIdempotencyKey(`memory-turn:commit_explicit:${g.turnId}`)].filter(Boolean).some(D=>D.state==="pending"||D.state==="leased"||D.state==="failed"),A=We({artifact:l,memoryStatus:g.status,memoryReceiptId:g.receiptId,retryOwned:C,reason:g.status==="pending"?"session_end_memory_pending":"session_end_reconciled"});K.push({turnId:g.turnId,state:A.toState,receiptId:A.receiptId});}}finally{u.close();}}catch(u){K.push({state:"terminal_integrity_failure",reason:w(u)});}F.terminalOutcomes=K,y=!0;let k;try{k=openGlobalDevFlowDatabase();let u=b;if(u)try{k.reconcileSkillExecution(u,"completed",h,F);let l=k.getSkillExecution(u);await J("/api/telemetry/skill-execution/complete",{executionId:u,finishedAt:h,status:"completed",summary:{totalToolCalls:l?.totalToolCalls??0,mcpToolCalls:l?.mcpToolCalls??0,directToolCalls:l?.directToolCalls??0,subagentCount:l?.subagentCount??0,totalDuration:l?.totalDuration??0,mcpComplianceRate:l?.mcpComplianceRate??0,missedTools:l?.missedMcpTools??[],actualFailureCount:l?.failedToolCalls??0,fallbackCount:l?.fallbackCount??0,fallbackReasons:l?.fallbackReasons??[]},metadata:F},{fallbackReason:"skill_execution_already_reconciled_locally"});}catch{}let d=k.reconcileRunningSkillExecutionsForSession(r,h,{closureReason:"session_finalize",...F});for(let l of d)await J("/api/telemetry/skill-execution/complete",{executionId:l.executionId,finishedAt:l.finishedAt,status:l.status,summary:{totalToolCalls:l.totalToolCalls??0,mcpToolCalls:l.mcpToolCalls??0,directToolCalls:l.directToolCalls??0,subagentCount:l.subagentCount??0,totalDuration:l.totalDuration??0,mcpComplianceRate:l.mcpComplianceRate??0,missedTools:l.missedMcpTools??[],actualFailureCount:l.failedToolCalls??0,fallbackCount:l.fallbackCount??0,fallbackReasons:l.fallbackReasons??[]},metadata:F},{fallbackReason:"skill_execution_already_reconciled_locally"});let g=k.getLatestSkillExecutionForSession(r);if(g&&!d.some(l=>l.executionId===g.executionId)&&k.mergeSkillExecutionMetadata(g.executionId,F),e){k.deleteHookReceipt(t);let l=q(t),H=createHash("sha256").update(t).digest("hex").slice(0,12);for(let C of [`session-id-${H}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join(l,C),{force:!0});}k.deleteContextReceipt(t,r);}catch(u){emitSemanticControlLog({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:b},level:"warn",timestamp:Date.now(),data:{stage:"lifecycle_telemetry",reason:w(u),fallback:"fail_open"}});}finally{k?.close();}try{await p.endSession(r),await p.flushAndAggregate();}catch(u){emitSemanticControlLog({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:b},level:"warn",timestamp:Date.now(),data:{stage:"telemetry_flush",reason:w(u),fallback:"local_state_authoritative"}});}}finally{if(_)try{_.close();}catch{}f&&p.close(),y&&s.removeSession(r),emitSemanticControlLog({event:y?"hook.session_end.completed":"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:i?.executionId??a?.executionId},level:y?"info":"warn",timestamp:Date.now(),data:{stage:"finalize",criticalStagesCompleted:y,transcriptStatus:c.status}});}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.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()=>{let e=an(t.trim()||process.argv[2]||"");e&&n(JSON.stringify(e)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}export{sn as buildMemoryTurnOutcomeMetadata,an as enqueueSessionEndFinalization,zi as handleSessionEnd};