@devflow-tools/cli 0.16.28 → 0.16.30

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 S(n,t,e){try{let r=openGlobalDevFlowDatabase();try{r.insertEvent({kind:n,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{r.close();}}catch{}}var Ve=getLocalApiKey(),M=join(homedir(),".devflow","errors");async function X(n,t,e={}){let r=e.endpoint??resolveRuntimeEndpoint().url,i=e.timeout??1500,o=e.durableMirror??true,s=e.maxRetries??(o?0:2),a=e.circuitBreaker??true,l=acquireRuntimeHttpCircuit(r,n);if(a&&!l.allowed)return {delivered:false,suppressed:true,fallbackReason:l.state.fallbackReason};let u;for(let d=0;d<=s;d+=1)try{return await Ke(r,n,t,i),a&&registerRuntimeHttpSuccess(r,n).transitioned&&S("http_circuit_transition",{endpoint:r,path:new URL(n,r).pathname,previous:l.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(p){u=p instanceof Error?p:new Error(String(p)),d<s&&await Ye(Math.min(100*2**d,1e3));}if(!u)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return K(n,u),{delivered:false,suppressed:false,fallbackReason:u.message};let c=registerRuntimeHttpFailure(r,n,e.fallbackReason??(o?"local_durable_mirror":"http_delivery_failed"));return c.transitioned&&(K(n,u),S("http_circuit_transition",{endpoint:r,path:new URL(n,r).pathname,previous:l.state.status,status:"open",failures:c.state.failures,openUntil:c.state.openUntil,fallbackReason:c.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:c.state.fallbackReason}}function Ke(n,t,e,r){return new Promise((i,o)=>{let s=JSON.stringify(e),a=new URL(t,n),l=false,u=d=>{l||(l=true,d?o(d):i());},c=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:r},d=>{d.on("error",u),d.on("end",()=>{let p=d.statusCode??0;u(p>=200&&p<300?void 0:new Error(`HTTP ${p}`));}),d.resume();});c.on("error",u),c.on("timeout",()=>c.destroy(new Error(`HTTP mirror timed out after ${r}ms`))),c.write(s),c.end();})}function K(n,t){try{existsSync$1(M)||mkdirSync$1(M,{recursive:!0}),appendFileSync(join(M,"http-errors.log"),`${new Date().toISOString()} | ${n} | ${t.message}
2
- `);}catch{}}function Ye(n){return new Promise(t=>setTimeout(t,n))}var ne=1e4,tt=3e4,O=500,I=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,r,i,o=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:r,startedAt:i,projectRoot:o,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",r=Date.now(),i){let o={executionId:t,status:e,finishedAt:r,metadata:i},s=this.commitOrCache("execution_complete",o);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",o),s}async sendSessionStart(t,e,r){let i={id:t,projectRoot:e,startedAt:r,label:e.split("/").pop()??"unknown"},o=this.commitOrCache("session_start",i);return o&&this.postHttp("/api/telemetry/sessions",i),o}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let r={sessionId:t,finishedAt:e},i=this.commitOrCache("session_end",r);return i&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),i}async flushCache(){try{let r=this.getDatabase(),i=r.listTelemetryFailures({unresolvedOnly:!0,limit:O}).reverse();for(let o of i)try{this.applyOperation(o.operation,o.payload),r.resolveTelemetryFailure(o.id);}catch{}r.trimTelemetryFailures(O);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(r=>!!r))].filter(r=>existsSync(r)).flatMap(r=>readdirSync(r).filter(i=>i.endsWith(".json")).map(i=>{let o=join$1(r,i);try{return {cacheFile:o,envelope:nt(JSON.parse(readFileSync(o,"utf8")),i)}}catch{return null}})).filter(r=>r!==null).sort((r,i)=>r.envelope.timestamp-i.envelope.timestamp||re(r.envelope.operation)-re(i.envelope.operation));for(let{cacheFile:r,envelope:i}of e)try{let o=this.getDatabase();o.insertTelemetryFailure({id:i.id,operation:i.operation,payload:i.payload,error:i.failure,createdAt:i.timestamp}),this.applyOperation(i.operation,i.payload),o.resolveTelemetryFailure(i.id),unlinkSync(r);}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(r){return this.cacheOperation(t,e,r),false}}applyOperation(t,e){let r=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(r,e),r.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(r,e),r.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":r.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":r.ensureSession(e),r.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(!r.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":r.closeSession(e.sessionId,e.finishedAt),r.updateRun(ie(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let r=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!r)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:r,projectRoot:i,label:i==="unknown"?void 0:i.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,r){let i=Date.now(),o={id:`failure:${i}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:r instanceof Error?r.message:String(r),timestamp:i};try{let s=this.getDatabase();s.insertTelemetryFailure({id:o.id,operation:t,payload:e,error:o.failure,createdAt:i}),s.trimTelemetryFailures(O),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(o,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of t.slice(0,Math.max(0,t.length-O)))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 re(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function ie(n){return `hook-run:${n}`}function nt(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 r=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!r)throw new Error("Unknown legacy telemetry cache operation");let i=e.payload??{},o=Number(i.timestamp??i.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:r,payload:i,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:o}}function j(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function g(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(j(n))}var ct=2,lt=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 oe(n=ut()){let t=[join$1(n,"dist","command-registry.json"),join$1(n,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let r=JSON.parse(readFileSync(e,"utf8"));if(r.version!==ct&&r.version!==lt||!dt(r.commands)){console.error(`[devflow] command registry contract mismatch: ${e}`);continue}return r.commands}catch(r){console.error(`[devflow] command registry load failed: ${r.message}`);}return null}function dt(n){return !n||typeof n!="object"||Array.isArray(n)?false:Object.values(n).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return F(e.mcpTools)&&F(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||F(e.runtimePackages))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function F(n){return Array.isArray(n)&&n.every(t=>typeof t=="string"&&t.length>0)}function se(n){let t=oe();return t?t[n]?.mcpTools??[]:[]}function _(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let t=n,e={};for(let r of ["lastMcpCall","bypassCount"])if(r in t){let i=t[r];if(i==null)continue;e[r]=typeof i=="number"&&Number.isFinite(i)&&i>=0?i:0;}return e}function gt(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function ft(n){try{return existsSync(n)?_(JSON.parse(readFileSync(n,"utf-8"))):{}}catch{return {}}}function le(n,t){let e=t instanceof Error?t.message:String(t);console.error(`[devflow] Receipt ${n} skipped: ${e}`);}function ae(n){let t=g(n);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join$1(t,e))&&unlinkSync(join$1(t,e));}catch{}}function ue(n,t){if(n.getHookReceipt(t)){ae(t);return}let e=join$1(g(t),"receipt.json");if(!existsSync(e))return;let r=ft(e);n.updateHookReceipt(t,()=>r),ae(t);}function de(n,t,e){let r;try{r=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),ue(r,n);let i={},o=r.updateHookReceipt(n,a=>(i=_(a),_(t(i)))),s=_(o);return {receipt:s,applied:!0,changed:!gt(i,s)}}catch(i){return le(e,i),{receipt:{},applied:false,changed:false}}finally{try{r?.close();}catch{}}}function pe(n){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),ue(t,n),_(t.getHookReceipt(n))}catch(e){return le("update",e),{}}finally{try{t?.close();}catch{}}}function ht(n,t){return de(n,()=>t,"write").applied}function yt(n,t){return de(n,t,"update")}var ce={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"};function vt(n){switch(n){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var x=class{constructor(t,e,r){this.projectRoot=t;this.sessionId=e;this.executionId=r;}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"}evaluate(t,e){let r=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(r==="context_gathering"&&ce[t])return {permissionDecision:"deny",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(r==="context_ready")return {permissionDecision:"allow"};let i=ce[t];if(!i)return {permissionDecision:"allow"};let o=yt(this.projectRoot,l=>({...l,bypassCount:(l.bypassCount??0)+1}));if(!o.applied)return {permissionDecision:"allow"};let s=o.receipt.bypassCount??0,a=vt(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});}};var Ot=10*1024*1024,It=5;function xt(n){return createHash$1("sha256").update(n).digest("hex").slice(0,16)}function fe(n){return join(homedir(),".devflow","logs","hook-debug",`${xt(n)}.jsonl`)}function he(n,t,e={}){let r=e.maxBytes??Ot,i=e.maxFiles??It;mkdirSync$1(dirname(n),{recursive:true,mode:448});let o=Buffer.byteLength(t),s=existsSync$1(n)?statSync(n).size:0;s>0&&s+o>r&&Ct(n,i),appendFileSync(n,t,{mode:384}),chmodSync(n,384);}function Ct(n,t){if(t<=1){rmSync$1(n,{force:true});return}rmSync$1(`${n}.${t-1}`,{force:true});for(let e=t-2;e>=1;e-=1){let r=`${n}.${e}`;existsSync$1(r)&&renameSync$1(r,`${n}.${e+1}`);}existsSync$1(n)&&renameSync$1(n,`${n}.1`);}var H="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 Ee(n){return Buffer.from(n,"utf8").toString("base64url")}function jt(n,t,e){let r=t?.trim();if(r){let i=/^[a-zA-Z0-9:._-]{1,192}$/.test(r)?r:`tool-${createHash("sha256").update(r.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${i}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function Oe(n){return `${n}:legacy-journal`}var A=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 r=this.get(e);if(r)return r.lastActivityAt=Date.now(),this.persist(r),r;let i=Date.now(),o={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:i,lastActivityAt:i};return this.sessions.set(e,o),this.persist(o),o}startExecution(t,e,r){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(r)],i.lastActivityAt=Date.now(),this.persist(i),i}get(t){let e=t.trim();if(!e)return null;let r=this.sessions.get(e);if(r)return this.replayEvidenceJournal(r),r;let i=this.snapshotPath(e);if(!existsSync(i))return null;try{let o=JSON.parse(readFileSync(i,"utf8"));return o.sessionId!==e||o.projectRoot!==this.projectRoot?null:(o.requiredMcpTools=Array.isArray(o.requiredMcpTools)?o.requiredMcpTools:[],o.evidenceObligations=Re(o.evidenceObligations),o.evidenceDegradations=De(o.evidenceDegradations),o.evidenceOutcomes=ke(o.evidenceOutcomes),this.replayEvidenceJournal(o),this.sessions.set(e,o),o)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let r=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),r}addEvidenceObligation(t,e,r=Date.now(),i){let o=this.registerSession(t),a=(i?void 0:o.evidenceObligations.find(u=>u.contractId===e.id))?.obligationId??jt(e.id,i,r);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:r,contract:e},`add\0${a}`),this.replayEvidenceJournal(o);let l=o.evidenceObligations.find(u=>u.obligationId===a);return l?(o.lastActivityAt=Date.now(),this.persist(o),structuredClone(l)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,r,i,o=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(c=>c.obligationId===e);if(!s||!a)return null;let l=/^[a-f0-9]{64}$/.test(i)?i:"";if(!l)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:o,fingerprint:l,violations:r.slice(0,16).map(c=>c.slice(0,240))},`correction\0${e}\0${l}`),this.replayEvidenceJournal(s),s.lastActivityAt=o,this.persist(s);let u=s.evidenceObligations.find(c=>c.obligationId===e);return u?structuredClone(u):null}resolveEvidenceObligation(t,e){let r=this.get(t);if(!r)return false;let i=r.evidenceObligations.find(s=>s.obligationId===e);if(!i)return false;let o=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:i.contractId,at:o},`resolve\0${e}`),this.replayEvidenceJournal(r),r.lastActivityAt=o,this.persist(r),true}degradeEvidenceObligation(t,e,r,i=Date.now()){let o=this.get(t),s=o?.evidenceObligations.find(l=>l.obligationId===e);if(!o||!s)return false;let a=r.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(o),o.lastActivityAt=i,this.persist(o),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${Ee(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Ee(t))}appendEvidenceEvent(t,e,r){let i=this.evidenceJournalDir(t);mkdirSync(i,{recursive:true,mode:448});let o=createHash("sha256").update(r).digest("hex"),s=join$1(i,`${e.kind}-${o}.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(l){if(l.code!=="EEXIST")throw l}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Re(t.evidenceObligations),t.evidenceDegradations=De(t.evidenceDegradations),t.evidenceOutcomes=ke(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let r;try{r=readdirSync(e).filter(o=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(o)).slice(0,4096);}catch{return}let i=r.flatMap(o=>{try{let s=readFileSync(join$1(e,o),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=Ft(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((o,s)=>o.at-s.at||we(o.kind)-we(s.kind));for(let o of i)this.applyEvidenceEvent(t,o);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let r=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(r)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||r||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 o=i?.attempt??0;t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),!r&&(e.kind==="degrade"&&t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:o}),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:o,...e.kind==="degrade"?{reason:e.reason}:{}}));}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),r=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(r,JSON.stringify(t),{mode:384}),renameSync(r,e);}};function Re(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)||!Ie(e.contract))return [];let r=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Oe(e.contractId),i=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,o=e.correctionFingerprint??i;return o!==void 0&&!/^[a-f0-9]{64}$/.test(o)?[]:[{...e,obligationId:r,correctionFingerprint:o}]}).slice(-8):[]}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"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function ke(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 Ft(n){if(!n||typeof n!="object")return null;let t=n;if(!["add","correction","resolve","degrade"].includes(t.kind??"")||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let e=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:Oe(t.contractId);if(t.kind==="add")return Ie(t.contract)?{...t,obligationId:e}:null;if(t.kind==="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(i=>typeof i=="string"&&i.length<=240)?{...t,obligationId:e,fingerprint:r}:null}return t.kind==="resolve"?{...t,obligationId:e}:typeof t.reason=="string"&&t.reason.length<=240?{...t,obligationId:e}:null}function we(n){return n==="add"?0:n==="correction"?1:2}function Ie(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,r=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(r)&&r.length<=16&&r.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 xe(n){let t=n.trim().replace(/^\//,"");if(!t.startsWith("devflow:"))return null;let e=t.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(e)?`devflow:${e.toLowerCase()}`:null}function Ce(n,t){return t?`evt_tool_${createHash("sha256").update(`${n}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var Lt=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 Ne(n){if(!Lt.has(n.toolName))return null;let t=Ut(n.toolInput);if(!t)return null;let e=Ht(t,n.projectRoot),r=resolve(n.projectRoot,".claude");if(Te(e,r)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return Ae;let i=resolve(n.home??homedir(),".claude","projects");return Te(e,i)&&relative(i,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?Ae:null}function Ut(n){for(let t of ["file_path","notebook_path","path"]){let e=n[t];if(typeof e=="string"&&e.trim())return e.trim()}return null}function Ht(n,t){return resolve(isAbsolute(n)?n:resolve(t,n))}function Te(n,t){let e=relative(t,n);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function E(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function Pe(n){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:n}}}function Bt(n){let t=g(n);return existsSync(t)||mkdirSync(t,{recursive:true}),t}function zt(n,t,e,r,i,o){let s=join$1(Bt(n),"event-map.json"),a=[];try{existsSync(s)&&(a=JSON.parse(readFileSync(s,"utf-8")));}catch{}a.push({sessionId:t,toolName:e,toolUseId:r,eventId:i,timestamp:o}),writeFileSync(s,JSON.stringify(a));}function Vt(n){switch(n){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 Kt(n){let t=ye();try{if(!n||n.trim()==="")return E();let e=JSON.parse(n),r=Date.now(),i=j(),o=new I;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 Pe(H);let a=new A(i),l=a.get(s)!==null;if(a.registerSession(s),l||await o.sendSessionStart(s,i,Date.now()),e.tool_name==="Skill"){let w=e.tool_input?.skill,f=w?xe(w):null;if(f){let Ue=a.get(s)?.executionId,b=a.startExecution(s,f,se(f));b.executionId&&b.executionId!==Ue&&await o.sendExecutionStart(b.executionId,s,f,b.lastActivityAt,i,b.requiredMcpTools);}}let u=a.get(s);e.tool_name.startsWith("mcp__devflow__")&&(e.tool_input._devflow_session_id=s,e.tool_input._devflow_execution_id=u?.executionId??s,e.tool_use_id&&(e.tool_input._devflow_tool_use_id=e.tool_use_id));let c=e.tool_name.startsWith("mcp__"),d=c?e.tool_name.replace(/^mcp__[^_]+__/,""):void 0,p=new x(i,s,u?.executionId),W=p.getPhase(),m,R=Ne({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:i}),D=R?{permissionDecision:"deny",reason:R}:p.evaluate(e.tool_name,c);D.permissionDecision==="deny"?m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:D.reason??"MCP context required"}}:D.additionalContext?m=Pe(D.additionalContext):m=E(),e.tool_name.startsWith("mcp__devflow__")&&(m.hookSpecificOutput.updatedInput=e.tool_input),t&&m.hookSpecificOutput.permissionDecision==="allow"&&(m.hookSpecificOutput.additionalContext=H);let Le=u?.executionId??s,v={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:c?"mcp":e.tool_name==="Agent"?"subagent":"direct",isMcpTool:c,mcpToolName:d,mcpEnforced:c&&W==="context_gathering",mcpFallback:!c&&W==="context_gathering",kind:Vt(e.tool_name),input:e.tool_input,duration:0,blocked:m.hookSpecificOutput.permissionDecision==="deny",blockReason:m.hookSpecificOutput.permissionDecision==="deny"?R?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0},k=await o.sendEvent(v);k&&!v.blocked&&zt(i,s,e.tool_name,e.tool_use_id,k,v.timestamp),k&&v.blocked&&await o.completeEvent({eventId:k,sessionId:s,error:R?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-v.timestamp,completedAt:Date.now()});try{let w=pe(i),f={ts:r,tool:e.tool_name,sessionId:s,skill:u?.skillName??"(none)",requiredTools:u?.requiredMcpTools??[],isMcp:c,enforce:u?.executionId!==void 0,stateless:u?.executionId===void 0&&!c&&e.tool_name!=="Skill",bypassCount:w.bypassCount??0,decision:m.hookSpecificOutput.permissionDecision,env_CLAUDE_PLUGIN_ROOT:process.env.CLAUDE_PLUGIN_ROOT??"(unset)",cwd:process.cwd()};he(fe(i),`${JSON.stringify(f)}
3
- `);}catch{}return m}catch{return E()}}if(process.argv[1]?.endsWith("pre-tool-use")||process.argv[1]?.endsWith("pre-tool-use.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=await Kt(t);n(JSON.stringify(e));}),process.stdin.on("error",()=>{n(JSON.stringify(E())),process.exit(0);}),setTimeout(()=>{n(JSON.stringify(E())),process.exit(0);},4e3).unref();}export{Kt 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 {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,4 +1,4 @@
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 N(o){return o??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function _(o){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(N(o))}function G(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 Ue=getLocalApiKey(),V=join(homedir(),".devflow","errors");async function $(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,l=acquireRuntimeHttpCircuit(n,o);if(a&&!l.allowed)return {delivered:false,suppressed:true,fallbackReason:l.state.fallbackReason};let u;for(let m=0;m<=s;m+=1)try{return await Be(n,o,t,i),a&&registerRuntimeHttpSuccess(n,o).transitioned&&G("http_circuit_transition",{endpoint:n,path:new URL(o,n).pathname,previous:l.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(h){u=h instanceof Error?h:new Error(String(h)),m<s&&await We(Math.min(100*2**m,1e3));}if(!u)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return ae(o,u),{delivered:false,suppressed:false,fallbackReason:u.message};let g=registerRuntimeHttpFailure(n,o,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return g.transitioned&&(ae(o,u),G("http_circuit_transition",{endpoint:n,path:new URL(o,n).pathname,previous:l.state.status,status:"open",failures:g.state.failures,openUntil:g.state.openUntil,fallbackReason:g.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:g.state.fallbackReason}}function Be(o,t,e,n){return new Promise((i,r)=>{let s=JSON.stringify(e),a=new URL(t,o),l=false,u=m=>{l||(l=true,m?r(m):i());},g=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":Ue,"Content-Length":Buffer.byteLength(s)},timeout:n},m=>{m.on("error",u),m.on("end",()=>{let h=m.statusCode??0;u(h>=200&&h<300?void 0:new Error(`HTTP ${h}`));}),m.resume();});g.on("error",u),g.on("timeout",()=>g.destroy(new Error(`HTTP mirror timed out after ${n}ms`))),g.write(s),g.end();})}function ae(o,t){try{existsSync(V)||mkdirSync(V,{recursive:!0}),appendFileSync(join(V,"http-errors.log"),`${new Date().toISOString()} | ${o} | ${t.message}
2
- `);}catch{}}function We(o){return new Promise(t=>setTimeout(t,o))}var ge=1e4,Ye=3e4,q=500,J=class{constructor(t){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=t?.apiUrl,this.cacheDir=t?.cacheDir??join$1(process.env.DEVFLOW_STATE_DIR??join$1(homedir$1(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join$1(homedir$1(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}async sendEvent(t){let e={...t,input:this.truncateInput(t.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),t.eventId):null}async sendExecutionStart(t,e,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:q}).reverse();for(let r of i)try{this.applyOperation(r.operation,r.payload),n.resolveTelemetryFailure(r.id);}catch{}n.trimTelemetryFailures(q);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync$1(n)).flatMap(n=>readdirSync(n).filter(i=>i.endsWith(".json")).map(i=>{let r=join$1(n,i);try{return {cacheFile:r,envelope:Ke(JSON.parse(readFileSync(r,"utf8")),i)}}catch{return null}})).filter(n=>n!==null).sort((n,i)=>n.envelope.timestamp-i.envelope.timestamp||me(n.envelope.operation)-me(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$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:fe(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(fe(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(q),this.scheduleRetry();return}catch{}try{existsSync$1(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${i}_${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-q)))unlinkSync$1(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},Ye).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){$(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ge?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ge)}...`}}};function me(o){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(o)}function fe(o){return `hook-run:${o}`}function Ke(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}}async function he(o){let t=!o.memory,e=o.memory??new MemoryGate(o.projectRoot),n=0,i=0;try{await e.forceWarmUp(),o.trigger==="session_end"&&(n=await e.releasePendingDistillLeases(o.sessionId)),i=e.getPendingEventCount(o.sessionId,o.trigger!=="session_end");}finally{t&&e.close();}let r={pendingEvents:i,releasedLeases:n,trigger:o.trigger,sessionId:o.sessionId,details:o.details};try{let s=openGlobalDevFlowDatabase();try{let a=Date.now(),l=o.trigger==="session_end"&&o.sessionId?`distill:session_end:${createHash("sha256").update(`${o.projectRoot}\0${o.sessionId}`).digest("hex").slice(0,24)}`:`distill:${a}:${Math.random().toString(36).slice(2,10)}`;s.recordMemoryDistillCheckpoint({id:l,projectRoot:o.projectRoot,sessionId:o.sessionId,trigger:o.trigger,pendingEvents:i,releasedLeases:n,details:o.details,createdAt:a}),s.insertEvent({kind:"memory_distill_requested",timestamp:a,success:!0,metadata:{...r,projectRoot:o.projectRoot}});}finally{s.close();}}catch(s){throw s}return r}function Se(o){return Buffer.from(o,"utf8").toString("base64url")}function ot(o,t,e){let n=t?.trim();if(n){let i=/^[a-zA-Z0-9:._-]{1,192}$/.test(n)?n:`tool-${createHash$1("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 P=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(_(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let 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$1(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=we(r.evidenceObligations),r.evidenceDegradations=Ee(r.evidenceDegradations),r.evidenceOutcomes=_e(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(u=>u.contractId===e.id))?.obligationId??ot(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 l=r.evidenceObligations.find(u=>u.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,i,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(g=>g.obligationId===e);if(!s||!a)return null;let l=/^[a-f0-9]{64}$/.test(i)?i:"";if(!l)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:l,violations:n.slice(0,16).map(g=>g.slice(0,240))},`correction\0${e}\0${l}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let u=s.evidenceObligations.find(g=>g.obligationId===e);return u?structuredClone(u):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(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: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$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,`${Se(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Se(t))}appendEvidenceEvent(t,e,n){let i=this.evidenceJournalDir(t);mkdirSync$1(i,{recursive:true,mode:448});let r=createHash$1("sha256").update(n).digest("hex"),s=join$1(i,`${e.kind}-${r}.json`);if(existsSync$1(s))return;let a=join$1(i,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(l){if(l.code!=="EEXIST")throw l}finally{rmSync$1(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=we(t.evidenceObligations),t.evidenceDegradations=Ee(t.evidenceDegradations),t.evidenceOutcomes=_e(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 i=n.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=st(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$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 we(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)||!Ae(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 Ee(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 _e(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 st(o){if(!o||typeof o!="object")return null;let t=o;if(!["add","correction","resolve","degrade"].includes(t.kind??"")||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let e=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:ke(t.contractId);if(t.kind==="add")return Ae(t.contract)?{...t,obligationId:e}:null;if(t.kind==="correction"){let n=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof n=="string"&&/^[a-f0-9]{64}$/.test(n)&&Array.isArray(t.violations)&&t.violations.every(i=>typeof i=="string"&&i.length<=240)?{...t,obligationId:e,fingerprint:n}:null}return t.kind==="resolve"?{...t,obligationId:e}:typeof t.reason=="string"&&t.reason.length<=240?{...t,obligationId:e}:null}function Ie(o){return o==="add"?0:o==="correction"?1:2}function Ae(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 De(o,t){let e=ut(o);mkdirSync(e,{recursive:true,mode:448});let n=join(e,`${t.receiptId}.json`);if(existsSync(n))return t.receiptId;let i=`${n}.${process.pid}.tmp`;writeFileSync(i,JSON.stringify(t),{mode:384});try{renameSync(i,n);}catch(r){try{unlinkSync(i);}catch{}if(!existsSync(n))throw r}return t.receiptId}function ut(o){return join(_(o),"session-finalize-pending")}var yt=512*1024,bt=500;var vt=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function St(o){let t=false,e=[],n=[];for(let i of o){if(/^\s*```/.test(i)){t=!t,e.push(""),n.push(i.replace(/^\s*```+[^\s`]*/,"").replace(/```+\s*$/,"").trim());continue}e.push(t?"":i.replace(/`[^`]*`/g,"").trim()),n.push(i.replace(/`([^`]*)`/g,(r,s)=>wt(s)?"":s).trim());}return {headingLines:e,claimLines:n}}function wt(o){let t=o.trim().slice(0,256);return !t||/\s/.test(t)||o.trim().length>256?false:/^[A-Za-z_$][\w$.-]*$/.test(t)||/^(['"])[^'"`]*\1$/.test(t)}function Et(o,t){if(!o||o.length>4096)return {degradationReason:"transcript_path_missing"};let e;try{let n=lstatSync(o);if(!n.isFile()||n.isSymbolicLink())return {degradationReason:"transcript_path_unsafe"};e=openSync(o,constants.O_RDONLY|(constants.O_NOFOLLOW??0));let i=fstatSync(e);if(!i.isFile()||i.dev!==n.dev||i.ino!==n.ino)return {degradationReason:"transcript_path_changed"};let r=Math.min(i.size,yt),s=Buffer.alloc(r),a=0;for(;a<r;){let y=readSync(e,s,a,r-a,i.size-r+a);if(y===0)break;a+=y;}let l=s.subarray(0,a).toString("utf8");i.size>r&&(l=l.slice(Math.max(0,l.indexOf(`
3
- `)+1)));let u=l.split(/\r?\n/).slice(-bt),g=t.length>0?Math.min(...t.map(y=>y.promptedAt)):0,m=It(u,g),b=[...m].reverse().find(y=>_t(y.text,t))??m.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 _t(o,t){let e=new Set(t.flatMap(i=>i.contract.requiredSections)),n=kt(St(o.split(/\r?\n/u)).headingLines);return [...e].every(i=>n.found.has(i))}function Te(o){return Et(o,[]).answer}function It(o,t){let e=[];for(let n=0;n<o.length;n++){let i=o[n];if(i.trim())try{let r=JSON.parse(i),s=r.message;if(!s||typeof s!="object"||s.role!=="assistant")continue;let a=s,l=Rt(r.timestamp);if(l>0&&l+5e3<t)continue;let u=s.content,g=typeof u=="string"?u:Array.isArray(u)?u.filter(m=>m&&typeof m=="object"&&m.type==="text").map(m=>m.text).filter(m=>typeof m=="string").join(`
4
- `):"";if(g.trim()){let m=g.trim(),h=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(i).digest("hex")}`,b=createHash("sha256").update(m).digest("hex"),y=createHash("sha256").update(`${h}\0${b}`).digest("hex");e.push({text:m,timestamp:l,fingerprint:y});}}catch{continue}}return e}function Rt(o){if(typeof o=="number"&&Number.isFinite(o))return o;if(typeof o!="string")return 0;let t=Date.parse(o);return Number.isFinite(t)?t:0}function kt(o){let t=new Set,e=new Map,n;for(let i=0;i<o.length;i++){let r=o[i].trim().replace(/^#{1,6}\s*/,"").replace(/^\*\*(.*)\*\*$/,"$1").replace(/^(?:[一二三123][、..]\s*)/,"").replace(/[::]\s*$/,"").trim(),s=vt.find(a=>r===a);s&&(n=s,t.add(s)),e.set(i,n);}return {found:t,byLine:e}}function Dt(o){let t={committed:0,skipped:0,pending:0},e=[];for(let n of o)t[n.status]+=1,n.receiptId&&e.push(n.receiptId);return {memoryReceiptIds:[...new Set(e)],missingMemoryDecisionCount:t.pending,memoryTurnOutcomes:t}}function k(o){return (o instanceof Error?o.message:String(o)).trim().slice(0,240)||"memory_lifecycle_unavailable"}var S=class extends Error{constructor(t,e){super(`session_finalize_${t}:${e}`),this.name="SessionFinalizationRetryableError",this.category=`session_finalize_${t}`;}};function M(o){let t;try{t=openGlobalDevFlowDatabase();let e=(o.executionId?t.getSkillExecution(o.executionId):null)??t.getLatestSkillExecutionForSession(o.sessionId),n={stage:o.stage,reason:o.reason,degradedAt:Date.now()};e&&t.mergeSkillExecutionMetadata(e.executionId,{...o.metadata,sessionFinalizationDegradations:[n]}),t.insertEvent({kind:"session_finalize_degraded",timestamp:n.degradedAt,success:!1,metadata:{projectRoot:o.projectRoot,sessionId:o.sessionId,executionId:e?.executionId,...n}});}catch{}finally{t?.close();}}function Ct(o,t=N(),e=true,n,i=true){let r;try{r=JSON.parse(o);}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)}`,l={inputJson:o,sessionId:s,cleanupSharedState:e,executionId:n},u;try{u=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let g=u.requestSessionClosure({receiptId:a,projectRoot:t,sessionId:s,payload:l}),m=u.getWorkByIdempotencyKey(a);return {status:g.state==="closed"||g.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:m?.state??"pending",closureState:g.state,pendingWorkCount:g.pendingWorkCount}}catch(g){if(!i)throw g;return De(t,{receiptId:a,...l}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{u?.close();}}async function Bn(o,t=N(),e=true,n){let i;try{i=JSON.parse(o);}catch{return}let r=i.session_id?.trim();if(!r)return;let s=new P(t),a=s.get(r),l={evidenceDegradations:a?.evidenceDegradations??[],evidenceContractOutcomes:a?.evidenceOutcomes??[],pendingEvidenceContractIds:a?.evidenceObligations.map(b=>b.contractId)??[]},u=n?.telemetry??new J,g=!n?.telemetry,m=false,h;try{try{await u.flushAndAggregate();}catch{}let b=Date.now(),y=n?.executionId??a?.executionId,x;try{let p=openGlobalDevFlowDatabase();try{x=p.listSessionMemoryTurnsForReconciliation(t,r);for(let c of x){let f=`memory:${c.turnId}`,d=p.getSessionObligation(t,r,f);d?d.state==="open"&&c.status!=="pending"&&p.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:f,state:"satisfied",receiptId:c.receiptId,reason:c.reason,resolvedAt:c.decidedAt}):p.upsertSessionObligation({obligationId:f,projectRoot:t,sessionId:r,turnId:c.turnId,kind:"memory_decision",state:c.status==="pending"?"open":"satisfied",payload:{eventId:c.eventId,promptHash:c.promptHash},receiptId:c.receiptId,reason:c.reason,createdAt:c.createdAt,updatedAt:c.decidedAt??c.createdAt,resolvedAt:c.decidedAt});}}finally{p.close();}}catch(p){let c=k(p),f={...l,memoryEventReconciliation:{status:"degraded",stage:"turn_load",reason:c,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw M({projectRoot:t,sessionId:r,executionId:y,stage:"turn_load",reason:c,metadata:f}),new S("turn_load",c)}let O=Dt(x),w=n?.memory??(h=new MemoryGate(t)),F={status:"completed"};try{F=typeof w.reconcileTurnObservationLineage=="function"?{status:"completed",...await w.reconcileTurnObservationLineage(x)}:{status:"unsupported_adapter",committed:0,skipped:0,quarantined:0,unlinked:0};}catch(p){let c=k(p);throw F={status:"degraded",reason:c},M({projectRoot:t,sessionId:r,executionId:y,stage:"memory_lineage",reason:c,metadata:{...O,...l,memoryLineageReconciliation:F}}),new S("memory_lineage",c)}let z={status:"unknown",selected:0,adopted:0,unknown:0,positive:0,negative:0};try{let p=Te(i.transcript_path),c=openGlobalDevFlowDatabase(),f="unknown",d="no_terminal_host_action_evidence",L,j,Q,ee=[];try{let U=c.listHostActionsForSession(t,r,y),te=U.filter(T=>T.state==="verified"),B=U.filter(T=>["failed","cancelled","degraded"].includes(T.state));B.length>0?(f="negative",d=`terminal_host_action_${B[0].state}`):te.length>0&&(f="positive",d="host_action_verified");let W=B[0]??te.at(-1);L=W?.runId,j=W?.contextReceipt,Q=W?.evidenceHash,ee=U.flatMap(T=>{let ne=T.report.toolUseIds;return Array.isArray(ne)?ne.filter(Me=>typeof Me=="string"):[]});}finally{c.close();}let Pe=await w.attributeRetrievalBenefits({sessionId:r,executionId:y,finalAnswer:p,outcome:f,outcomeReason:d,workflowRunId:L,contextReceipt:j,toolEvidence:ee,verificationReceipt:Q});z={status:p?"evaluated":"unknown",...Pe};}catch(p){z={...z,status:"degraded",reason:k(p)};}let E;try{E=await w.reconcileDecidedTurnEventWindows(r,x,b);}catch(p){let c=k(p),f={...O,...l,memoryEventReconciliation:{status:"degraded",stage:"event_reconciliation",reason:c,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw M({projectRoot:t,sessionId:r,executionId:y,stage:"event_reconciliation",reason:c,metadata:f}),new S("event_reconciliation",c)}let D;try{D=await he({projectRoot:t,sessionId:r,trigger:"session_end",memory:w,details:{eventReconciliation:E},strictPersistence:!0});}catch(p){let c=k(p),f={...O,...l,memoryEventReconciliation:{status:"completed",...E,checkpointPending:null},memoryCheckpointDegradation:c};throw M({projectRoot:t,sessionId:r,executionId:y,stage:"checkpoint",reason:c,metadata:f}),new S("checkpoint",c)}let K={memoryLineageReconciliation:F,memoryBenefitAttribution:z,memoryEventReconciliation:{status:"completed",...E,checkpointPending:D.pendingEvents},memoryDistillCheckpoint:D};try{let p=openGlobalDevFlowDatabase();try{let c=`session-finalize:${r}:events`,f=Math.max(Number(D.pendingEvents??0),Number(E.remainingUndecided??0)),d=p.getSessionObligation(t,r,c);f>0?p.upsertSessionObligation({obligationId:c,projectRoot:t,sessionId:r,executionId:y,kind:"session_finalize",state:"open",payload:{pendingEvents:f,reconciliation:E,checkpointId:D.id},reason:"active_unprocessed_session_events",createdAt:d?.createdAt??b,updatedAt:b}):d?.state==="open"&&p.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:c,state:"satisfied",reason:"session_events_reconciled",resolvedAt:b});}finally{p.close();}}catch(p){console.error("[devflow] Session finalization obligation persistence failed:",p.message);}try{await w.closeSession(r),h&&(h.close(),h=void 0);}catch(p){let c=k(p),f={...O,...l,...K,memorySessionCloseDegradation:c};throw M({projectRoot:t,sessionId:r,executionId:y,stage:"memory_close",reason:c,metadata:f}),new S("memory_close",c)}let C={...O,...l,...K};m=!0;let v;try{v=openGlobalDevFlowDatabase();let p=y;if(p)try{v.reconcileSkillExecution(p,"completed",b,C);let d=v.getSkillExecution(p);await $("/api/telemetry/skill-execution/complete",{executionId:p,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:C},{fallbackReason:"skill_execution_already_reconciled_locally"});}catch{}let c=v.reconcileRunningSkillExecutionsForSession(r,b,{closureReason:"session_finalize",...C});for(let d of c)await $("/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:C},{fallbackReason:"skill_execution_already_reconciled_locally"});let f=v.getLatestSkillExecutionForSession(r);if(f&&!c.some(d=>d.executionId===f.executionId)&&v.mergeSkillExecutionMetadata(f.executionId,C),e){v.deleteHookReceipt(t);let d=_(t),L=createHash("sha256").update(t).digest("hex").slice(0,12);for(let j of [`session-id-${L}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join(d,j),{force:!0});}v.deleteContextReceipt(t,r);}catch{}finally{v?.close();}try{await u.endSession(r),await u.flushAndAggregate();}catch{}}finally{if(h)try{h.close();}catch{}g&&u.close(),m&&s.removeSession(r);}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.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=Ct(t.trim()||process.argv[2]||"");e&&o(JSON.stringify(e)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}export{Dt as buildMemoryTurnOutcomeMetadata,Ct as enqueueSessionEndFinalization,Bn as handleSessionEnd};
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 Ve=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 Ze(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 Xe(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 Ze(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":Ve,"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 Xe(i){return new Promise(t=>setTimeout(t,i))}var ye=1e4,tt=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:nt(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();},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){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 nt(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 lt(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??lt(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=dt(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 dt(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=ft(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 ft(i){return join(k(i),"session-finalize-pending")}var wt=512*1024,It=500;var _t=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function Rt(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)=>Et(s)?"":s).trim());}return {headingLines:e,claimLines:n}}function Et(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 kt(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(-It),p=t.length>0?Math.min(...t.map(h=>h.promptedAt)):0,g=xt(u,p),b=[...g].reverse().find(h=>At(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 At(i,t){let e=new Set(t.flatMap(o=>o.contract.requiredSections)),n=Ot(Rt(i.split(/\r?\n/u)).headingLines);return [...e].every(o=>n.found.has(o))}function Fe(i){return kt(i,[]).answer}function xt(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=Dt(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 Dt(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 Ot(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=_t.find(a=>r===a);s&&(n=s,t.add(s)),e.set(o,n);}return {found:t,byLine:e}}function Me(i){let t=openGlobalDevFlowDatabase();try{let e=t.listRetrievalLedgerEvents(i),n=new Map(e.filter(c=>c.stage==="selected").map(c=>[`${c.sourceType}\0${c.sourceId}`,c])),o=new Map(e.filter(c=>c.stage==="adopted").map(c=>[`${c.sourceType}\0${c.sourceId}`,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:$t(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 $t(i,t,e){return `retrieval:${createHash("sha256").update(`${i}\0${t}\0${e}`).digest("hex")}`}function zt(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 I=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 jt(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 ii(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 I("turn_load",l)}let T=zt(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 I("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(w=>w.status==="failed"),K=E.filter(w=>w.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(w=>w.command).filter(w=>typeof w=="string");}}finally{l.close();}let je=Me({projectRoot:t,sessionId:r,executionId:h,outcome:f,outcomeReason:d,verificationReceipt:M,finishedAt:b}),Le=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",...Le,retrievalLedger:je};}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 I("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 I("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 I("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=jt(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{zt as buildMemoryTurnOutcomeMetadata,jt as enqueueSessionEndFinalization,ii as handleSessionEnd};
@@ -1,17 +1,17 @@
1
- import {getLocalApiKey,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir}from'@devflow-tools/sdk';import {existsSync as existsSync$1,readFileSync as readFileSync$1,rmSync,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1}from'fs';import {join as join$1}from'path';import {randomUUID,createHash as createHash$1}from'crypto';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import'@devflow-tools/memory-engine';import'os';import {request}from'node:http';import {mkdirSync,existsSync,writeFileSync,renameSync,unlinkSync,readFileSync,openSync,constants,fstatSync,closeSync,appendFileSync,lstatSync,readSync}from'node:fs';import {join,resolve}from'node:path';import {homedir}from'node:os';import {createHash}from'node:crypto';function v(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function S(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(v(n))}function j(n){return Buffer.from(n,"utf8").toString("base64url")}function be(n,e,t){let r=e?.trim();if(r){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(r)?r:`tool-${createHash$1("sha256").update(r.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${o}`}return `${n}:legacy-${t}-${randomUUID().slice(0,8)}`}function U(n){return `${n}:legacy-journal`}var y=class{constructor(e){this.projectRoot=e;this.sessions=new Map;this.sessionsDir=join$1(S(e),"hook-sessions");}registerSession(e){let t=e.trim();if(!t)throw new Error("session_id_required");let r=this.get(t);if(r)return r.lastActivityAt=Date.now(),this.persist(r),r;let o=Date.now(),i={sessionId:t,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:o,lastActivityAt:o};return this.sessions.set(t,i),this.persist(i),i}startExecution(e,t,r){let o=this.registerSession(e);return (!o.executionId||o.skillName!==t)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=t,o.requiredMcpTools=[...new Set(r)],o.lastActivityAt=Date.now(),this.persist(o),o}get(e){let t=e.trim();if(!t)return null;let r=this.sessions.get(t);if(r)return this.replayEvidenceJournal(r),r;let o=this.snapshotPath(t);if(!existsSync$1(o))return null;try{let i=JSON.parse(readFileSync$1(o,"utf8"));return i.sessionId!==t||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],i.evidenceObligations=F(i.evidenceObligations),i.evidenceDegradations=N(i.evidenceDegradations),i.evidenceOutcomes=L(i.evidenceOutcomes),this.replayEvidenceJournal(i),this.sessions.set(t,i),i)}catch{return null}}completeExecution(e){let t=this.get(e);if(!t)return null;let r=structuredClone(t);return delete t.executionId,delete t.skillName,t.requiredMcpTools=[],t.lastActivityAt=Date.now(),this.persist(t),r}addEvidenceObligation(e,t,r=Date.now(),o){let i=this.registerSession(e),a=(o?void 0:i.evidenceObligations.find(d=>d.contractId===t.id))?.obligationId??be(t.id,o,r);this.appendEvidenceEvent(e,{kind:"add",obligationId:a,contractId:t.id,at:r,contract:t},`add\0${a}`),this.replayEvidenceJournal(i);let c=i.evidenceObligations.find(d=>d.obligationId===a);return c?(i.lastActivityAt=Date.now(),this.persist(i),structuredClone(c)):null}listEvidenceObligations(e){return (this.get(e)?.evidenceObligations??[]).map(t=>structuredClone(t))}markEvidenceCorrection(e,t,r,o,i=Date.now()){let s=this.get(e),a=s?.evidenceObligations.find(l=>l.obligationId===t);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(o)?o:"";if(!c)return null;this.appendEvidenceEvent(e,{kind:"correction",obligationId:t,contractId:a.contractId,at:i,fingerprint:c,violations:r.slice(0,16).map(l=>l.slice(0,240))},`correction\0${t}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=i,this.persist(s);let d=s.evidenceObligations.find(l=>l.obligationId===t);return d?structuredClone(d):null}resolveEvidenceObligation(e,t){let r=this.get(e);if(!r)return false;let o=r.evidenceObligations.find(s=>s.obligationId===t);if(!o)return false;let i=Date.now();return this.appendEvidenceEvent(e,{kind:"resolve",obligationId:t,contractId:o.contractId,at:i},`resolve\0${t}`),this.replayEvidenceJournal(r),r.lastActivityAt=i,this.persist(r),true}degradeEvidenceObligation(e,t,r,o=Date.now()){let i=this.get(e),s=i?.evidenceObligations.find(c=>c.obligationId===t);if(!i||!s)return false;let a=r.slice(0,240);return this.appendEvidenceEvent(e,{kind:"degrade",obligationId:t,contractId:s.contractId,at:o,reason:a},`degrade\0${t}\0${a}`),this.replayEvidenceJournal(i),i.lastActivityAt=o,this.persist(i),true}removeSession(e){let t=e.trim();t&&(this.sessions.delete(t),rmSync(this.snapshotPath(t),{force:true}),rmSync(this.evidenceJournalDir(t),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(e){return join$1(this.sessionsDir,`${j(e)}.json`)}evidenceJournalDir(e){return join$1(this.sessionsDir,"evidence-journal",j(e))}appendEvidenceEvent(e,t,r){let o=this.evidenceJournalDir(e);mkdirSync$1(o,{recursive:true,mode:448});let i=createHash$1("sha256").update(r).digest("hex"),s=join$1(o,`${t.kind}-${i}.json`);if(existsSync$1(s))return;let a=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(t),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(e){e.evidenceObligations=F(e.evidenceObligations),e.evidenceDegradations=N(e.evidenceDegradations),e.evidenceOutcomes=L(e.evidenceOutcomes);let t=this.evidenceJournalDir(e.sessionId);if(!existsSync$1(t))return;let r;try{r=readdirSync(t).filter(i=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(i)).slice(0,4096);}catch{return}let o=r.flatMap(i=>{try{let s=readFileSync$1(join$1(t,i),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=ve(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((i,s)=>i.at-s.at||z(i.kind)-z(s.kind));for(let i of o)this.applyEvidenceEvent(e,i);e.evidenceObligations=e.evidenceObligations.slice(-8),e.evidenceDegradations=e.evidenceDegradations.slice(-20),e.evidenceOutcomes=e.evidenceOutcomes.slice(-20);}applyEvidenceEvent(e,t){let r=e.evidenceOutcomes.find(s=>s.obligationId===t.obligationId);if(t.kind==="add"){if(r)return;let s=e.evidenceObligations.find(a=>a.obligationId===t.obligationId);s?(s.contract=t.contract,s.promptedAt=Math.min(s.promptedAt,t.at)):e.evidenceObligations.push({obligationId:t.obligationId,contractId:t.contractId,contract:t.contract,promptedAt:t.at,attempt:0,correctionRequested:false,violations:[]});return}let o=e.evidenceObligations.find(s=>s.obligationId===t.obligationId);if(t.kind==="correction"){if(!o||r||o.correctionFingerprint===t.fingerprint)return;o.attempt+=1,o.correctionRequested=true,o.correctionRequestedAt=t.at,o.correctionFingerprint=t.fingerprint,o.violations=t.violations;return}let i=o?.attempt??0;e.evidenceObligations=e.evidenceObligations.filter(s=>s.obligationId!==t.obligationId),!r&&(t.kind==="degrade"&&e.evidenceDegradations.push({obligationId:t.obligationId,contractId:t.contractId,reason:t.reason,degradedAt:t.at,attempt:i}),e.evidenceOutcomes.push({obligationId:t.obligationId,contractId:t.contractId,status:t.kind==="resolve"?"resolved":"degraded",completedAt:t.at,attempt:i,...t.kind==="degrade"?{reason:t.reason}:{}}));}persist(e){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let t=this.snapshotPath(e.sessionId),r=`${t}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(r,JSON.stringify(e),{mode:384}),renameSync$1(r,t);}};function F(n){return Array.isArray(n)?n.flatMap(e=>{if(!e||typeof e!="object")return [];let t=e;if(typeof t.contractId!="string"||t.contractId.length===0||t.contractId.length>128||typeof t.promptedAt!="number"||typeof t.attempt!="number"||typeof t.correctionRequested!="boolean"||!Array.isArray(t.violations)||!q(t.contract))return [];let r=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:U(t.contractId),o=typeof t.correctionTranscriptHash=="string"?t.correctionTranscriptHash:void 0,i=t.correctionFingerprint??o;return i!==void 0&&!/^[a-f0-9]{64}$/.test(i)?[]:[{...t,obligationId:r,correctionFingerprint:i}]}).slice(-8):[]}function N(n){return Array.isArray(n)?n.filter(e=>{if(!e||typeof e!="object")return false;let t=e;return typeof t.obligationId=="string"&&typeof t.contractId=="string"&&typeof t.reason=="string"&&typeof t.degradedAt=="number"&&typeof t.attempt=="number"}).slice(-20):[]}function L(n){return Array.isArray(n)?n.filter(e=>{if(!e||typeof e!="object")return false;let t=e;return typeof t.obligationId=="string"&&typeof t.contractId=="string"&&(t.status==="resolved"||t.status==="degraded")&&typeof t.completedAt=="number"&&typeof t.attempt=="number"&&(t.reason===void 0||typeof t.reason=="string")}).slice(-20):[]}function ve(n){if(!n||typeof n!="object")return null;let e=n;if(!["add","correction","resolve","degrade"].includes(e.kind??"")||typeof e.contractId!="string"||e.contractId.length>128||typeof e.at!="number")return null;let t=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:U(e.contractId);if(e.kind==="add")return q(e.contract)?{...e,obligationId:t}:null;if(e.kind==="correction"){let r=typeof e.fingerprint=="string"?e.fingerprint:e.transcriptHash;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)&&Array.isArray(e.violations)&&e.violations.every(o=>typeof o=="string"&&o.length<=240)?{...e,obligationId:t,fingerprint:r}:null}return e.kind==="resolve"?{...e,obligationId:t}:typeof e.reason=="string"&&e.reason.length<=240?{...e,obligationId:t}:null}function z(n){return n==="add"?0:n==="correction"?1:2}function q(n){if(!n||typeof n!="object")return false;let e=n,t=e.requiredSections,r=e.prohibitedClaims;return e.version==="1.0"&&typeof e.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(e.id)&&typeof e.runtimeProfilingOccurred=="boolean"&&typeof e.samplingEvidenceOccurred=="boolean"&&Array.isArray(t)&&t.length===3&&t[0]==="\u5DE5\u5177\u53D1\u73B0"&&t[1]==="\u6A21\u578B\u5047\u8BBE"&&t[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(r)&&r.length<=16&&r.every(o=>typeof o=="string"&&o.length<=128)&&typeof e.canonicalReport=="string"&&Buffer.byteLength(e.canonicalReport,"utf8")<=48*1024&&!!e.correctionPolicy&&e.correctionPolicy.maxAttempts===1&&e.correctionPolicy.repeatedViolation==="fail_open"}function x(n,e,t){try{let r=openGlobalDevFlowDatabase();try{r.insertEvent({kind:n,timestamp:Date.now(),duration:t,success:e.success!==!1,metadata:e});}finally{r.close();}}catch{}}var xe=getLocalApiKey(),C=join(homedir(),".devflow","errors");async function _(n,e,t={}){let r=t.endpoint??resolveRuntimeEndpoint().url,o=t.timeout??1500,i=t.durableMirror??true,s=t.maxRetries??(i?0:2),a=t.circuitBreaker??true,c=acquireRuntimeHttpCircuit(r,n);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let d;for(let u=0;u<=s;u+=1)try{return await Ce(r,n,e,o),a&&registerRuntimeHttpSuccess(r,n).transitioned&&x("http_circuit_transition",{endpoint:r,path:new URL(n,r).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(m){d=m instanceof Error?m:new Error(String(m)),u<s&&await Me(Math.min(100*2**u,1e3));}if(!d)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return V(n,d),{delivered:false,suppressed:false,fallbackReason:d.message};let l=registerRuntimeHttpFailure(r,n,t.fallbackReason??(i?"local_durable_mirror":"http_delivery_failed"));return l.transitioned&&(V(n,d),x("http_circuit_transition",{endpoint:r,path:new URL(n,r).pathname,previous:c.state.status,status:"open",failures:l.state.failures,openUntil:l.state.openUntil,fallbackReason:l.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:l.state.fallbackReason}}function Ce(n,e,t,r){return new Promise((o,i)=>{let s=JSON.stringify(t),a=new URL(e,n),c=false,d=u=>{c||(c=true,u?i(u):o());},l=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":xe,"Content-Length":Buffer.byteLength(s)},timeout:r},u=>{u.on("error",d),u.on("end",()=>{let m=u.statusCode??0;d(m>=200&&m<300?void 0:new Error(`HTTP ${m}`));}),u.resume();});l.on("error",d),l.on("timeout",()=>l.destroy(new Error(`HTTP mirror timed out after ${r}ms`))),l.write(s),l.end();})}function V(n,e){try{existsSync(C)||mkdirSync(C,{recursive:!0}),appendFileSync(join(C,"http-errors.log"),`${new Date().toISOString()} | ${n} | ${e.message}
2
- `);}catch{}}function Me(n){return new Promise(e=>setTimeout(e,n))}function Z(n,e){let t=$e(n);mkdirSync(t,{recursive:true,mode:448});let r=join(t,`${e.receiptId}.json`);if(existsSync(r))return e.receiptId;let o=`${r}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(e),{mode:384});try{renameSync(o,r);}catch(i){try{unlinkSync(o);}catch{}if(!existsSync(r))throw i}return e.receiptId}function $e(n){return join(S(n),"session-finalize-pending")}var ze=512*1024,He=500;var Ue=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function te(n){let e=n.runtimeStore??new y(n.projectRoot),t=e.listEvidenceObligations(n.sessionId);if(t.length===0)return null;let r=re(n.transcriptPath,t);if(!r.answer){let s=r.degradationReason??"transcript_answer_unavailable";for(let a of t)e.degradeEvidenceObligation(n.sessionId,a.obligationId,s);return null}let o=r.fingerprint;if(!o){for(let s of t)e.degradeEvidenceObligation(n.sessionId,s.obligationId,"transcript_identity_unavailable");return null}let i=[];for(let s of t){let a=Je(r.answer,[s]);if(a.length===0){e.resolveEvidenceObligation(n.sessionId,s.obligationId);continue}if(!s.correctionFingerprint){e.markEvidenceCorrection(n.sessionId,s.obligationId,a,o),i.push({obligation:s,violations:a});continue}if(s.correctionFingerprint===o){i.push({obligation:s,violations:a});continue}e.degradeEvidenceObligation(n.sessionId,s.obligationId,"evidence_contract_unresolved");}return i.length===0?null:qe(i)}function qe(n){let e=[...new Set(n.flatMap(r=>r.violations))],t=[...new Map(n.map(r=>[r.obligation.contractId,r.obligation.contract.canonicalReport])).values()];return {decision:"block",reason:["DevFlow evidence contract violation. Correct the final performance answer once before stopping.",`Violations: ${e.join("; ")}`,"Use this canonical report (you may add clearly labeled hypotheses or runtime verification steps, but no unsupported measured claims):",t.join(`
1
+ import {getLocalApiKey,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir}from'@devflow-tools/sdk';import {existsSync as existsSync$1,readFileSync as readFileSync$1,rmSync,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1}from'fs';import {join as join$1}from'path';import {randomUUID,createHash as createHash$1}from'crypto';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import'@devflow-tools/memory-engine';import'os';import {request}from'node:http';import {mkdirSync,existsSync,writeFileSync,renameSync,unlinkSync,readFileSync,openSync,constants,fstatSync,closeSync,appendFileSync,lstatSync,readSync}from'node:fs';import {join,resolve}from'node:path';import {homedir}from'node:os';import {createHash}from'node:crypto';function v(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function S(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(v(n))}function j(n){return Buffer.from(n,"utf8").toString("base64url")}function be(n,e,t){let o=e?.trim();if(o){let r=/^[a-zA-Z0-9:._-]{1,192}$/.test(o)?o:`tool-${createHash$1("sha256").update(o.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${r}`}return `${n}:legacy-${t}-${randomUUID().slice(0,8)}`}function U(n){return `${n}:legacy-journal`}var y=class{constructor(e){this.projectRoot=e;this.sessions=new Map;this.sessionsDir=join$1(S(e),"hook-sessions");}registerSession(e){let t=e.trim();if(!t)throw new Error("session_id_required");let o=this.get(t);if(o)return o.lastActivityAt=Date.now(),this.persist(o),o;let r=Date.now(),i={sessionId:t,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:r,lastActivityAt:r};return this.sessions.set(t,i),this.persist(i),i}startExecution(e,t,o){let r=this.registerSession(e);return (!r.executionId||r.skillName!==t)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=t,r.requiredMcpTools=[...new Set(o)],r.lastActivityAt=Date.now(),this.persist(r),r}get(e){let t=e.trim();if(!t)return null;let o=this.sessions.get(t);if(o)return this.replayEvidenceJournal(o),o;let r=this.snapshotPath(t);if(!existsSync$1(r))return null;try{let i=JSON.parse(readFileSync$1(r,"utf8"));return i.sessionId!==t||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],i.evidenceObligations=F(i.evidenceObligations),i.evidenceDegradations=N(i.evidenceDegradations),i.evidenceOutcomes=L(i.evidenceOutcomes),this.replayEvidenceJournal(i),this.sessions.set(t,i),i)}catch{return null}}completeExecution(e){let t=this.get(e);if(!t)return null;let o=structuredClone(t);return delete t.executionId,delete t.skillName,t.requiredMcpTools=[],t.lastActivityAt=Date.now(),this.persist(t),o}addEvidenceObligation(e,t,o=Date.now(),r){let i=this.registerSession(e),a=(r?void 0:i.evidenceObligations.find(d=>d.contractId===t.id))?.obligationId??be(t.id,r,o);this.appendEvidenceEvent(e,{kind:"add",obligationId:a,contractId:t.id,at:o,contract:t},`add\0${a}`),this.replayEvidenceJournal(i);let c=i.evidenceObligations.find(d=>d.obligationId===a);return c?(i.lastActivityAt=Date.now(),this.persist(i),structuredClone(c)):null}listEvidenceObligations(e){return (this.get(e)?.evidenceObligations??[]).map(t=>structuredClone(t))}markEvidenceCorrection(e,t,o,r,i=Date.now()){let s=this.get(e),a=s?.evidenceObligations.find(l=>l.obligationId===t);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(r)?r:"";if(!c)return null;this.appendEvidenceEvent(e,{kind:"correction",obligationId:t,contractId:a.contractId,at:i,fingerprint:c,violations:o.slice(0,16).map(l=>l.slice(0,240))},`correction\0${t}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=i,this.persist(s);let d=s.evidenceObligations.find(l=>l.obligationId===t);return d?structuredClone(d):null}resolveEvidenceObligation(e,t){let o=this.get(e);if(!o)return false;let r=o.evidenceObligations.find(s=>s.obligationId===t);if(!r)return false;let i=Date.now();return this.appendEvidenceEvent(e,{kind:"resolve",obligationId:t,contractId:r.contractId,at:i},`resolve\0${t}`),this.replayEvidenceJournal(o),o.lastActivityAt=i,this.persist(o),true}degradeEvidenceObligation(e,t,o,r=Date.now()){let i=this.get(e),s=i?.evidenceObligations.find(c=>c.obligationId===t);if(!i||!s)return false;let a=o.slice(0,240);return this.appendEvidenceEvent(e,{kind:"degrade",obligationId:t,contractId:s.contractId,at:r,reason:a},`degrade\0${t}\0${a}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}removeSession(e){let t=e.trim();t&&(this.sessions.delete(t),rmSync(this.snapshotPath(t),{force:true}),rmSync(this.evidenceJournalDir(t),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(e){return join$1(this.sessionsDir,`${j(e)}.json`)}evidenceJournalDir(e){return join$1(this.sessionsDir,"evidence-journal",j(e))}appendEvidenceEvent(e,t,o){let r=this.evidenceJournalDir(e);mkdirSync$1(r,{recursive:true,mode:448});let i=createHash$1("sha256").update(o).digest("hex"),s=join$1(r,`${t.kind}-${i}.json`);if(existsSync$1(s))return;let a=join$1(r,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(t),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(e){e.evidenceObligations=F(e.evidenceObligations),e.evidenceDegradations=N(e.evidenceDegradations),e.evidenceOutcomes=L(e.evidenceOutcomes);let t=this.evidenceJournalDir(e.sessionId);if(!existsSync$1(t))return;let o;try{o=readdirSync(t).filter(i=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(i)).slice(0,4096);}catch{return}let r=o.flatMap(i=>{try{let s=readFileSync$1(join$1(t,i),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=ve(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((i,s)=>i.at-s.at||z(i.kind)-z(s.kind));for(let i of r)this.applyEvidenceEvent(e,i);e.evidenceObligations=e.evidenceObligations.slice(-8),e.evidenceDegradations=e.evidenceDegradations.slice(-20),e.evidenceOutcomes=e.evidenceOutcomes.slice(-20);}applyEvidenceEvent(e,t){let o=e.evidenceOutcomes.find(s=>s.obligationId===t.obligationId);if(t.kind==="add"){if(o)return;let s=e.evidenceObligations.find(a=>a.obligationId===t.obligationId);s?(s.contract=t.contract,s.promptedAt=Math.min(s.promptedAt,t.at)):e.evidenceObligations.push({obligationId:t.obligationId,contractId:t.contractId,contract:t.contract,promptedAt:t.at,attempt:0,correctionRequested:false,violations:[]});return}let r=e.evidenceObligations.find(s=>s.obligationId===t.obligationId);if(t.kind==="correction"){if(!r||o||r.correctionFingerprint===t.fingerprint)return;r.attempt+=1,r.correctionRequested=true,r.correctionRequestedAt=t.at,r.correctionFingerprint=t.fingerprint,r.violations=t.violations;return}let i=r?.attempt??0;e.evidenceObligations=e.evidenceObligations.filter(s=>s.obligationId!==t.obligationId),!o&&(t.kind==="degrade"&&e.evidenceDegradations.push({obligationId:t.obligationId,contractId:t.contractId,reason:t.reason,degradedAt:t.at,attempt:i}),e.evidenceOutcomes.push({obligationId:t.obligationId,contractId:t.contractId,status:t.kind==="resolve"?"resolved":"degraded",completedAt:t.at,attempt:i,...t.kind==="degrade"?{reason:t.reason}:{}}));}persist(e){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let t=this.snapshotPath(e.sessionId),o=`${t}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(o,JSON.stringify(e),{mode:384}),renameSync$1(o,t);}};function F(n){return Array.isArray(n)?n.flatMap(e=>{if(!e||typeof e!="object")return [];let t=e;if(typeof t.contractId!="string"||t.contractId.length===0||t.contractId.length>128||typeof t.promptedAt!="number"||typeof t.attempt!="number"||typeof t.correctionRequested!="boolean"||!Array.isArray(t.violations)||!q(t.contract))return [];let o=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:U(t.contractId),r=typeof t.correctionTranscriptHash=="string"?t.correctionTranscriptHash:void 0,i=t.correctionFingerprint??r;return i!==void 0&&!/^[a-f0-9]{64}$/.test(i)?[]:[{...t,obligationId:o,correctionFingerprint:i}]}).slice(-8):[]}function N(n){return Array.isArray(n)?n.filter(e=>{if(!e||typeof e!="object")return false;let t=e;return typeof t.obligationId=="string"&&typeof t.contractId=="string"&&typeof t.reason=="string"&&typeof t.degradedAt=="number"&&typeof t.attempt=="number"}).slice(-20):[]}function L(n){return Array.isArray(n)?n.filter(e=>{if(!e||typeof e!="object")return false;let t=e;return typeof t.obligationId=="string"&&typeof t.contractId=="string"&&(t.status==="resolved"||t.status==="degraded")&&typeof t.completedAt=="number"&&typeof t.attempt=="number"&&(t.reason===void 0||typeof t.reason=="string")}).slice(-20):[]}function ve(n){if(!n||typeof n!="object")return null;let e=n,t=e.kind;if(t!=="add"&&t!=="correction"&&t!=="resolve"&&t!=="degrade"||typeof e.contractId!="string"||e.contractId.length>128||typeof e.at!="number")return null;let r={obligationId:typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:U(e.contractId),contractId:e.contractId,at:e.at};if(t==="add")return q(e.contract)?{kind:t,...r,contract:e.contract}:null;if(t==="correction"){let i=typeof e.fingerprint=="string"?e.fingerprint:e.transcriptHash;return typeof i=="string"&&/^[a-f0-9]{64}$/.test(i)&&Array.isArray(e.violations)&&e.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:t,...r,fingerprint:i,violations:e.violations}:null}return t==="resolve"?{kind:t,...r}:typeof e.reason=="string"&&e.reason.length<=240?{kind:t,...r,reason:e.reason}:null}function z(n){return n==="add"?0:n==="correction"?1:2}function q(n){if(!n||typeof n!="object")return false;let e=n,t=e.requiredSections,o=e.prohibitedClaims;return e.version==="1.0"&&typeof e.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(e.id)&&typeof e.runtimeProfilingOccurred=="boolean"&&typeof e.samplingEvidenceOccurred=="boolean"&&Array.isArray(t)&&t.length===3&&t[0]==="\u5DE5\u5177\u53D1\u73B0"&&t[1]==="\u6A21\u578B\u5047\u8BBE"&&t[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(o)&&o.length<=16&&o.every(r=>typeof r=="string"&&r.length<=128)&&typeof e.canonicalReport=="string"&&Buffer.byteLength(e.canonicalReport,"utf8")<=48*1024&&!!e.correctionPolicy&&e.correctionPolicy.maxAttempts===1&&e.correctionPolicy.repeatedViolation==="fail_open"}function x(n,e,t){try{let o=openGlobalDevFlowDatabase();try{o.insertEvent({kind:n,timestamp:Date.now(),duration:t,success:e.success!==!1,metadata:e});}finally{o.close();}}catch{}}var xe=getLocalApiKey(),C=join(homedir(),".devflow","errors");async function _(n,e,t={}){let o=t.endpoint??resolveRuntimeEndpoint().url,r=t.timeout??1500,i=t.durableMirror??true,s=t.maxRetries??(i?0:2),a=t.circuitBreaker??true,c=acquireRuntimeHttpCircuit(o,n);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let d;for(let u=0;u<=s;u+=1)try{return await Ce(o,n,e,r),a&&registerRuntimeHttpSuccess(o,n).transitioned&&x("http_circuit_transition",{endpoint:o,path:new URL(n,o).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(m){d=m instanceof Error?m:new Error(String(m)),u<s&&await Ae(Math.min(100*2**u,1e3));}if(!d)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return V(n,d),{delivered:false,suppressed:false,fallbackReason:d.message};let l=registerRuntimeHttpFailure(o,n,t.fallbackReason??(i?"local_durable_mirror":"http_delivery_failed"));return l.transitioned&&(V(n,d),x("http_circuit_transition",{endpoint:o,path:new URL(n,o).pathname,previous:c.state.status,status:"open",failures:l.state.failures,openUntil:l.state.openUntil,fallbackReason:l.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:l.state.fallbackReason}}function Ce(n,e,t,o){return new Promise((r,i)=>{let s=JSON.stringify(t),a=new URL(e,n),c=false,d=u=>{c||(c=true,u?i(u):r());},l=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":xe,"Content-Length":Buffer.byteLength(s)},timeout:o},u=>{u.on("error",d),u.on("end",()=>{let m=u.statusCode??0;d(m>=200&&m<300?void 0:new Error(`HTTP ${m}`));}),u.resume();});l.on("error",d),l.on("timeout",()=>l.destroy(new Error(`HTTP mirror timed out after ${o}ms`))),l.write(s),l.end();})}function V(n,e){try{existsSync(C)||mkdirSync(C,{recursive:!0}),appendFileSync(join(C,"http-errors.log"),`${new Date().toISOString()} | ${n} | ${e.message}
2
+ `);}catch{}}function Ae(n){return new Promise(e=>setTimeout(e,n))}function Z(n,e){let t=$e(n);mkdirSync(t,{recursive:true,mode:448});let o=join(t,`${e.receiptId}.json`);if(existsSync(o))return e.receiptId;let r=`${o}.${process.pid}.tmp`;writeFileSync(r,JSON.stringify(e),{mode:384});try{renameSync(r,o);}catch(i){try{unlinkSync(r);}catch{}if(!existsSync(o))throw i}return e.receiptId}function $e(n){return join(S(n),"session-finalize-pending")}var ze=512*1024,He=500;var Ue=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function te(n){let e=n.runtimeStore??new y(n.projectRoot),t=e.listEvidenceObligations(n.sessionId);if(t.length===0)return null;let o=oe(n.transcriptPath,t);if(!o.answer){let s=o.degradationReason??"transcript_answer_unavailable";for(let a of t)e.degradeEvidenceObligation(n.sessionId,a.obligationId,s);return null}let r=o.fingerprint;if(!r){for(let s of t)e.degradeEvidenceObligation(n.sessionId,s.obligationId,"transcript_identity_unavailable");return null}let i=[];for(let s of t){let a=Je(o.answer,[s]);if(a.length===0){e.resolveEvidenceObligation(n.sessionId,s.obligationId);continue}if(!s.correctionFingerprint){e.markEvidenceCorrection(n.sessionId,s.obligationId,a,r),i.push({obligation:s,violations:a});continue}if(s.correctionFingerprint===r){i.push({obligation:s,violations:a});continue}e.degradeEvidenceObligation(n.sessionId,s.obligationId,"evidence_contract_unresolved");}return i.length===0?null:qe(i)}function qe(n){let e=[...new Set(n.flatMap(o=>o.violations))],t=[...new Map(n.map(o=>[o.obligation.contractId,o.obligation.contract.canonicalReport])).values()];return {decision:"block",reason:["DevFlow evidence contract violation. Correct the final performance answer once before stopping.",`Violations: ${e.join("; ")}`,"Use this canonical report (you may add clearly labeled hypotheses or runtime verification steps, but no unsupported measured claims):",t.join(`
3
3
 
4
4
  ---
5
5
 
6
6
  `)].join(`
7
7
 
8
- `)}}function Je(n,e){let t=new Set,r=new Set(e.flatMap(c=>c.contract.requiredSections)),o=ne(n.split(/\r?\n/)),i=oe(o.headingLines);for(let c of r)i.found.has(c)||t.add(`missing_section:${c}`);if(e.every(c=>c.contract.runtimeProfilingOccurred))return [...t];let a=e.every(c=>c.contract.samplingEvidenceOccurred);for(let c=0;c<o.claimLines.length;c++){let d=o.claimLines[c].trim();if(!d||Be(d))continue;let l=i.byLine.get(c);for(let u of Ye(d))Ve(u,l,a,t);}return [...t]}function ne(n){let e=false,t=[],r=[];for(let o of n){if(/^\s*```/.test(o)){e=!e,t.push(""),r.push(o.replace(/^\s*```+[^\s`]*/,"").replace(/```+\s*$/,"").trim());continue}t.push(e?"":o.replace(/`[^`]*`/g,"").trim()),r.push(o.replace(/`([^`]*)`/g,(i,s)=>We(s)?"":s).trim());}return {headingLines:t,claimLines:r}}function We(n){let e=n.trim().slice(0,256);return !e||/\s/.test(e)||n.trim().length>256?false:/^[A-Za-z_$][\w$.-]*$/.test(e)||/^(['"])[^'"`]*\1$/.test(e)}function Be(n){if(n.length>2048)return false;let e=n.replace(/^\s*(?:[-*+]|\d+[.)])\s+/,"").trim();return e?Ge(e)||/^(?:\/\/|\/\*|\*\/|\*\s|#!)/.test(e)||/^(?:import|export|const|let|var|function|class|type|interface|enum|namespace|declare)\b/.test(e)||/^(?:async\s+)?(?:function\s+)?[A-Za-z_$][\w$]*\s*=\s*/.test(e)||/^[A-Za-z_$][\w$.[\]'"-]*\s*(?:=|\+=|-=|\*=|\/=|\?\?=|&&=|\|\|=)\s*/.test(e)||/^[A-Za-z_$'"-][\w$.'"-]*\s*:\s*[^:]+[,}]?$/.test(e)||/=>/.test(e)||/^(?:await\s+|return\s+|throw\s+|new\s+)?[A-Za-z_$][\w$.]*\s*\([^)]*\)\s*;?$/.test(e)||/^(['"])[\s\S]*\1[;,]?$/.test(e)?true:/[{}()[\]=<>]\s*;?$/.test(e)&&/(?:;|=>|\b(?:return|new|await)\b)/.test(e):false}function Ge(n){if(n.length>1024)return false;let e="(?:--[A-Za-z0-9_-]+|(?:-webkit-|-moz-|-ms-)?(?:animation(?:-[a-z-]+)?|transition(?:-[a-z-]+)?|opacity|transform|will-change|contain|content-visibility|display|position|top|right|bottom|left|width|height|min-(?:width|height)|max-(?:width|height)|margin(?:-[a-z]+)?|padding(?:-[a-z]+)?|color|background(?:-[a-z-]+)?|border(?:-[a-z-]+)?|font(?:-[a-z-]+)?|line-height|z-index|overflow(?:-[xy])?))";return new RegExp(`^${e}\\s*:\\s*\\S[^;]{0,960};$`,"i").test(n)}function Ve(n,e,t,r){let o=/\bP0\b/gi;for(let f of n.matchAll(o))ee(n,f.index??0,f[0],"p0")||r.add("unsupported_p0_severity");let i=/(?:中高|高)(?:风险|优先级)|严重(?:问题|风险)|\bhigh[- ](?:risk|severity|priority)\b/gi;for(let f of n.matchAll(i))ee(n,f.index??0,f[0],"high")||r.add("unsupported_high_severity");let s=/(?:性能)?瓶颈|卡顿|掉帧|CPU\s*(?:热点|尖峰)|\bbottleneck\b|\bjank\b|\bdropped frames?\b|\bCPU hotspot\b/gi;for(let f of n.matchAll(s))Xe(n,f.index??0,f[0])||(/(?:瓶颈|bottleneck)/i.test(f[0])?r.add("unsupported_confirmed_bottleneck"):r.add("unsupported_runtime_effect"));let a=/\b\d{1,3}(?:\.\d+)?\s*%/.test(n),c=/(?:预计|预期|估计|提升|降低|减少|节省|改善|收益|加速|improve|reduce|faster|gain|benefit|speedup|expected|estimated)/i.test(n),d=/\b\d+(?:\.\d+)?\s*[x×]\b/i.test(n);(a||d)&&c&&r.add(a?"unsupported_benefit_percentage":"unsupported_performance_number");let l=/\b\d+(?:\.\d+)?(?:\s*[-–~]\s*\d+(?:\.\d+)?)?\s*(?:ms|fps|hz)\b/i.test(n)||/\d+(?:\.\d+)?(?:\s*[-–~]\s*\d+(?:\.\d+)?)?\s*(?:毫秒|次\s*\/\s*秒|帧)/.test(n),u=e==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&/(?:采集|记录|测量|收集|collect|measure|record)/i.test(n)&&!/(?:预计|预期|估计|约|大约|通常|平均|每(?:隔)?|达到|提升|降低|减少|节省|改善|improve|reduce|faster|expected|estimated|average|typically|every)/i.test(n);a&&!c&&!u&&r.add("unsupported_benefit_percentage"),l&&!u&&r.add("unsupported_performance_number");let m=/(?:requestAnimationFrame|\bRAF\b)/i.test(n),g=/(?:建议|应该|应当|使用|添加|采用|切换|包裹|优化|节流|\buse\b|\badopt\b|\brecommend\b|\bswitch\b|\bwrap\b|\bthrottl(?:e|ing)\b)/i.test(n),p=/(?:不要|不得|不能|不应|避免|不建议|不推荐).{0,16}(?:使用|采用|添加|切换|包裹|节流)?.{0,8}(?:requestAnimationFrame|\bRAF\b)|\b(?:do\s+not|don't|never|avoid)\s+(?:use|adopt|recommend|switch|wrap|throttle)?.{0,8}(?:requestAnimationFrame|RAF)\b/i.test(n);m&&g&&!p&&!t&&r.add("raf_without_sampling_evidence");}function ee(n,e,t,r){let o=n.slice(Math.max(0,e-64),e),i=n.slice(e+t.length,e+t.length+28),s=Ke(o),a=/^(?:\s+)?(?:未发现|不存在|并不存在|未被发现)/.test(i)||/^(?:\s+)?(?:was\s+|is\s+)?not found\b/i.test(i);return s||a?true:r==="high"?/(?:未发现|没有发现|不存在|无证据(?:表明|证明)?)\s*(?:任何|明确的)?\s*P0\s*(?:或|和|及|、)\s*$/i.test(o)||/\b(?:no evidence (?:of|for)|no)\s+P0\s+(?:or|and)\s+$/i.test(o):false}function Ke(n){if(/(?:未发现|没有发现|不存在|无证据(?:表明|证明)?|不是|并非|未被)\s*(?:任何|明确的)?\s*(?:(?:问题|发现|证据|项|内容)\s*)?(?:(?:属于|(?:被)?(?:评|判定|认定|标记|列|视|定|归(?:类)?)为)\s*)?$/i.test(n)||/\b(?:no evidence (?:of|for)|no|not|isn't|is\s+not)\s+(?:an?\s+)?(?:(?:issues?|findings?|evidence|items?)\s+)?(?:(?:classified|rated|marked|labelled|labeled)(?:\s+as)?\s+)?$/i.test(n))return true;let t=/(?:不得|不能|不应|不宜|不要)\s*(?:被\s*)?(?:(?:直接|轻易|简单|明确|正式|合理|据此|当前|目前)\s*){0,2}(?:(?:评|判定|认定|标记|列|视|定|归(?:类)?)为|属于)\s*$/i,r=/\b(?:cannot|can't|must not|should not|shouldn't|do not|don't)\s+(?:(?:reasonably|directly|formally|currently)\s+){0,2}(?:be\s+)?(?:classified|labeled|labelled|rated|marked)(?:\s+as)?\s+$/i;return t.test(n)||r.test(n)}function Xe(n,e,t){let r=n.slice(Math.max(0,e-40),e),o=n.slice(e+t.length,e+t.length+32),i=/(?:是否|待验证|候选|可能|潜在|未观察到|没有观察到|未发现|不存在|无证据(?:表明)?|不能(?:据此)?确认|尚未(?:确认|证明)|验证(?:是否)?|测量(?:是否)?|采集|记录|收集).{0,16}$/i.test(r)||/\b(?:whether|measure|validate|candidate|potential|possible|may|might|no|no evidence(?: of| for)?|not observed|unobserved|collect|record).{0,18}$/i.test(r),s=/^(?:是否|有待验证|待验证|候选|可能|潜在|指标|需要(?:验证|测量)|需(?:验证|测量))/.test(o)||/^(?:\s+)?(?:candidate|potential|possible|metric|metrics|to (?:measure|validate)|needs? (?:measurement|validation)|is (?:a )?(?:candidate|potential))/i.test(o);return i||s}function Ye(n){return n.split(/(?:[。!?;;,,]|\b(?:but|however|yet|nevertheless|nonetheless)\b|但是|但|然而|却|不过|可是)/i).map(e=>e.trim()).filter(Boolean)}function re(n,e){if(!n||n.length>4096)return {degradationReason:"transcript_path_missing"};let t;try{let r=lstatSync(n);if(!r.isFile()||r.isSymbolicLink())return {degradationReason:"transcript_path_unsafe"};t=openSync(n,constants.O_RDONLY|(constants.O_NOFOLLOW??0));let o=fstatSync(t);if(!o.isFile()||o.dev!==r.dev||o.ino!==r.ino)return {degradationReason:"transcript_path_changed"};let i=Math.min(o.size,ze),s=Buffer.alloc(i),a=0;for(;a<i;){let p=readSync(t,s,a,i-a,o.size-i+a);if(p===0)break;a+=p;}let c=s.subarray(0,a).toString("utf8");o.size>i&&(c=c.slice(Math.max(0,c.indexOf(`
9
- `)+1)));let d=c.split(/\r?\n/).slice(-He),l=e.length>0?Math.min(...e.map(p=>p.promptedAt)):0,u=Qe(d,l),g=[...u].reverse().find(p=>Ze(p.text,e))??u.at(-1);return g?.text?{answer:g.text,fingerprint:g.fingerprint}:{degradationReason:"transcript_answer_unavailable"}}catch{return {degradationReason:"transcript_unreadable"}}finally{t!==void 0&&closeSync(t);}}function Ze(n,e){let t=new Set(e.flatMap(o=>o.contract.requiredSections)),r=oe(ne(n.split(/\r?\n/u)).headingLines);return [...t].every(o=>r.found.has(o))}function A(n){return re(n,[]).answer}function Qe(n,e){let t=[];for(let r=0;r<n.length;r++){let o=n[r];if(o.trim())try{let i=JSON.parse(o),s=i.message;if(!s||typeof s!="object"||s.role!=="assistant")continue;let a=s,c=et(i.timestamp);if(c>0&&c+5e3<e)continue;let d=s.content,l=typeof d=="string"?d:Array.isArray(d)?d.filter(u=>u&&typeof u=="object"&&u.type==="text").map(u=>u.text).filter(u=>typeof u=="string").join(`
10
- `):"";if(l.trim()){let u=l.trim(),m=typeof a.id=="string"&&a.id?`message:${a.id}`:typeof i.uuid=="string"&&i.uuid?`uuid:${i.uuid}`:`record:${String(i.timestamp??"")}:${r}:${createHash("sha256").update(o).digest("hex")}`,g=createHash("sha256").update(u).digest("hex"),p=createHash("sha256").update(`${m}\0${g}`).digest("hex");t.push({text:u,timestamp:c,fingerprint:p});}}catch{continue}}return t}function et(n){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n!="string")return 0;let e=Date.parse(n);return Number.isFinite(e)?e:0}function oe(n){let e=new Set,t=new Map,r;for(let o=0;o<n.length;o++){let i=n[o].trim().replace(/^#{1,6}\s*/,"").replace(/^\*\*(.*)\*\*$/,"$1").replace(/^(?:[一二三123][、..]\s*)/,"").replace(/[::]\s*$/,"").trim(),s=Ue.find(a=>i===a);s&&(r=s,e.add(s)),t.set(o,r);}return {found:e,byLine:t}}function ie(n){let e={committed:0,skipped:0,pending:0},t=[];for(let r of n)e[r.status]+=1,r.receiptId&&t.push(r.receiptId);return {memoryReceiptIds:[...new Set(t)],missingMemoryDecisionCount:e.pending,memoryTurnOutcomes:e}}function rt(n,e=v(),t=true,r,o=true){let i;try{i=JSON.parse(n);}catch{return null}let s=i.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${e}\0${s}`).digest("hex").slice(0,24)}`,c={inputJson:n,sessionId:s,cleanupSharedState:t,executionId:r},d;try{d=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let l=d.requestSessionClosure({receiptId:a,projectRoot:e,sessionId:s,payload:c}),u=d.getWorkByIdempotencyKey(a);return {status:l.state==="closed"||l.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:u?.state??"pending",closureState:l.state,pendingWorkCount:l.pendingWorkCount}}catch(l){if(!o)throw l;return Z(e,{receiptId:a,...c}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{d?.close();}}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 e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=rt(e.trim()||process.argv[2]||"");t&&n(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}var k=1,lt="memory-snapshot-v1.json",ut=512*1024,de=256*1024,le=2e3,mt=500,pt=10,ft=240,gt=300*1e3,yt=720*60*60*1e3,ht=2147483647;function bt(n){return n.currentUid===void 0?{ownerSafe:true,modeSafe:true}:{ownerSafe:n.ownerUid===n.currentUid,modeSafe:(n.mode&18)===0}}function b(n){return resolve(n)}function w(n){return createHash("sha256").update(b(n)).digest("hex").slice(0,16)}function vt(n,e={}){let t=w(n),r=e.stateRoot?join(e.stateRoot,t):getProjectStateDir(b(n));return join(r,lt)}function St(n,e){let r=(n instanceof Error?n.message:"").replace(/[\r\n\t]+/gu," ").trim().slice(0,160);return r?`${e}:${r}`:e}function D(n,e){return Array.isArray(n)&&n.length<=e&&n.every(t=>typeof t=="string"&&t.length>0&&t.length<=512)}function wt(n){if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return typeof e.id=="string"&&e.id.length>0&&e.id.length<=512&&typeof e.kind=="string"&&e.kind.length>0&&e.kind.length<=128&&(e.family===void 0||typeof e.family=="string"&&e.family.length>0&&e.family.length<=256)&&(e.entity===void 0||typeof e.entity=="string"&&e.entity.length>0&&e.entity.length<=256)&&D(e.memoryIds,100)&&(e.status==="withheld"||e.status==="resolved")&&(e.summary===void 0||typeof e.summary=="string"&&e.summary.length<=2e3)}function It(n){if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return typeof e.reason=="string"&&e.reason.length>0&&e.reason.length<=512&&(e.stale===void 0||typeof e.stale=="boolean")}function ue(n,e,t){if(!n||typeof n!="object"||Array.isArray(n))return null;let r=n,o=b(e),i=w(o),s=r.generation===void 0?0:r.generation;return r.version!==k||r.projectRoot!==o||r.projectHash!==i||typeof r.markdown!="string"||Buffer.byteLength(r.markdown,"utf8")>de||!D(r.memoryIds,le)||!Array.isArray(r.conflicts)||r.conflicts.length>mt||!r.conflicts.every(wt)||typeof r.generatedAt!="number"||!Number.isFinite(r.generatedAt)||r.generatedAt<0||r.generatedAt>t+gt||!Number.isInteger(s)||s<0||s>ht||!["ready","pending","degraded","disabled"].includes(String(r.status))||r.degradation!==void 0&&!It(r.degradation)?null:{...r,generation:s}}function _t(n,e,t,r,o=0){let i=b(n);return {version:k,projectRoot:i,projectHash:w(i),markdown:"",memoryIds:[],conflicts:[],generatedAt:r,generation:o,status:e,degradation:{reason:t}}}function kt(n,e={}){let t=e.now??Date.now(),r=vt(n,e),o;try{o=openSync(r,constants.O_RDONLY|constants.O_NOFOLLOW);let i=fstatSync(o);if(!i.isFile()||i.size<=0||i.size>ut)throw new Error("cache_size_invalid");let s=bt({...typeof process.getuid=="function"?{currentUid:process.getuid()}:{},ownerUid:i.uid,mode:i.mode});if(!s.ownerSafe)throw new Error("cache_owner_invalid");if(!s.modeSafe)throw new Error("cache_permissions_unsafe");let a=JSON.parse(readFileSync(o,"utf8")),c=ue(a,n,t);if(!c)throw new Error("cache_schema_invalid");return c.status==="ready"&&t-c.generatedAt>yt?{snapshot:{...c,status:"degraded",degradation:{reason:"cache_stale",stale:!0}},source:"cache",valid:!0,stale:!0}:{snapshot:c,source:"cache",valid:!0,stale:!1}}catch(i){let a=i.code==="ENOENT";return {snapshot:_t(n,a?"pending":"degraded",a?"cache_missing":St(i,"cache_invalid"),t),source:"none",valid:false,stale:false}}finally{if(o!==void 0)try{closeSync(o);}catch{}}}function Rt(n){if(!n)return true;try{return JSON.parse(readFileSync(n,"utf8")).sessionStart?.injectMemories??!0}catch{return true}}function Et(n,e,t){if(!e.trim())return null;try{let r=JSON.parse(e);if(r.status!=="ok"&&r.status!=="degraded")return null;if(r.enabled===!1){let i=b(n);return {version:k,projectRoot:i,projectHash:w(i),markdown:"",memoryIds:[],conflicts:[],generatedAt:t,generation:0,status:"disabled"}}let o=ue(r.snapshot,n,t);if(o)return o;if(r.status==="ok"&&typeof r.markdown=="string"&&r.markdown.length>0&&Buffer.byteLength(r.markdown,"utf8")<=de){let i=b(n);return {version:k,projectRoot:i,projectHash:w(i),markdown:r.markdown,memoryIds:D(r.memoryIds,le)?r.memoryIds:[],conflicts:[],generatedAt:t,generation:0,status:"ready"}}}catch{}return null}function O(n,e){return [...(n??e).replace(/[\r\n\t|]+/gu," ").trim()||e].slice(0,ft).join("")}function xt(n){if(n.length===0)return "";let e=n.slice(0,pt),t=e.map(r=>{let o=O(r.family,"unknown"),i=O(r.entity,"unknown"),s=O(r.summary,"Explicit choice required.");return `- family=${o}; entity=${i}; status=${r.status}; summary=${s}`});return n.length>e.length&&t.push(`- ${n.length-e.length} additional conflict(s) omitted from SessionStart output.`),`## Withheld preference conflicts (${n.length})
8
+ `)}}function Je(n,e){let t=new Set,o=new Set(e.flatMap(c=>c.contract.requiredSections)),r=ne(n.split(/\r?\n/)),i=re(r.headingLines);for(let c of o)i.found.has(c)||t.add(`missing_section:${c}`);if(e.every(c=>c.contract.runtimeProfilingOccurred))return [...t];let a=e.every(c=>c.contract.samplingEvidenceOccurred);for(let c=0;c<r.claimLines.length;c++){let d=r.claimLines[c].trim();if(!d||Be(d))continue;let l=i.byLine.get(c);for(let u of Ye(d))Ve(u,l,a,t);}return [...t]}function ne(n){let e=false,t=[],o=[];for(let r of n){if(/^\s*```/.test(r)){e=!e,t.push(""),o.push(r.replace(/^\s*```+[^\s`]*/,"").replace(/```+\s*$/,"").trim());continue}t.push(e?"":r.replace(/`[^`]*`/g,"").trim()),o.push(r.replace(/`([^`]*)`/g,(i,s)=>We(s)?"":s).trim());}return {headingLines:t,claimLines:o}}function We(n){let e=n.trim().slice(0,256);return !e||/\s/.test(e)||n.trim().length>256?false:/^[A-Za-z_$][\w$.-]*$/.test(e)||/^(['"])[^'"`]*\1$/.test(e)}function Be(n){if(n.length>2048)return false;let e=n.replace(/^\s*(?:[-*+]|\d+[.)])\s+/,"").trim();return e?Ge(e)||/^(?:\/\/|\/\*|\*\/|\*\s|#!)/.test(e)||/^(?:import|export|const|let|var|function|class|type|interface|enum|namespace|declare)\b/.test(e)||/^(?:async\s+)?(?:function\s+)?[A-Za-z_$][\w$]*\s*=\s*/.test(e)||/^[A-Za-z_$][\w$.[\]'"-]*\s*(?:=|\+=|-=|\*=|\/=|\?\?=|&&=|\|\|=)\s*/.test(e)||/^[A-Za-z_$'"-][\w$.'"-]*\s*:\s*[^:]+[,}]?$/.test(e)||/=>/.test(e)||/^(?:await\s+|return\s+|throw\s+|new\s+)?[A-Za-z_$][\w$.]*\s*\([^)]*\)\s*;?$/.test(e)||/^(['"])[\s\S]*\1[;,]?$/.test(e)?true:/[{}()[\]=<>]\s*;?$/.test(e)&&/(?:;|=>|\b(?:return|new|await)\b)/.test(e):false}function Ge(n){if(n.length>1024)return false;let e="(?:--[A-Za-z0-9_-]+|(?:-webkit-|-moz-|-ms-)?(?:animation(?:-[a-z-]+)?|transition(?:-[a-z-]+)?|opacity|transform|will-change|contain|content-visibility|display|position|top|right|bottom|left|width|height|min-(?:width|height)|max-(?:width|height)|margin(?:-[a-z]+)?|padding(?:-[a-z]+)?|color|background(?:-[a-z-]+)?|border(?:-[a-z-]+)?|font(?:-[a-z-]+)?|line-height|z-index|overflow(?:-[xy])?))";return new RegExp(`^${e}\\s*:\\s*\\S[^;]{0,960};$`,"i").test(n)}function Ve(n,e,t,o){let r=/\bP0\b/gi;for(let f of n.matchAll(r))ee(n,f.index??0,f[0],"p0")||o.add("unsupported_p0_severity");let i=/(?:中高|高)(?:风险|优先级)|严重(?:问题|风险)|\bhigh[- ](?:risk|severity|priority)\b/gi;for(let f of n.matchAll(i))ee(n,f.index??0,f[0],"high")||o.add("unsupported_high_severity");let s=/(?:性能)?瓶颈|卡顿|掉帧|CPU\s*(?:热点|尖峰)|\bbottleneck\b|\bjank\b|\bdropped frames?\b|\bCPU hotspot\b/gi;for(let f of n.matchAll(s))Xe(n,f.index??0,f[0])||(/(?:瓶颈|bottleneck)/i.test(f[0])?o.add("unsupported_confirmed_bottleneck"):o.add("unsupported_runtime_effect"));let a=/\b\d{1,3}(?:\.\d+)?\s*%/.test(n),c=/(?:预计|预期|估计|提升|降低|减少|节省|改善|收益|加速|improve|reduce|faster|gain|benefit|speedup|expected|estimated)/i.test(n),d=/\b\d+(?:\.\d+)?\s*[x×]\b/i.test(n);(a||d)&&c&&o.add(a?"unsupported_benefit_percentage":"unsupported_performance_number");let l=/\b\d+(?:\.\d+)?(?:\s*[-–~]\s*\d+(?:\.\d+)?)?\s*(?:ms|fps|hz)\b/i.test(n)||/\d+(?:\.\d+)?(?:\s*[-–~]\s*\d+(?:\.\d+)?)?\s*(?:毫秒|次\s*\/\s*秒|帧)/.test(n),u=e==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&/(?:采集|记录|测量|收集|collect|measure|record)/i.test(n)&&!/(?:预计|预期|估计|约|大约|通常|平均|每(?:隔)?|达到|提升|降低|减少|节省|改善|improve|reduce|faster|expected|estimated|average|typically|every)/i.test(n);a&&!c&&!u&&o.add("unsupported_benefit_percentage"),l&&!u&&o.add("unsupported_performance_number");let m=/(?:requestAnimationFrame|\bRAF\b)/i.test(n),g=/(?:建议|应该|应当|使用|添加|采用|切换|包裹|优化|节流|\buse\b|\badopt\b|\brecommend\b|\bswitch\b|\bwrap\b|\bthrottl(?:e|ing)\b)/i.test(n),p=/(?:不要|不得|不能|不应|避免|不建议|不推荐).{0,16}(?:使用|采用|添加|切换|包裹|节流)?.{0,8}(?:requestAnimationFrame|\bRAF\b)|\b(?:do\s+not|don't|never|avoid)\s+(?:use|adopt|recommend|switch|wrap|throttle)?.{0,8}(?:requestAnimationFrame|RAF)\b/i.test(n);m&&g&&!p&&!t&&o.add("raf_without_sampling_evidence");}function ee(n,e,t,o){let r=n.slice(Math.max(0,e-64),e),i=n.slice(e+t.length,e+t.length+28),s=Ke(r),a=/^(?:\s+)?(?:未发现|不存在|并不存在|未被发现)/.test(i)||/^(?:\s+)?(?:was\s+|is\s+)?not found\b/i.test(i);return s||a?true:o==="high"?/(?:未发现|没有发现|不存在|无证据(?:表明|证明)?)\s*(?:任何|明确的)?\s*P0\s*(?:或|和|及|、)\s*$/i.test(r)||/\b(?:no evidence (?:of|for)|no)\s+P0\s+(?:or|and)\s+$/i.test(r):false}function Ke(n){if(/(?:未发现|没有发现|不存在|无证据(?:表明|证明)?|不是|并非|未被)\s*(?:任何|明确的)?\s*(?:(?:问题|发现|证据|项|内容)\s*)?(?:(?:属于|(?:被)?(?:评|判定|认定|标记|列|视|定|归(?:类)?)为)\s*)?$/i.test(n)||/\b(?:no evidence (?:of|for)|no|not|isn't|is\s+not)\s+(?:an?\s+)?(?:(?:issues?|findings?|evidence|items?)\s+)?(?:(?:classified|rated|marked|labelled|labeled)(?:\s+as)?\s+)?$/i.test(n))return true;let t=/(?:不得|不能|不应|不宜|不要)\s*(?:被\s*)?(?:(?:直接|轻易|简单|明确|正式|合理|据此|当前|目前)\s*){0,2}(?:(?:评|判定|认定|标记|列|视|定|归(?:类)?)为|属于)\s*$/i,o=/\b(?:cannot|can't|must not|should not|shouldn't|do not|don't)\s+(?:(?:reasonably|directly|formally|currently)\s+){0,2}(?:be\s+)?(?:classified|labeled|labelled|rated|marked)(?:\s+as)?\s+$/i;return t.test(n)||o.test(n)}function Xe(n,e,t){let o=n.slice(Math.max(0,e-40),e),r=n.slice(e+t.length,e+t.length+32),i=/(?:是否|待验证|候选|可能|潜在|未观察到|没有观察到|未发现|不存在|无证据(?:表明)?|不能(?:据此)?确认|尚未(?:确认|证明)|验证(?:是否)?|测量(?:是否)?|采集|记录|收集).{0,16}$/i.test(o)||/\b(?:whether|measure|validate|candidate|potential|possible|may|might|no|no evidence(?: of| for)?|not observed|unobserved|collect|record).{0,18}$/i.test(o),s=/^(?:是否|有待验证|待验证|候选|可能|潜在|指标|需要(?:验证|测量)|需(?:验证|测量))/.test(r)||/^(?:\s+)?(?:candidate|potential|possible|metric|metrics|to (?:measure|validate)|needs? (?:measurement|validation)|is (?:a )?(?:candidate|potential))/i.test(r);return i||s}function Ye(n){return n.split(/(?:[。!?;;,,]|\b(?:but|however|yet|nevertheless|nonetheless)\b|但是|但|然而|却|不过|可是)/i).map(e=>e.trim()).filter(Boolean)}function oe(n,e){if(!n||n.length>4096)return {degradationReason:"transcript_path_missing"};let t;try{let o=lstatSync(n);if(!o.isFile()||o.isSymbolicLink())return {degradationReason:"transcript_path_unsafe"};t=openSync(n,constants.O_RDONLY|(constants.O_NOFOLLOW??0));let r=fstatSync(t);if(!r.isFile()||r.dev!==o.dev||r.ino!==o.ino)return {degradationReason:"transcript_path_changed"};let i=Math.min(r.size,ze),s=Buffer.alloc(i),a=0;for(;a<i;){let p=readSync(t,s,a,i-a,r.size-i+a);if(p===0)break;a+=p;}let c=s.subarray(0,a).toString("utf8");r.size>i&&(c=c.slice(Math.max(0,c.indexOf(`
9
+ `)+1)));let d=c.split(/\r?\n/).slice(-He),l=e.length>0?Math.min(...e.map(p=>p.promptedAt)):0,u=Qe(d,l),g=[...u].reverse().find(p=>Ze(p.text,e))??u.at(-1);return g?.text?{answer:g.text,fingerprint:g.fingerprint}:{degradationReason:"transcript_answer_unavailable"}}catch{return {degradationReason:"transcript_unreadable"}}finally{t!==void 0&&closeSync(t);}}function Ze(n,e){let t=new Set(e.flatMap(r=>r.contract.requiredSections)),o=re(ne(n.split(/\r?\n/u)).headingLines);return [...t].every(r=>o.found.has(r))}function M(n){return oe(n,[]).answer}function Qe(n,e){let t=[];for(let o=0;o<n.length;o++){let r=n[o];if(r.trim())try{let i=JSON.parse(r),s=i.message;if(!s||typeof s!="object"||s.role!=="assistant")continue;let a=s,c=et(i.timestamp);if(c>0&&c+5e3<e)continue;let d=s.content,l=typeof d=="string"?d:Array.isArray(d)?d.filter(u=>u&&typeof u=="object"&&u.type==="text").map(u=>u.text).filter(u=>typeof u=="string").join(`
10
+ `):"";if(l.trim()){let u=l.trim(),m=typeof a.id=="string"&&a.id?`message:${a.id}`:typeof i.uuid=="string"&&i.uuid?`uuid:${i.uuid}`:`record:${String(i.timestamp??"")}:${o}:${createHash("sha256").update(r).digest("hex")}`,g=createHash("sha256").update(u).digest("hex"),p=createHash("sha256").update(`${m}\0${g}`).digest("hex");t.push({text:u,timestamp:c,fingerprint:p});}}catch{continue}}return t}function et(n){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n!="string")return 0;let e=Date.parse(n);return Number.isFinite(e)?e:0}function re(n){let e=new Set,t=new Map,o;for(let r=0;r<n.length;r++){let i=n[r].trim().replace(/^#{1,6}\s*/,"").replace(/^\*\*(.*)\*\*$/,"$1").replace(/^(?:[一二三123][、..]\s*)/,"").replace(/[::]\s*$/,"").trim(),s=Ue.find(a=>i===a);s&&(o=s,e.add(s)),t.set(r,o);}return {found:e,byLine:t}}function ie(n){let e={committed:0,skipped:0,pending:0},t=[];for(let o of n)e[o.status]+=1,o.receiptId&&t.push(o.receiptId);return {memoryReceiptIds:[...new Set(t)],missingMemoryDecisionCount:e.pending,memoryTurnOutcomes:e}}function ot(n,e=v(),t=true,o,r=true){let i;try{i=JSON.parse(n);}catch{return null}let s=i.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${e}\0${s}`).digest("hex").slice(0,24)}`,c={inputJson:n,sessionId:s,cleanupSharedState:t,executionId:o},d;try{d=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let l=d.requestSessionClosure({receiptId:a,projectRoot:e,sessionId:s,payload:c}),u=d.getWorkByIdempotencyKey(a);return {status:l.state==="closed"||l.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:u?.state??"pending",closureState:l.state,pendingWorkCount:l.pendingWorkCount}}catch(l){if(!r)throw l;return Z(e,{receiptId:a,...c}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{d?.close();}}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 e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=ot(e.trim()||process.argv[2]||"");t&&n(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}var k=1,lt="memory-snapshot-v1.json",ut=512*1024,de=256*1024,le=2e3,mt=500,pt=10,ft=240,gt=300*1e3,yt=720*60*60*1e3,ht=2147483647;function bt(n){return n.currentUid===void 0?{ownerSafe:true,modeSafe:true}:{ownerSafe:n.ownerUid===n.currentUid,modeSafe:(n.mode&18)===0}}function b(n){return resolve(n)}function I(n){return createHash("sha256").update(b(n)).digest("hex").slice(0,16)}function vt(n,e={}){let t=I(n),o=e.stateRoot?join(e.stateRoot,t):getProjectStateDir(b(n));return join(o,lt)}function St(n,e){let o=(n instanceof Error?n.message:"").replace(/[\r\n\t]+/gu," ").trim().slice(0,160);return o?`${e}:${o}`:e}function D(n,e){return Array.isArray(n)&&n.length<=e&&n.every(t=>typeof t=="string"&&t.length>0&&t.length<=512)}function It(n){if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return typeof e.id=="string"&&e.id.length>0&&e.id.length<=512&&typeof e.kind=="string"&&e.kind.length>0&&e.kind.length<=128&&(e.family===void 0||typeof e.family=="string"&&e.family.length>0&&e.family.length<=256)&&(e.entity===void 0||typeof e.entity=="string"&&e.entity.length>0&&e.entity.length<=256)&&D(e.memoryIds,100)&&(e.status==="withheld"||e.status==="resolved")&&(e.summary===void 0||typeof e.summary=="string"&&e.summary.length<=2e3)}function wt(n){if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return typeof e.reason=="string"&&e.reason.length>0&&e.reason.length<=512&&(e.stale===void 0||typeof e.stale=="boolean")}function ue(n,e,t){if(!n||typeof n!="object"||Array.isArray(n))return null;let o=n,r=b(e),i=I(r),s=o.generation===void 0?0:o.generation;return o.version!==k||o.projectRoot!==r||o.projectHash!==i||typeof o.markdown!="string"||Buffer.byteLength(o.markdown,"utf8")>de||!D(o.memoryIds,le)||!Array.isArray(o.conflicts)||o.conflicts.length>mt||!o.conflicts.every(It)||typeof o.generatedAt!="number"||!Number.isFinite(o.generatedAt)||o.generatedAt<0||o.generatedAt>t+gt||!Number.isInteger(s)||s<0||s>ht||!["ready","pending","degraded","disabled"].includes(String(o.status))||o.degradation!==void 0&&!wt(o.degradation)?null:{...o,generation:s}}function _t(n,e,t,o,r=0){let i=b(n);return {version:k,projectRoot:i,projectHash:I(i),markdown:"",memoryIds:[],conflicts:[],generatedAt:o,generation:r,status:e,degradation:{reason:t}}}function kt(n,e={}){let t=e.now??Date.now(),o=vt(n,e),r;try{r=openSync(o,constants.O_RDONLY|constants.O_NOFOLLOW);let i=fstatSync(r);if(!i.isFile()||i.size<=0||i.size>ut)throw new Error("cache_size_invalid");let s=bt({...typeof process.getuid=="function"?{currentUid:process.getuid()}:{},ownerUid:i.uid,mode:i.mode});if(!s.ownerSafe)throw new Error("cache_owner_invalid");if(!s.modeSafe)throw new Error("cache_permissions_unsafe");let a=JSON.parse(readFileSync(r,"utf8")),c=ue(a,n,t);if(!c)throw new Error("cache_schema_invalid");return c.status==="ready"&&t-c.generatedAt>yt?{snapshot:{...c,status:"degraded",degradation:{reason:"cache_stale",stale:!0}},source:"cache",valid:!0,stale:!0}:{snapshot:c,source:"cache",valid:!0,stale:!1}}catch(i){let a=i.code==="ENOENT";return {snapshot:_t(n,a?"pending":"degraded",a?"cache_missing":St(i,"cache_invalid"),t),source:"none",valid:false,stale:false}}finally{if(r!==void 0)try{closeSync(r);}catch{}}}function Rt(n){if(!n)return true;try{return JSON.parse(readFileSync(n,"utf8")).sessionStart?.injectMemories??!0}catch{return true}}function Et(n,e,t){if(!e.trim())return null;try{let o=JSON.parse(e);if(o.status!=="ok"&&o.status!=="degraded")return null;if(o.enabled===!1){let i=b(n);return {version:k,projectRoot:i,projectHash:I(i),markdown:"",memoryIds:[],conflicts:[],generatedAt:t,generation:0,status:"disabled"}}let r=ue(o.snapshot,n,t);if(r)return r;if(o.status==="ok"&&typeof o.markdown=="string"&&o.markdown.length>0&&Buffer.byteLength(o.markdown,"utf8")<=de){let i=b(n);return {version:k,projectRoot:i,projectHash:I(i),markdown:o.markdown,memoryIds:D(o.memoryIds,le)?o.memoryIds:[],conflicts:[],generatedAt:t,generation:0,status:"ready"}}}catch{}return null}function O(n,e){return [...(n??e).replace(/[\r\n\t|]+/gu," ").trim()||e].slice(0,ft).join("")}function xt(n){if(n.length===0)return "";let e=n.slice(0,pt),t=e.map(o=>{let r=O(o.family,"unknown"),i=O(o.entity,"unknown"),s=O(o.summary,"Explicit choice required.");return `- family=${r}; entity=${i}; status=${o.status}; summary=${s}`});return n.length>e.length&&t.push(`- ${n.length-e.length} additional conflict(s) omitted from SessionStart output.`),`## Withheld preference conflicts (${n.length})
11
11
  ${t.join(`
12
- `)}`}function Ct(n){let e=n.now??Date.now();if(Rt(n.configPath)===false)return "";let t=Et(n.projectRoot,n.daemonResponse??"",e),r=t?{snapshot:t,source:"daemon"}:kt(n.projectRoot,{...n.cacheOptions,now:e}),{snapshot:o}=r;if(o.status==="disabled")return `## Project memory
13
- DevFlow memory snapshot=pending; source=${r.source}; reason=previous_snapshot_disabled. Memory availability is not yet known; do not conclude that the project has no memories.`;let i=new Date(o.generatedAt).toISOString(),s=o.degradation?.reason?`; reason=${o.degradation.reason}`:"",a=`DevFlow memory snapshot=${o.status}; source=${r.source}; generatedAt=${i}${s}.`,c=xt(o.conflicts);return o.markdown?[o.markdown,c,a].filter(Boolean).join(`
12
+ `)}`}function Ct(n){let e=n.now??Date.now();if(Rt(n.configPath)===false)return "";let t=Et(n.projectRoot,n.daemonResponse??"",e),o=t?{snapshot:t,source:"daemon"}:kt(n.projectRoot,{...n.cacheOptions,now:e}),{snapshot:r}=o;if(r.status==="disabled")return `## Project memory
13
+ DevFlow memory snapshot=pending; source=${o.source}; reason=previous_snapshot_disabled. Memory availability is not yet known; do not conclude that the project has no memories.`;let i=new Date(r.generatedAt).toISOString(),s=r.degradation?.reason?`; reason=${r.degradation.reason}`:"",a=`DevFlow memory snapshot=${r.status}; source=${o.source}; generatedAt=${i}${s}.`,c=xt(r.conflicts);return r.markdown?[r.markdown,c,a].filter(Boolean).join(`
14
14
  `):["## Project memory",c,`${a} Memory availability is not yet known; do not conclude that the project has no memories.`].filter(Boolean).join(`
15
- `)}if(process.env.DEVFLOW_MEMORY_SNAPSHOT_CLI==="1"){let[,,n,e,t]=process.argv;n!=="session-start"||!e?process.exitCode=2:process.stdout.write(Ct({projectRoot:e,configPath:t,daemonResponse:process.env.DEVFLOW_MEMORY_RESPONSE}));}function me(n){return `DevFlow memory decision required for ${n.turnId}. Before the final response, semantically decide whether this turn contains durable project knowledge. Call mcp__devflow__memory_commit_turn with evidence-bound candidates, or mcp__devflow__memory_skip_turn with a concrete reason. Do not claim memory success without a canonical receipt. For candidates, preserve exact package names, flags, versions, paths, and identifiers; provide subject, predicate, value, polarity, and entities when known. Do not save assistant echoes, task narration, retries, or unverified guesses. Express a change from an old choice as the new durable value. If the decision tool remains unavailable, explicitly state that the memory was not saved.`}function pe(n){let e=te({projectRoot:n.projectRoot,sessionId:n.sessionId,transcriptPath:n.transcriptPath,runtimeStore:n.runtimeStore}),t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});try{Dt(n.runtimeStore,n.sessionId,t);let r=t.getPendingMemoryTurn(n.projectRoot,n.sessionId),o=r?t.markMemoryTurnStopPrompted(r.turnId):!1,i=[];e&&i.push(e.reason),r&&o&&i.push(me(r)),r&&!o&&At(t,r.turnId)&&Ot(A(n.transcriptPath))&&i.push(`DevFlow explicit memory ${r.turnId} still has no canonical receipt. Remove the memory-success claim and tell the user that the memory was not saved, or complete the pending turn.`);let a=t.listSessionObligations(n.projectRoot,n.sessionId,["open"]).map(c=>({obligationId:c.obligationId,kind:c.kind,action:c.kind==="memory_decision"?"Call mcp__devflow__memory_decide_turn using the canonical turn ID.":c.kind==="evidence_contract"?"Return a final answer that satisfies the canonical evidence contract.":"Allow SessionEnd durable finalization to complete.",canonicalInput:c.kind==="memory_decision"&&c.turnId?{turnId:c.turnId}:void 0}));return i.length>0?{decision:"block_once",unresolved:a,additionalContext:["DevFlow has unresolved terminal obligations. Complete all actions below before stopping.",...i].join(`
15
+ `)}if(process.env.DEVFLOW_MEMORY_SNAPSHOT_CLI==="1"){let[,,n,e,t]=process.argv;n!=="session-start"||!e?process.exitCode=2:process.stdout.write(Ct({projectRoot:e,configPath:t,daemonResponse:process.env.DEVFLOW_MEMORY_RESPONSE}));}function me(n){return `DevFlow memory decision required for ${n.turnId}. Before the final response, semantically decide whether this turn contains durable project knowledge. Call mcp__devflow__memory_commit_turn with evidence-bound candidates, or mcp__devflow__memory_skip_turn with a concrete reason. Do not claim memory success without a canonical receipt. For candidates, preserve exact package names, flags, versions, paths, and identifiers; provide subject, predicate, value, polarity, and entities when known. Do not save assistant echoes, task narration, retries, or unverified guesses. Express a change from an old choice as the new durable value. If the decision tool remains unavailable, explicitly state that the memory was not saved.`}function pe(n){let e=te({projectRoot:n.projectRoot,sessionId:n.sessionId,transcriptPath:n.transcriptPath,runtimeStore:n.runtimeStore}),t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});try{Dt(n.runtimeStore,n.sessionId,t);let o=t.getPendingMemoryTurn(n.projectRoot,n.sessionId),r=o?t.markMemoryTurnStopPrompted(o.turnId):!1,i=[];e&&i.push(e.reason),o&&r&&i.push(me(o)),o&&!r&&Mt(t,o.turnId)&&Ot(M(n.transcriptPath))&&i.push(`DevFlow explicit memory ${o.turnId} still has no canonical receipt. Remove the memory-success claim and tell the user that the memory was not saved, or complete the pending turn.`);let a=t.listSessionObligations(n.projectRoot,n.sessionId,["open"]).map(c=>({obligationId:c.obligationId,kind:c.kind,action:c.kind==="memory_decision"?"Call mcp__devflow__memory_decide_turn using the canonical turn ID.":c.kind==="evidence_contract"?c.payload.subtype==="policy_verification"?`Complete the required project verification: ${String(c.payload.command??c.payload.verificationKind??"unknown command")}.`:"Return a final answer that satisfies the canonical evidence contract.":"Allow SessionEnd durable finalization to complete.",canonicalInput:c.kind==="memory_decision"&&c.turnId?{turnId:c.turnId}:void 0}));return i.length>0?{decision:"block_once",unresolved:a,additionalContext:["DevFlow has unresolved terminal obligations. Complete all actions below before stopping.",...i].join(`
16
16
 
17
- `)}:a.length>0?{decision:"degrade",unresolved:a,additionalContext:"DevFlow terminal obligations remain unresolved after their one-shot correction budget."}:{decision:"allow",unresolved:[]}}finally{t.close();}}function At(n,e){return !!n.getWorkByIdempotencyKey(`memory-turn:commit_explicit:${e}`)}function Ot(n){if(!n)return false;let e=n.normalize("NFKC").replace(/\s+/gu," ");return /(?:未|没有|无法|失败|暂未|尚未).{0,24}(?:记住|记下|记录|保存|持久化|回执)|(?:memory|receipt).{0,24}(?:failed|missing|pending|degraded|not saved)|status=(?:pending|degraded|rejected|failed)/iu.test(e)?false:/(?:已|已经|成功).{0,20}(?:记住|记下|记录|保存|持久化)|跨会话生效|(?:memory|preference).{0,20}(?:saved|remembered|persisted)|status=(?:accepted|committed)/iu.test(e)}function Dt(n,e,t){let r=n.get(e);if(r){for(let o of r.evidenceObligations)t.upsertSessionObligation({obligationId:`evidence:${o.obligationId}`,projectRoot:r.projectRoot,sessionId:e,executionId:r.executionId,kind:"evidence_contract",state:"open",payload:{contract:o.contract,runtimeObligationId:o.obligationId},createdAt:o.promptedAt,updatedAt:r.lastActivityAt});for(let o of r.evidenceOutcomes){let i=`evidence:${o.obligationId}`,s=t.getSessionObligation(r.projectRoot,e,i);!s||s.state!=="open"||t.resolveSessionObligation({projectRoot:r.projectRoot,sessionId:e,obligationId:i,state:o.status==="resolved"?"satisfied":"degraded",reason:o.reason,resolvedAt:o.completedAt});}}}async function $t(n,e=v()){let t;try{t=JSON.parse(n);}catch{return null}let r=t.session_id?.trim();if(!r)return null;let o=new y(e),i=pe({projectRoot:e,sessionId:r,transcriptPath:t.transcript_path,stopHookActive:t.stop_hook_active===true,runtimeStore:o});if(i.decision==="block_once")return {decision:"block",reason:i.additionalContext};let s=o.completeExecution(r);if(s?.executionId){let a=openGlobalDevFlowDatabase();try{let c=a.listSessionMemoryTurnsForReconciliation(e,r);a.reconcileSkillExecution(s.executionId,"completed",Date.now(),{...ie(c),evidenceDegradations:s.evidenceDegradations,evidenceContractOutcomes:s.evidenceOutcomes,unresolvedObligations:i.unresolved,terminalState:i.decision}),a.deleteContextReceipt(e,r,s.executionId);}finally{a.close();}}return _(`/api/telemetry/sessions/${encodeURIComponent(r)}/tick`,{timestamp:Date.now()},{fallbackReason:"stop_tick_already_local"}),null}if(process.argv[1]?.endsWith("stop")||process.argv[1]?.endsWith("stop.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=await $t(e.trim()||process.argv[2]||"");t&&n(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),4e3).unref();}export{$t as handleStop};
17
+ `)}:a.length>0?{decision:"degrade",unresolved:a,additionalContext:"DevFlow terminal obligations remain unresolved after their one-shot correction budget."}:{decision:"allow",unresolved:[]}}finally{t.close();}}function Mt(n,e){return !!n.getWorkByIdempotencyKey(`memory-turn:commit_explicit:${e}`)}function Ot(n){if(!n)return false;let e=n.normalize("NFKC").replace(/\s+/gu," ");return /(?:未|没有|无法|失败|暂未|尚未).{0,24}(?:记住|记下|记录|保存|持久化|回执)|(?:memory|receipt).{0,24}(?:failed|missing|pending|degraded|not saved)|status=(?:pending|degraded|rejected|failed)/iu.test(e)?false:/(?:已|已经|成功).{0,20}(?:记住|记下|记录|保存|持久化)|跨会话生效|(?:memory|preference).{0,20}(?:saved|remembered|persisted)|status=(?:accepted|committed)/iu.test(e)}function Dt(n,e,t){let o=n.get(e);if(o){for(let r of o.evidenceObligations)t.upsertSessionObligation({obligationId:`evidence:${r.obligationId}`,projectRoot:o.projectRoot,sessionId:e,executionId:o.executionId,kind:"evidence_contract",state:"open",payload:{contract:r.contract,runtimeObligationId:r.obligationId},createdAt:r.promptedAt,updatedAt:o.lastActivityAt});for(let r of o.evidenceOutcomes){let i=`evidence:${r.obligationId}`,s=t.getSessionObligation(o.projectRoot,e,i);!s||s.state!=="open"||t.resolveSessionObligation({projectRoot:o.projectRoot,sessionId:e,obligationId:i,state:r.status==="resolved"?"satisfied":"degraded",reason:r.reason,resolvedAt:r.completedAt});}}}async function $t(n,e=v()){let t;try{t=JSON.parse(n);}catch{return null}let o=t.session_id?.trim();if(!o)return null;let r=new y(e),i=pe({projectRoot:e,sessionId:o,transcriptPath:t.transcript_path,stopHookActive:t.stop_hook_active===true,runtimeStore:r});if(i.decision==="block_once")return {decision:"block",reason:i.additionalContext};let s=r.completeExecution(o);if(s?.executionId){let a=openGlobalDevFlowDatabase();try{let c=a.listSessionMemoryTurnsForReconciliation(e,o);a.reconcileSkillExecution(s.executionId,"completed",Date.now(),{...ie(c),evidenceDegradations:s.evidenceDegradations,evidenceContractOutcomes:s.evidenceOutcomes,unresolvedObligations:i.unresolved,terminalState:i.decision}),a.deleteContextReceipt(e,o,s.executionId);}finally{a.close();}}return _(`/api/telemetry/sessions/${encodeURIComponent(o)}/tick`,{timestamp:Date.now()},{fallbackReason:"stop_tick_already_local"}),null}if(process.argv[1]?.endsWith("stop")||process.argv[1]?.endsWith("stop.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=await $t(e.trim()||process.argv[2]||"");t&&n(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),4e3).unref();}export{$t as handleStop};