@devflow-tools/cli 0.17.8 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/commands/context.d.ts +1 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +8 -2
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/db.js +1 -1
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +2 -0
- package/dist/commands/docs.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +34 -44
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/graph.js +1 -1
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/index-cmd.js +1 -1
- package/dist/commands/index-cmd.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +2 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/knowledge.d.ts +1 -1
- package/dist/commands/knowledge.d.ts.map +1 -1
- package/dist/commands/knowledge.js +21 -5
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/logs.d.ts +14 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +40 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/memory.d.ts.map +1 -1
- package/dist/commands/memory.js +3 -2
- package/dist/commands/memory.js.map +1 -1
- package/dist/commands/plugin-memory-hints.js +3 -0
- package/dist/commands/plugin-memory-hints.js.map +1 -1
- package/dist/commands/workflow.js +1 -1
- package/dist/commands/workflow.js.map +1 -1
- package/dist/index.js +18 -2
- package/dist/index.js.map +1 -1
- package/dist/plugin-files/.claude-plugin/plugin.json +1 -1
- package/dist/plugin-files/dist/command-registry.json +5 -5
- package/dist/plugin-files/dist/hooks/enforcer-summary.js +3 -3
- package/dist/plugin-files/dist/hooks/hook-client.js +3 -3
- package/dist/plugin-files/dist/hooks/hook-daemon.js +27 -25
- package/dist/plugin-files/dist/hooks/post-tool-use-failure.js +2 -2
- package/dist/plugin-files/dist/hooks/post-tool-use.js +6 -6
- package/dist/plugin-files/dist/hooks/pre-compact.js +3 -3
- package/dist/plugin-files/dist/hooks/pre-tool-use.js +4 -4
- package/dist/plugin-files/dist/hooks/server-bootstrap.js +22 -22
- package/dist/plugin-files/dist/hooks/session-end.js +6 -6
- package/dist/plugin-files/dist/hooks/stop.js +10 -10
- package/dist/plugin-files/dist/hooks/user-prompt-submit.js +11 -9
- package/dist/plugin-files/package.json +28 -19
- package/package.json +39 -29
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {getLocalApiKey,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure}from'@devflow-tools/sdk';import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync}from'fs';import {join as join$1}from'path';import {
|
|
2
|
-
|
|
1
|
+
import {getLocalApiKey,getDevFlowStateRoot,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure}from'@devflow-tools/sdk';import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync}from'fs';import {join as join$1}from'path';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {request}from'node:http';import {existsSync as existsSync$1,mkdirSync as mkdirSync$1,appendFileSync}from'node:fs';import {join}from'node:path';import {rotateDiagnosticLogFile}from'@devflow-tools/telemetry';import {MemoryGate}from'@devflow-tools/memory-engine';import {createHash}from'node:crypto';function b(s){return s??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function p(s,r,e){try{let t=openGlobalDevFlowDatabase();try{t.insertEvent({kind:s,timestamp:Date.now(),duration:e,success:r.success!==!1,metadata:r});}finally{t.close();}}catch{}}var J=getLocalApiKey(),y=join(getDevFlowStateRoot(),"errors");async function k(s,r,e={}){let t=e.endpoint??resolveRuntimeEndpoint().url,o=e.timeout??1500,n=e.durableMirror??true,i=e.maxRetries??(n?0:2),a=e.circuitBreaker??true,c=acquireRuntimeHttpCircuit(t,s);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let d;for(let l=0;l<=i;l+=1)try{return await W(t,s,r,o),a&®isterRuntimeHttpSuccess(t,s).transitioned&&p("http_circuit_transition",{endpoint:t,path:new URL(s,t).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(m){d=m instanceof Error?m:new Error(String(m)),l<i&&await B(Math.min(100*2**l,1e3));}if(!d)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return w(s,d),{delivered:false,suppressed:false,fallbackReason:d.message};let u=registerRuntimeHttpFailure(t,s,e.fallbackReason??(n?"local_durable_mirror":"http_delivery_failed"));return u.transitioned&&(w(s,d),p("http_circuit_transition",{endpoint:t,path:new URL(s,t).pathname,previous:c.state.status,status:"open",failures:u.state.failures,openUntil:u.state.openUntil,fallbackReason:u.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:u.state.fallbackReason}}function W(s,r,e,t){return new Promise((o,n)=>{let i=JSON.stringify(e),a=new URL(r,s),c=false,d=l=>{c||(c=true,l?n(l):o());},u=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":J,"Content-Length":Buffer.byteLength(i)},timeout:t},l=>{l.on("error",d),l.on("end",()=>{let m=l.statusCode??0;d(m>=200&&m<300?void 0:new Error(`HTTP ${m}`));}),l.resume();});u.on("error",d),u.on("timeout",()=>u.destroy(new Error(`HTTP mirror timed out after ${t}ms`))),u.write(i),u.end();})}function w(s,r){try{existsSync$1(y)||mkdirSync$1(y,{recursive:!0});let e=join(y,"http-errors.log"),t=`${new Date().toISOString()} | ${s} | ${r.message}
|
|
2
|
+
`;rotateDiagnosticLogFile({path:e,maxBytes:50*1024*1024,maxFiles:5,incomingBytes:Buffer.byteLength(t)}),appendFileSync(e,t);}catch{}}function B(s){return new Promise(r=>setTimeout(r,s))}var C=1e4,Z=3e4,f=500,h=class{constructor(r){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=r?.apiUrl,this.cacheDir=r?.cacheDir??join$1(getDevFlowStateRoot(),"global","telemetry-cache"),this.database=r?.database??null,this.ownsDatabase=!r?.database;let e=r?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}async sendEvent(r){let e={...r,input:this.truncateInput(r.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),r.eventId):null}async sendExecutionStart(r,e,t,o,n=process.env.CLAUDE_PROJECT_DIR??process.cwd(),i=[]){let a={executionId:r,sessionId:e,skillName:t,startedAt:o,projectRoot:n,requiredMcpTools:i};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(r,e="completed",t=Date.now(),o){let n={executionId:r,status:e,finishedAt:t,metadata:o},i=this.commitOrCache("execution_complete",n);return i&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",n),i}async sendSessionStart(r,e,t){let o={id:r,projectRoot:e,startedAt:t,label:e.split("/").pop()??"unknown"},n=this.commitOrCache("session_start",o);return n&&this.postHttp("/api/telemetry/sessions",o),n}async completeEvent(r){let e=this.commitOrCache("complete_event",r);return e&&(this.postHttp("/api/telemetry/tool-call/output",r),this.scheduleMetricAggregation()),e}async endSession(r,e=Date.now()){let t={sessionId:r,finishedAt:e},o=this.commitOrCache("session_end",t);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(r)}/close`,{finishedAt:e})),o}async flushCache(){try{let e=this.getDatabase(),t=e.listTelemetryFailures({unresolvedOnly:!0,limit:f}).reverse();for(let o of t)try{this.applyOperation(o.operation,o.payload),e.resolveTelemetryFailure(o.id);}catch{}e.trimTelemetryFailures(f);}catch{}let r=(existsSync(this.cacheDir)?readdirSync(this.cacheDir):[]).filter(e=>e.endsWith(".json")).map(e=>{let t=join$1(this.cacheDir,e);try{return {cacheFile:t,envelope:Q(JSON.parse(readFileSync(t,"utf8")))}}catch{return null}}).filter(e=>e!==null).sort((e,t)=>e.envelope.timestamp-t.envelope.timestamp||O(e.envelope.operation)-O(t.envelope.operation));for(let{cacheFile:e,envelope:t}of r)try{let o=this.getDatabase();o.insertTelemetryFailure({id:t.id,operation:t.operation,payload:t.payload,error:t.failure,createdAt:t.timestamp}),this.applyOperation(t.operation,t.payload),o.resolveTelemetryFailure(t.id),unlinkSync(e);}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(r,e){try{return this.applyOperation(r,e),!0}catch(t){return this.cacheOperation(r,e,t),false}}applyOperation(r,e){let t=this.getDatabase();switch(r){case "tool_call":this.ensureParentSession(t,e),t.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(t,e),t.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":t.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":t.ensureSession(e),t.insertRun({id:x(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(!t.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":t.closeSession(e.sessionId,e.finishedAt),t.updateRun(x(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(r,e){let t=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!t)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";r.ensureSession({id:t,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(r,e,t){let o=Date.now(),n={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:r,payload:e,failure:t instanceof Error?t.message:String(t),timestamp:o};try{let i=this.getDatabase();i.insertTelemetryFailure({id:n.id,operation:r,payload:e,error:n.failure,createdAt:o}),i.trimTelemetryFailures(f),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let i=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(i,JSON.stringify(n,null,2),{mode:384}),this.trimRetryCache(),this.scheduleRetry();}catch{}}trimRetryCache(){try{let r=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of r.slice(0,Math.max(0,r.length-f)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},Z).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(r,e){k(r,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(r){let e=JSON.stringify(r);return e===void 0||e.length<=C?r:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,C)}...`}}};function O(s){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(s)}function x(s){return `hook-run:${s}`}function Q(s){if(!s||typeof s!="object")throw new Error("Invalid telemetry cache envelope");let r=s;if(typeof r.id!="string"||typeof r.operation!="string"||r.payload===void 0||typeof r.failure!="string"||typeof r.timestamp!="number")throw new Error("Invalid telemetry cache envelope");return r}async function M(s){let r=!s.memory,e=s.memory??new MemoryGate(s.projectRoot),t=0,o=0;try{await e.forceWarmUp(),s.trigger==="session_end"&&(t=await e.releasePendingDistillLeases(s.sessionId)),o=e.getPendingEventCount(s.sessionId,s.trigger!=="session_end");}finally{r&&e.close();}let n=Date.now(),i=s.trigger==="session_end"&&s.sessionId?`distill:session_end:${createHash("sha256").update(`${s.projectRoot}\0${s.sessionId}`).digest("hex").slice(0,24)}`:`distill:${n}:${Math.random().toString(36).slice(2,10)}`,a={id:i,pendingEvents:o,releasedLeases:t,trigger:s.trigger,sessionId:s.sessionId,details:s.details};try{let c=openGlobalDevFlowDatabase();try{c.recordMemoryDistillCheckpoint({id:i,projectRoot:s.projectRoot,sessionId:s.sessionId,trigger:s.trigger,pendingEvents:o,releasedLeases:t,details:s.details,createdAt:n}),c.insertEvent({kind:"memory_distill_requested",timestamp:n,success:!0,metadata:{...a,projectRoot:s.projectRoot}});}finally{c.close();}}catch(c){if(s.strictPersistence)throw c}return a}function P(s){if(s.pendingEvents===0)return "";let r=s.sessionId?`\uFF0CsessionId=${s.sessionId}`:"";return `Memory distill checkpoint: ${s.pendingEvents} \u4E2A\u4E8B\u4EF6\u5F85\u63D0\u70BC${r}\u3002\u4E0A\u4E0B\u6587\u538B\u7F29\u5B8C\u6210\u540E\uFF0C\u8C03\u7528 mcp__devflow__memory_request_distill\uFF1B\u6309\u8FD4\u56DE\u7684 nextPage \u5206\u9875\u8BFB\u53D6\u5168\u90E8\u4E8B\u4EF6\uFF0C\u63D0\u70BC observations\uFF0C\u518D\u8C03\u7528 mcp__devflow__memory_save_distilled \u5E76\u786E\u8BA4\u4FDD\u5B58\u7ED3\u679C\u3002`}var A="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function F(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}async function se(s="",r=b()){let e;try{let i=JSON.parse(s);typeof i.session_id=="string"&&i.session_id.trim()&&(e=i.session_id.trim());}catch{}let t=new h;try{await t.flushAndAggregate();}finally{t.close();}let o=await M({projectRoot:r,sessionId:e,trigger:"pre_compact"}),n=[F()?A:"",P(o)].filter(Boolean).join(`
|
|
3
3
|
|
|
4
|
-
`);return {hookSpecificOutput:{hookEventName:"PreCompact",...n?{additionalContext:n}:{}}}}if(process.argv[1]?.endsWith("pre-compact")||process.argv[1]?.endsWith("pre-compact.js")){let s=console.log,r=console.info,e=()=>{console.log=s,console.info=r;};console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",o=>{t+=o;}),process.stdin.on("end",()=>{
|
|
4
|
+
`);return {hookSpecificOutput:{hookEventName:"PreCompact",...n?{additionalContext:n}:{}}}}if(process.argv[1]?.endsWith("pre-compact")||process.argv[1]?.endsWith("pre-compact.js")){let s=console.log,r=console.info,e=()=>{console.log=s,console.info=r;};console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",o=>{t+=o;}),process.stdin.on("end",()=>{se(t.trim()||process.argv[2]||"").then(o=>{e(),s(JSON.stringify(o)),process.exit(0);}).catch(()=>{e(),process.exit(0);});}),process.stdin.on("error",()=>{e(),process.exit(0);}),setTimeout(()=>process.exit(0),14e3).unref();}export{se as handlePreCompact};
|
|
@@ -1,4 +1,4 @@
|
|
|
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 {
|
|
2
|
-
`);}catch{}}function dt(n){return new Promise(t=>setTimeout(t,n))}var ce=1e4,mt=3e4,k=500,A=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,o,i,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:o,startedAt:i,projectRoot:r,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",o=Date.now(),i){let r={executionId:t,status:e,finishedAt:o,metadata:i},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(t,e,o){let i={id:t,projectRoot:e,startedAt:o,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 o={sessionId:t,finishedAt:e},i=this.commitOrCache("session_end",o);return i&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),i}async flushCache(){try{let o=this.getDatabase(),i=o.listTelemetryFailures({unresolvedOnly:!0,limit:k}).reverse();for(let r of i)try{this.applyOperation(r.operation,r.payload),o.resolveTelemetryFailure(r.id);}catch{}o.trimTelemetryFailures(k);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(o=>!!o))].filter(o=>existsSync(o)).flatMap(o=>readdirSync(o).filter(i=>i.endsWith(".json")).map(i=>{let r=join$1(o,i);try{return {cacheFile:r,envelope:ht(JSON.parse(readFileSync(r,"utf8")),i)}}catch{return null}})).filter(o=>o!==null).sort((o,i)=>o.envelope.timestamp-i.envelope.timestamp||le(o.envelope.operation)-le(i.envelope.operation));for(let{cacheFile:o,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(o);}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(o){return this.cacheOperation(t,e,o),false}}applyOperation(t,e){let o=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(o,e),o.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(o,e),o.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":o.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":o.ensureSession(e),o.insertRun({id:de(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(!o.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":o.closeSession(e.sessionId,e.finishedAt),o.updateRun(de(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let o=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!o)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:o,projectRoot:i,label:i==="unknown"?void 0:i.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,o){let i=Date.now(),r={id:`failure:${i}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:o instanceof Error?o.message:String(o),timestamp:i};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:i}),s.trimTelemetryFailures(k),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-k)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},mt).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){oe(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ce?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ce)}...`}}};function le(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function de(n){return `hook-run:${n}`}function ht(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 o=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!o)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:o,payload:i,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:r}}function N(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function f(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(N(n))}var Et=2,Dt=1;function It(){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 ue(n=It()){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 o=JSON.parse(readFileSync(e,"utf8"));if(o.version!==Et&&o.version!==Dt||!xt(o.commands)){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:"contract_mismatch",registryPath:e}});continue}return o.commands}catch(o){emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:o.message,fallback:"next_registry_candidate"}});}return null}function xt(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 C(e.mcpTools)&&C(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||C(e.runtimePackages))&&(e.hostTools===void 0||wt(e.hostTools))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function wt(n){return !!n&&typeof n=="object"&&!Array.isArray(n)&&Object.entries(n).every(([t,e])=>t.length>0&&C(e))}function C(n){return Array.isArray(n)&&n.every(t=>typeof t=="string"&&t.length>0)}function pe(n){let t=ue();return t?t[n]?.mcpTools??[]:[]}function D(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let t=n,e={};for(let o of ["lastMcpCall","bypassCount"])if(o in t){let i=t[o];if(i==null)continue;e[o]=typeof i=="number"&&Number.isFinite(i)&&i>=0?i:0;}return e}function kt(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function At(n){try{return existsSync(n)?D(JSON.parse(readFileSync(n,"utf-8"))):{}}catch{return {}}}function me(n,t,e){let o=e instanceof Error?e.message:String(e);emitSemanticControlLog({event:"hook.runtime.degraded",identity:{projectRoot:n},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:o,fallback:"fail_open"}});}function ge(n){let t=f(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 he(n,t){if(n.getHookReceipt(t)){ge(t);return}let e=join$1(f(t),"receipt.json");if(!existsSync(e))return;let o=At(e);n.updateHookReceipt(t,()=>o),ge(t);}function ye(n,t,e){let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),he(o,n);let i={},r=o.updateHookReceipt(n,a=>(i=D(a),D(t(i)))),s=D(r);return {receipt:s,applied:!0,changed:!kt(i,s)}}catch(i){return me(n,e,i),{receipt:{},applied:false,changed:false}}finally{try{o?.close();}catch{}}}function ve(n){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),he(t,n),D(t.getHookReceipt(n))}catch(e){return me("update",e),{}}finally{try{t?.close();}catch{}}}function Ct(n,t){return ye(n,()=>t,"write").applied}function Tt(n,t){return ye(n,t,"update")}var fe={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},Ft=new Set(["Write","Edit","NotebookEdit"]),jt=new Set(["failed","timeout","unavailable"]);function Mt(n){switch(n){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var T=class{constructor(t,e,o){this.projectRoot=t;this.sessionId=e;this.executionId=o;}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 o=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(o==="context_gathering"&&fe[t])return {permissionDecision:"deny",reasonCode:"DEVFLOW_CONTEXT_REQUIRED",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(o==="context_ready"){if(Ft.has(t)){let l=this.evaluateRequiredAction();if(l)return l}return {permissionDecision:"allow"}}let i=fe[t];if(!i)return {permissionDecision:"allow"};let r=Tt(this.projectRoot,l=>({...l,bypassCount:(l.bypassCount??0)+1}));if(!r.applied)return {permissionDecision:"allow"};let s=r.receipt.bypassCount??0,a=Mt(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(){Ct(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(t,e,o,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(),l=i?.trim()?`${i.trim()}:${e}`:`${t}:${e}:${a}`,c=s.actionAttempts??[];return r.upsertContextReceipt({...s,actionAttempts:c.some(d=>d.id===l||i&&d.toolUseId===i&&d.status===e)?c:[...c,{id:l,tool:t,status:e,attemptedAt:a,toolUseId:i,reason:o?.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 o=e.binding;if(o.requiredContextReceipt!==t.contextHash||o.projectRoot!==this.projectRoot||o.sessionId!==this.sessionId||o.requestId!==t.requestId||o.executionId&&o.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&&jt.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 o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let i=o.getContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!i||i.contextHash!==t.contextHash||i.actionDegradation)return;o.upsertContextReceipt({...i,actionDegradation:e});let r=o.getSkillExecution(t.executionId);if(!r)return;let s=r.metadata&&typeof r.metadata=="object"?r.metadata:{},a=Array.isArray(s.requiredActionDegradations)?s.requiredActionDegradations:[];o.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{o?.close();}catch{}}}};var Wt=10*1024*1024,Bt=5;function Gt(n){return createHash$1("sha256").update(n).digest("hex").slice(0,16)}function Re(n){return join(homedir(),".devflow","logs","hook-debug",`${Gt(n)}.jsonl`)}function Ee(n,t,e={}){let o=e.maxBytes??Wt,i=e.maxFiles??Bt;mkdirSync$1(dirname(n),{recursive:true,mode:448});let r=Buffer.byteLength(t),s=existsSync$1(n)?statSync(n).size:0;s>0&&s+r>o&&Vt(n,i),appendFileSync(n,t,{mode:384}),chmodSync(n,384);}function Vt(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 o=`${n}.${e}`;existsSync$1(o)&&renameSync$1(o,`${n}.${e+1}`);}existsSync$1(n)&&renameSync$1(n,`${n}.1`);}var J="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function De(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function Se(n){return Buffer.from(n,"utf8").toString("base64url")}function Xt(n,t,e){let o=t?.trim();if(o){let i=/^[a-zA-Z0-9:._-]{1,192}$/.test(o)?o:`tool-${createHash("sha256").update(o.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${i}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function Fe(n){return `${n}:legacy-journal`}var j=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(f(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let o=this.get(e);if(o)return o.lastActivityAt=Date.now(),this.persist(o),o;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,o){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(o)],i.lastActivityAt=Date.now(),this.persist(i),i}bindTaskIdentity(t,e){let o=this.registerSession(t);return o.activeTurnId=e.turnId,o.activeRequestId=e.requestId,o.intentArtifactHash=e.intentArtifactHash,o.lastActivityAt=Date.now(),this.persist(o),o}get(t){let e=t.trim();if(!e)return null;let o=this.sessions.get(e);if(o)return this.replayEvidenceJournal(o),o;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=Oe(r.evidenceObligations),r.evidenceDegradations=ke(r.evidenceDegradations),r.evidenceOutcomes=Ae(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 o=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),o}addEvidenceObligation(t,e,o=Date.now(),i){let r=this.registerSession(t),a=(i?void 0:r.evidenceObligations.find(c=>c.contractId===e.id))?.obligationId??Xt(e.id,i,o);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:o,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let l=r.evidenceObligations.find(c=>c.obligationId===a);return l?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(l)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,o,i,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!a)return null;let l=/^[a-f0-9]{64}$/.test(i)?i:"";if(!l)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:l,violations:o.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${l}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let c=s.evidenceObligations.find(d=>d.obligationId===e);return c?structuredClone(c):null}resolveEvidenceObligation(t,e){let o=this.get(t);if(!o)return false;let i=o.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(o),o.lastActivityAt=r,this.persist(o),true}resolveDegradedEvidence(t,e){let o=this.get(t),i=o?.evidenceDegradations.find(s=>s.obligationId===e);if(!o||!i)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:i.contractId,at:r},`resolve-degraded\0${e}\0${r}`),this.replayEvidenceJournal(o),o.lastActivityAt=r,this.persist(o),true}degradeEvidenceObligation(t,e,o,i=Date.now()){let r=this.get(t),s=r?.evidenceObligations.find(l=>l.obligationId===e);if(!r||!s)return false;let a=o.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,`${Se(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Se(t))}appendEvidenceEvent(t,e,o){let i=this.evidenceJournalDir(t);mkdirSync(i,{recursive:true,mode:448});let r=createHash("sha256").update(o).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(l){if(l.code!=="EEXIST")throw l}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Oe(t.evidenceObligations),t.evidenceDegradations=ke(t.evidenceDegradations),t.evidenceOutcomes=Ae(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let o;try{o=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let i=o.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=Qt(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||Ce(r.kind)-Ce(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 o=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(o)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||o||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??o?.attempt??0;if(e.kind==="resolve"&&o?.status==="degraded")t.evidenceOutcomes=t.evidenceOutcomes.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations=t.evidenceDegradations.filter(s=>s.obligationId!==e.obligationId);else if(o)return;e.kind==="degrade"?(t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r,contract:i?.contract})):t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}});}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),o=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384}),renameSync(o,e);}};function Oe(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)||!je(e.contract))return [];let o=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Fe(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:o,correctionFingerprint:r}]}).slice(-8):[]}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"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function Ae(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(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 Qt(n){if(!n||typeof n!="object")return null;let t=n,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let i={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:Fe(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return je(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 Ce(n){return n==="add"?0:n==="correction"?1:2}function je(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,o=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(o)&&o.length<=16&&o.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 Me(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 Pe(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 nn=new Set(["Write","Edit","NotebookEdit"]),$e="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 qe(n){if(!nn.has(n.toolName))return null;let t=on(n.toolInput);if(!t)return null;let e=rn(t,n.projectRoot),o=resolve(n.projectRoot,".claude");if(Ne(e,o)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return $e;let i=resolve(n.home??homedir(),".claude","projects");return Ne(e,i)&&relative(i,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?$e:null}function on(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 rn(n,t){return resolve(isAbsolute(n)?n:resolve(t,n))}function Ne(n,t){let e=relative(t,n);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function Ge(n){let t=gn(n.toolName,n.toolInput),e=t?fn(n.projectRoot,n.toolName,n.toolInput):void 0;if(!t||!e||!n.toolUseId)return {allowed:true};let o=hn(e),i,r=0,s,a;try{a=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:100,readonly:!0});let c=a.getActiveContextReceipt(n.projectRoot,n.sessionId,n.executionId);i=c?.contextHash,r=c?.issuedAt??0,s=c?.canonicalAction?.binding.operationTargets?.find(d=>yn(n.projectRoot,d.path,e));}catch{}finally{try{a?.close();}catch{}}let l={toolUseId:n.toolUseId,sessionId:n.sessionId,executionId:n.executionId,operation:t,path:e,before:o,contextReceipt:i,observedAt:Date.now()};if(_n(n.projectRoot,l),t==="edit"||t==="write"||t==="delete"){let c=Rn(n.projectRoot,e),d=c?.success&&c.operation==="delete"&&!c.after.exists&&c.completedAt>=r,u=s?.expectedState==="existing"&&!o.exists||s?.expectedState==="missing"&&o.exists||!!(s?.contentHash&&o.hash!==s.contentHash);if(d||s?.expectedState==="existing"&&!o.exists)return Je(n,l,"DEVFLOW_FILE_STATE_DELETED","The target was deleted after the active Context receipt. Refresh project context before editing or recreating it.");if(u)return Je(n,l,"DEVFLOW_FILE_STATE_STALE","The target state no longer matches the active Context receipt. Refresh project context before overwriting it.")}return Ve(n,l,true),{allowed:true,pending:l}}function Je(n,t,e,o){return Ve(n,t,false,e),{allowed:false,reasonCode:e,reason:o,pending:t}}function Ve(n,t,e,o){emitSemanticControlLog({event:"canonical.action.validated",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:n.executionId,contextReceipt:t.contextReceipt},level:e?"info":"warn",timestamp:Date.now(),data:{stage:"host_file_state_precondition",valid:e,operation:t.operation,targetPath:relative(n.projectRoot,t.path),targetExists:t.before.exists,targetHash:t.before.hash,reason:o,toolUseId:t.toolUseId}});}function gn(n,t){if(n==="Read")return "read";if(n==="Edit"||n==="NotebookEdit")return "edit";if(n==="Write")return "write";if(n==="Delete"||n==="Bash"&&ze(t.command))return "delete"}function fn(n,t,e){let o=mn(e,["file_path","filePath","notebook_path","path","targetPath"])??(t==="Bash"?ze(e.command):void 0);if(!o)return;let i=isAbsolute(o)?normalize(o):resolve(n,o),r=relative(n,i);return r.startsWith("..")||isAbsolute(r)?void 0:i}function ze(n){return typeof n!="string"?void 0:/(?:^|[;&|]\s*)\s*(?:rm|unlink)\s+(?:-[A-Za-z]+\s+)*(?:--\s+)?(["']?)([^\s;&|"']+)\1/u.exec(n)?.[2]}function mn(n,t){for(let e of t){let o=n[e];if(typeof o=="string"&&o.trim())return o.trim()}}function hn(n){if(!existsSync$1(n))return {exists:false};try{return {exists:!0,hash:createHash$1("sha256").update(readFileSync$1(n)).digest("hex")}}catch{return {exists:true}}}function yn(n,t,e){return (isAbsolute(t)?normalize(t):resolve(n,t))===normalize(e)}function Ke(n){return join(f(n),"file-state")}function Ye(n){return join(Ke(n),"pending.json")}function vn(n){return join(Ke(n),"observations.jsonl")}function bn(n){try{return JSON.parse(readFileSync$1(Ye(n),"utf8"))}catch{return {}}}function _n(n,t){let e=Ye(n);mkdirSync$1(dirname(e),{recursive:true});let o=bn(n);o[t.toolUseId]=t,En(e,JSON.stringify(o));}function Rn(n,t){try{let e=readFileSync$1(vn(n),"utf8").trim().split(`
|
|
3
|
-
`);for(let o=e.length-1;o>=0;o-=1){let
|
|
4
|
-
`);}catch{}return g}catch{return
|
|
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 {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {getLocalApiKey,getDevFlowStateRoot,resolveRuntimeEndpoint,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir}from'@devflow-tools/sdk';import {request}from'node:http';import {mkdirSync as mkdirSync$1,appendFileSync,chmodSync,existsSync as existsSync$1,readFileSync as readFileSync$1,writeFileSync as writeFileSync$1,renameSync as renameSync$1}from'node:fs';import {join,resolve,basename,relative,sep,dirname,isAbsolute,normalize}from'node:path';import {maybeRunDiagnosticLogCleanup,rotateDiagnosticLogFile,emitSemanticControlLog}from'@devflow-tools/telemetry';import {fileURLToPath}from'url';import {createHash as createHash$1}from'node:crypto';import {homedir}from'node:os';import {randomUUID,createHash}from'crypto';function D(n,t,e){try{let o=openGlobalDevFlowDatabase();try{o.insertEvent({kind:n,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{o.close();}}catch{}}var tt=getLocalApiKey(),$=join(getDevFlowStateRoot(),"errors");async function ee(n,t,e={}){let o=e.endpoint??resolveRuntimeEndpoint().url,r=e.timeout??1500,i=e.durableMirror??true,s=e.maxRetries??(i?0:2),a=e.circuitBreaker??true,l=acquireRuntimeHttpCircuit(o,n);if(a&&!l.allowed)return {delivered:false,suppressed:true,fallbackReason:l.state.fallbackReason};let c;for(let u=0;u<=s;u+=1)try{return await nt(o,n,t,r),a&®isterRuntimeHttpSuccess(o,n).transitioned&&D("http_circuit_transition",{endpoint:o,path:new URL(n,o).pathname,previous:l.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(p){c=p instanceof Error?p:new Error(String(p)),u<s&&await ot(Math.min(100*2**u,1e3));}if(!c)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return Q(n,c),{delivered:false,suppressed:false,fallbackReason:c.message};let d=registerRuntimeHttpFailure(o,n,e.fallbackReason??(i?"local_durable_mirror":"http_delivery_failed"));return d.transitioned&&(Q(n,c),D("http_circuit_transition",{endpoint:o,path:new URL(n,o).pathname,previous:l.state.status,status:"open",failures:d.state.failures,openUntil:d.state.openUntil,fallbackReason:d.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:d.state.fallbackReason}}function nt(n,t,e,o){return new Promise((r,i)=>{let s=JSON.stringify(e),a=new URL(t,n),l=false,c=u=>{l||(l=true,u?i(u):r());},d=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":tt,"Content-Length":Buffer.byteLength(s)},timeout:o},u=>{u.on("error",c),u.on("end",()=>{let p=u.statusCode??0;c(p>=200&&p<300?void 0:new Error(`HTTP ${p}`));}),u.resume();});d.on("error",c),d.on("timeout",()=>d.destroy(new Error(`HTTP mirror timed out after ${o}ms`))),d.write(s),d.end();})}function Q(n,t){try{existsSync$1($)||mkdirSync$1($,{recursive:!0});let e=join($,"http-errors.log"),o=`${new Date().toISOString()} | ${n} | ${t.message}
|
|
2
|
+
`;rotateDiagnosticLogFile({path:e,maxBytes:50*1024*1024,maxFiles:5,incomingBytes:Buffer.byteLength(o)}),appendFileSync(e,o);}catch{}}function ot(n){return new Promise(t=>setTimeout(t,n))}var re=1e4,lt=3e4,S=500,O=class{constructor(t){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=t?.apiUrl,this.cacheDir=t?.cacheDir??join$1(getDevFlowStateRoot(),"global","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,o,r,i=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:o,startedAt:r,projectRoot:i,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",o=Date.now(),r){let i={executionId:t,status:e,finishedAt:o,metadata:r},s=this.commitOrCache("execution_complete",i);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",i),s}async sendSessionStart(t,e,o){let r={id:t,projectRoot:e,startedAt:o,label:e.split("/").pop()??"unknown"},i=this.commitOrCache("session_start",r);return i&&this.postHttp("/api/telemetry/sessions",r),i}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 o={sessionId:t,finishedAt:e},r=this.commitOrCache("session_end",o);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),r}async flushCache(){try{let e=this.getDatabase(),o=e.listTelemetryFailures({unresolvedOnly:!0,limit:S}).reverse();for(let r of o)try{this.applyOperation(r.operation,r.payload),e.resolveTelemetryFailure(r.id);}catch{}e.trimTelemetryFailures(S);}catch{}let t=(existsSync(this.cacheDir)?readdirSync(this.cacheDir):[]).filter(e=>e.endsWith(".json")).map(e=>{let o=join$1(this.cacheDir,e);try{return {cacheFile:o,envelope:dt(JSON.parse(readFileSync(o,"utf8")))}}catch{return null}}).filter(e=>e!==null).sort((e,o)=>e.envelope.timestamp-o.envelope.timestamp||ie(e.envelope.operation)-ie(o.envelope.operation));for(let{cacheFile:e,envelope:o}of t)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(e);}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(o){return this.cacheOperation(t,e,o),false}}applyOperation(t,e){let o=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(o,e),o.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(o,e),o.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":o.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":o.ensureSession(e),o.insertRun({id:se(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!o.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":o.closeSession(e.sessionId,e.finishedAt),o.updateRun(se(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let o=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!o)throw new Error("Canonical session ID is required for telemetry");let r=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:o,projectRoot:r,label:r==="unknown"?void 0:r.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,o){let r=Date.now(),i={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:o instanceof Error?o.message:String(o),timestamp:r};try{let s=this.getDatabase();s.insertTelemetryFailure({id:i.id,operation:t,payload:e,error:i.failure,createdAt:r}),s.trimTelemetryFailures(S),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${r}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(i,null,2),{mode:384}),this.trimRetryCache(),this.scheduleRetry();}catch{}}trimRetryCache(){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();},lt).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){ee(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=re?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,re)}...`}}};function ie(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function se(n){return `hook-run:${n}`}function dt(n){if(!n||typeof n!="object")throw new Error("Invalid telemetry cache envelope");let t=n;if(typeof t.id!="string"||typeof t.operation!="string"||t.payload===void 0||typeof t.failure!="string"||typeof t.timestamp!="number")throw new Error("Invalid telemetry cache envelope");return t}function A(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function m(n){return getProjectStateDir(A(n))}var f=emitSemanticControlLog;var vt=2,yt=1;function bt(){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 ae(n=bt()){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 o=JSON.parse(readFileSync(e,"utf8"));if(o.version!==vt&&o.version!==yt||!_t(o.commands)){f({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:"contract_mismatch",registryPath:e}});continue}return o.commands}catch(o){f({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:o.message,fallback:"next_registry_candidate"}});}return null}function _t(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 C(e.mcpTools)&&C(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||C(e.runtimePackages))&&(e.hostTools===void 0||Rt(e.hostTools))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function Rt(n){return !!n&&typeof n=="object"&&!Array.isArray(n)&&Object.entries(n).every(([t,e])=>t.length>0&&C(e))}function C(n){return Array.isArray(n)&&n.every(t=>typeof t=="string"&&t.length>0)}function ce(n){let t=ae();return t?t[n]?.mcpTools??[]:[]}function T(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let t=n,e={};for(let o of ["lastMcpCall","bypassCount"])if(o in t){let r=t[o];if(r==null)continue;e[o]=typeof r=="number"&&Number.isFinite(r)&&r>=0?r:0;}return e}function Et(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function de(n,t,e){let o=e instanceof Error?e.message:String(e);f({event:"hook.runtime.degraded",identity:{projectRoot:n},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:o,fallback:"fail_open"}});}function ue(n,t,e){let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let r={},i=o.updateHookReceipt(n,a=>(r=T(a),T(t(r)))),s=T(i);return {receipt:s,applied:!0,changed:!Et(r,s)}}catch(r){return de(n,e,r),{receipt:{},applied:false,changed:false}}finally{try{o?.close();}catch{}}}function pe(n){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),T(t.getHookReceipt(n))}catch(e){return de(n,"update",e),{}}finally{try{t?.close();}catch{}}}function xt(n,t){return ue(n,()=>t,"write").applied}function wt(n,t){return ue(n,t,"update")}var le={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},It=new Set(["Write","Edit","NotebookEdit"]),Dt=new Set(["failed","timeout","unavailable"]);function kt(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 F=class{constructor(t,e,o){this.projectRoot=t;this.sessionId=e;this.executionId=o;}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 o=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(o==="context_gathering"&&le[t])return {permissionDecision:"deny",reasonCode:"DEVFLOW_CONTEXT_REQUIRED",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(o==="context_ready"){if(It.has(t)){let l=this.evaluateRequiredAction();if(l)return l}return {permissionDecision:"allow"}}let r=le[t];if(!r)return {permissionDecision:"allow"};let i=wt(this.projectRoot,l=>({...l,bypassCount:(l.bypassCount??0)+1}));if(!i.applied)return {permissionDecision:"allow"};let s=i.receipt.bypassCount??0,a=kt(t);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${r} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){xt(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(t,e,o,r){if(!this.sessionId||!this.executionId)return false;let i;try{i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let s=i.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(!s||s.expiresAt<=Date.now()||s.canonicalAction?.tool!==t)return !1;let a=Date.now(),l=r?.trim()?`${r.trim()}:${e}`:`${t}:${e}:${a}`,c=s.actionAttempts??[];return i.upsertContextReceipt({...s,actionAttempts:c.some(d=>d.id===l||r&&d.toolUseId===r&&d.status===e)?c:[...c,{id:l,tool:t,status:e,attemptedAt:a,toolUseId:r,reason:o?.slice(0,500)}].slice(-20),actionSatisfiedAt:e==="succeeded"?a:s.actionSatisfiedAt,actionDegradation:e==="succeeded"?void 0:s.actionDegradation}),!0}catch{return false}finally{try{i?.close();}catch{}}}evaluateRequiredAction(){let t=this.getContextReceipt(),e=t?.canonicalAction;if(!t||!e||!e.required||e.status!=="required")return null;let o=e.binding;if(o.requiredContextReceipt!==t.contextHash||o.projectRoot!==this.projectRoot||o.sessionId!==this.sessionId||o.requestId!==t.requestId||o.executionId&&o.executionId!==this.executionId)return {permissionDecision:"deny",reasonCode:"DEVFLOW_ACTION_BINDING_STALE",reason:"DevFlow canonical action binding is stale or mismatched. Call mcp__devflow__get_project_context again before writing."};if(t.actionSatisfiedAt)return null;if(t.actionDegradation?.authorizedByContextReceipt===t.contextHash)return {permissionDecision:"allow",additionalContext:`DevFlow degraded fallback authorized by context receipt ${t.contextHash}: ${t.actionDegradation.reason}`};let r=(t.actionAttempts??[]).filter(i=>i.tool===e.tool&&Dt.has(i.status));if(r.length>0){let i=r.at(-1),s={missedTool:e.tool,failedAttemptCount:r.length,reason:`${i.status}:${i.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} ${i.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 o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let r=o.getContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!r||r.contextHash!==t.contextHash||r.actionDegradation)return;o.upsertContextReceipt({...r,actionDegradation:e});let i=o.getSkillExecution(t.executionId);if(!i)return;let s=i.metadata&&typeof i.metadata=="object"?i.metadata:{},a=Array.isArray(s.requiredActionDegradations)?s.requiredActionDegradations:[];o.updateSkillExecution(t.executionId,{missedMcpTools:[...new Set([...i.missedMcpTools??[],e.missedTool])],failedToolCalls:Math.max(i.failedToolCalls??0,e.failedAttemptCount),fallbackCount:(i.fallbackCount??0)+1,fallbackReasons:[...new Set([...i.fallbackReasons??[],`required_action_${e.reason}`])],metadata:{...s,requiredActionDegradations:[...a,e]}});}catch{}finally{try{o?.close();}catch{}}}};var Lt=10*1024*1024,Mt=5;function $t(n){return createHash$1("sha256").update(n).digest("hex").slice(0,16)}function ge(n){return join(homedir(),".devflow","logs","hook-debug",`${$t(n)}.jsonl`)}function me(n,t,e={}){let o=e.maxBytes??Lt,r=e.maxFiles??Mt;mkdirSync$1(dirname(n),{recursive:true,mode:448});let i=Buffer.byteLength(t);rotateDiagnosticLogFile({path:n,maxBytes:o,maxFiles:r,incomingBytes:i}),appendFileSync(n,t,{mode:384}),chmodSync(n,384);}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 fe(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function be(n){return Buffer.from(n,"utf8").toString("base64url")}function qt(n,t,e){let o=t?.trim();if(o){let r=/^[a-zA-Z0-9:._-]{1,192}$/.test(o)?o:`tool-${createHash("sha256").update(o.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${r}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function Ie(n){return `${n}:legacy-journal`}var P=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(m(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let o=this.get(e);if(o)return o.lastActivityAt=Date.now(),this.persist(o),o;let r=Date.now(),i={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:r,lastActivityAt:r};return this.sessions.set(e,i),this.persist(i),i}startExecution(t,e,o){let r=this.registerSession(t);return (!r.executionId||r.skillName!==e)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=e,r.requiredMcpTools=[...new Set(o)],r.lastActivityAt=Date.now(),this.persist(r),r}bindTaskIdentity(t,e){let o=this.registerSession(t);return o.activeTurnId=e.turnId,o.activeRequestId=e.requestId,o.intentArtifactHash=e.intentArtifactHash,o.lastActivityAt=Date.now(),this.persist(o),o}get(t){let e=t.trim();if(!e)return null;let o=this.sessions.get(e);if(o)return this.replayEvidenceJournal(o),o;let r=this.snapshotPath(e);if(!existsSync(r))return null;try{let i=JSON.parse(readFileSync(r,"utf8"));return i.sessionId!==e||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],i.evidenceObligations=_e(i.evidenceObligations),i.evidenceDegradations=Re(i.evidenceDegradations),i.evidenceOutcomes=Ee(i.evidenceOutcomes),this.replayEvidenceJournal(i),this.sessions.set(e,i),i)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let o=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),o}addEvidenceObligation(t,e,o=Date.now(),r){let i=this.registerSession(t),a=(r?void 0:i.evidenceObligations.find(c=>c.contractId===e.id))?.obligationId??qt(e.id,r,o);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:o,contract:e},`add\0${a}`),this.replayEvidenceJournal(i);let l=i.evidenceObligations.find(c=>c.obligationId===a);return l?(i.lastActivityAt=Date.now(),this.persist(i),structuredClone(l)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,o,r,i=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!a)return null;let l=/^[a-f0-9]{64}$/.test(r)?r:"";if(!l)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:i,fingerprint:l,violations:o.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${l}`),this.replayEvidenceJournal(s),s.lastActivityAt=i,this.persist(s);let c=s.evidenceObligations.find(d=>d.obligationId===e);return c?structuredClone(c):null}resolveEvidenceObligation(t,e){let o=this.get(t);if(!o)return false;let r=o.evidenceObligations.find(s=>s.obligationId===e);if(!r)return false;let i=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:r.contractId,at:i},`resolve\0${e}`),this.replayEvidenceJournal(o),o.lastActivityAt=i,this.persist(o),true}resolveDegradedEvidence(t,e){let o=this.get(t),r=o?.evidenceDegradations.find(s=>s.obligationId===e);if(!o||!r)return false;let i=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:r.contractId,at:i},`resolve-degraded\0${e}\0${i}`),this.replayEvidenceJournal(o),o.lastActivityAt=i,this.persist(o),true}degradeEvidenceObligation(t,e,o,r=Date.now()){let i=this.get(t),s=i?.evidenceObligations.find(l=>l.obligationId===e);if(!i||!s)return false;let a=o.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:r,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),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,`${be(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",be(t))}appendEvidenceEvent(t,e,o){let r=this.evidenceJournalDir(t);mkdirSync(r,{recursive:true,mode:448});let i=createHash("sha256").update(o).digest("hex"),s=join$1(r,`${e.kind}-${i}.json`);if(existsSync(s))return;let a=join$1(r,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(l){if(l.code!=="EEXIST")throw l}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=_e(t.evidenceObligations),t.evidenceDegradations=Re(t.evidenceDegradations),t.evidenceOutcomes=Ee(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let o;try{o=readdirSync(e).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(join$1(e,i),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=Jt(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((i,s)=>i.at-s.at||xe(i.kind)-xe(s.kind));for(let i of r)this.applyEvidenceEvent(t,i);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let o=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(o)return;let s=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let r=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!r||o||r.correctionFingerprint===e.fingerprint)return;r.attempt+=1,r.correctionRequested=true,r.correctionRequestedAt=e.at,r.correctionFingerprint=e.fingerprint,r.violations=e.violations;return}let i=r?.attempt??o?.attempt??0;if(e.kind==="resolve"&&o?.status==="degraded")t.evidenceOutcomes=t.evidenceOutcomes.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations=t.evidenceDegradations.filter(s=>s.obligationId!==e.obligationId);else if(o)return;e.kind==="degrade"?(t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:i,contract:r?.contract})):t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:i,...e.kind==="degrade"?{reason:e.reason}:{}});}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),o=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384}),renameSync(o,e);}};function _e(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)||!De(e.contract))return [];let o=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Ie(e.contractId),r=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,i=e.correctionFingerprint??r;return i!==void 0&&!/^[a-f0-9]{64}$/.test(i)?[]:[{...e,obligationId:o,correctionFingerprint:i}]}).slice(-8):[]}function Re(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 Ee(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(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 Jt(n){if(!n||typeof n!="object")return null;let t=n,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let r={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:Ie(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return De(t.contract)?{kind:e,...r,contract:t.contract}:null;if(e==="correction"){let i=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof i=="string"&&/^[a-f0-9]{64}$/.test(i)&&Array.isArray(t.violations)&&t.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:e,...r,fingerprint:i,violations:t.violations}:null}return e==="resolve"?{kind:e,...r}:typeof t.reason=="string"&&t.reason.length<=240?{kind:e,...r,reason:t.reason}:null}function xe(n){return n==="add"?0:n==="correction"?1:2}function De(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,o=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(o)&&o.length<=16&&o.every(r=>typeof r=="string"&&r.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function ke(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 Se(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 Gt=new Set(["Write","Edit","NotebookEdit"]),Oe="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 je(n){if(!Gt.has(n.toolName))return null;let t=zt(n.toolInput);if(!t)return null;let e=Kt(t,n.projectRoot),o=resolve(n.projectRoot,".claude");if(Ae(e,o)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return Oe;let r=resolve(n.home??homedir(),".claude","projects");return Ae(e,r)&&relative(r,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?Oe:null}function zt(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 Kt(n,t){return resolve(isAbsolute(n)?n:resolve(t,n))}function Ae(n,t){let e=relative(t,n);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function $e(n){let t=on(n.toolName,n.toolInput),e=t?rn(n.projectRoot,n.toolName,n.toolInput):void 0;if(!t||!e||!n.toolUseId)return {allowed:true};let o=an(e),r,i=0,s,a;try{a=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:100,readonly:!0});let c=a.getActiveContextReceipt(n.projectRoot,n.sessionId,n.executionId);r=c?.contextHash,i=c?.issuedAt??0,s=c?.canonicalAction?.binding.operationTargets?.find(d=>cn(n.projectRoot,d.path,e));}catch{}finally{try{a?.close();}catch{}}let l={toolUseId:n.toolUseId,sessionId:n.sessionId,executionId:n.executionId,operation:t,path:e,before:o,contextReceipt:r,observedAt:Date.now()};if(un(n.projectRoot,l),t==="edit"||t==="write"||t==="delete"){let c=pn(n.projectRoot,e),d=c?.success&&c.operation==="delete"&&!c.after.exists&&c.completedAt>=i,u=s?.expectedState==="existing"&&!o.exists||s?.expectedState==="missing"&&o.exists||!!(s?.contentHash&&o.hash!==s.contentHash);if(d||s?.expectedState==="existing"&&!o.exists)return Pe(n,l,"DEVFLOW_FILE_STATE_DELETED","The target was deleted after the active Context receipt. Refresh project context before editing or recreating it.");if(u)return Pe(n,l,"DEVFLOW_FILE_STATE_STALE","The target state no longer matches the active Context receipt. Refresh project context before overwriting it.")}return Ne(n,l,true),{allowed:true,pending:l}}function Pe(n,t,e,o){return Ne(n,t,false,e),{allowed:false,reasonCode:e,reason:o,pending:t}}function Ne(n,t,e,o){f({event:"canonical.action.validated",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:n.executionId,contextReceipt:t.contextReceipt},level:e?"info":"warn",timestamp:Date.now(),data:{stage:"host_file_state_precondition",valid:e,operation:t.operation,targetPath:relative(n.projectRoot,t.path),targetExists:t.before.exists,targetHash:t.before.hash,reason:o,toolUseId:t.toolUseId}});}function on(n,t){if(n==="Read")return "read";if(n==="Edit"||n==="NotebookEdit")return "edit";if(n==="Write")return "write";if(n==="Delete"||n==="Bash"&&He(t.command))return "delete"}function rn(n,t,e){let o=sn(e,["file_path","filePath","notebook_path","path","targetPath"])??(t==="Bash"?He(e.command):void 0);if(!o)return;let r=isAbsolute(o)?normalize(o):resolve(n,o),i=relative(n,r);return i.startsWith("..")||isAbsolute(i)?void 0:r}function He(n){return typeof n!="string"?void 0:/(?:^|[;&|]\s*)\s*(?:rm|unlink)\s+(?:-[A-Za-z]+\s+)*(?:--\s+)?(["']?)([^\s;&|"']+)\1/u.exec(n)?.[2]}function sn(n,t){for(let e of t){let o=n[e];if(typeof o=="string"&&o.trim())return o.trim()}}function an(n){if(!existsSync$1(n))return {exists:false};try{return {exists:!0,hash:createHash$1("sha256").update(readFileSync$1(n)).digest("hex")}}catch{return {exists:true}}}function cn(n,t,e){return (isAbsolute(t)?normalize(t):resolve(n,t))===normalize(e)}function Ue(n){return join(m(n),"file-state")}function qe(n){return join(Ue(n),"pending.json")}function ln(n){return join(Ue(n),"observations.jsonl")}function dn(n){try{return JSON.parse(readFileSync$1(qe(n),"utf8"))}catch{return {}}}function un(n,t){let e=qe(n);mkdirSync$1(dirname(e),{recursive:true});let o=dn(n);o[t.toolUseId]=t,gn(e,JSON.stringify(o));}function pn(n,t){try{let e=readFileSync$1(ln(n),"utf8").trim().split(`
|
|
3
|
+
`);for(let o=e.length-1;o>=0;o-=1){let r=JSON.parse(e[o]);if(r.path===t)return r}}catch{}}function gn(n,t){let e=`${n}.${process.pid}.${Date.now()}.tmp`;writeFileSync$1(e,t,{encoding:"utf8",mode:384}),renameSync$1(e,n);}function E(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function Je(n){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:n}}}function bn(n){let t=m(n);return existsSync(t)||mkdirSync(t,{recursive:true}),t}function _n(n,t,e,o,r,i){let s=join$1(bn(n),"event-map.json"),a=[];try{existsSync(s)&&(a=JSON.parse(readFileSync(s,"utf-8")));}catch{}a.push({sessionId:t,toolName:e,toolUseId:o,eventId:r,timestamp:i}),writeFileSync(s,JSON.stringify(a));}function Rn(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 En(n){let t=fe();try{if(!n||n.trim()==="")return E();let e=JSON.parse(n),o=Date.now();try{maybeRunDiagnosticLogCleanup(A(),{now:o});}catch{}let r=A(),i=new O;e.tool_name.startsWith("mcp__devflow__")&&(typeof e.tool_input.projectRoot!="string"||!e.tool_input.projectRoot.trim())&&(e.tool_input.projectRoot=r);let s=e.session_id?.trim();if(!s)return Je(H);let a=new P(r),l=a.get(s)!==null;if(a.registerSession(s),l||await i.sendSessionStart(s,r,Date.now()),e.tool_name==="Skill"){let I=e.tool_input?.skill,v=I?ke(I):null;if(v){let Be=a.get(s)?.executionId,R=a.startExecution(s,v,ce(v));R.executionId&&R.executionId!==Be&&await i.sendExecutionStart(R.executionId,s,v,R.lastActivityAt,r,R.requiredMcpTools);}}let c=a.get(s);e.tool_name.startsWith("mcp__devflow__")&&(e.tool_input._devflow_session_id=s,e.tool_input._devflow_execution_id=c?.executionId??s,c?.activeTurnId&&(e.tool_input._devflow_turn_id=c.activeTurnId),c?.activeRequestId&&(e.tool_input._devflow_request_id=c.activeRequestId),c?.intentArtifactHash&&(e.tool_input._devflow_intent_artifact_hash=c.intentArtifactHash),c?.skillName&&(e.tool_input._devflow_active_skill=c.skillName),e.tool_use_id&&(e.tool_input._devflow_tool_use_id=e.tool_use_id));let d=e.tool_name.startsWith("mcp__"),u=d?e.tool_name.replace(/^mcp__[^_]+__/,""):void 0,p=new F(r,s,c?.executionId),G=p.getPhase(),g,x=je({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:r}),M=$e({projectRoot:r,sessionId:s,executionId:c?.executionId,toolUseId:e.tool_use_id,toolName:e.tool_name,toolInput:e.tool_input}),h=x?{permissionDecision:"deny",reason:x}:M.allowed?p.evaluate(e.tool_name,d):{permissionDecision:"deny",reason:M.reason,reasonCode:M.reasonCode};h.permissionDecision==="deny"?g={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:h.reason??"MCP context required"}}:h.additionalContext?g=Je(h.additionalContext):g=E(),e.tool_name.startsWith("mcp__devflow__")&&(g.hookSpecificOutput.updatedInput=e.tool_input),t&&g.hookSpecificOutput.permissionDecision==="allow"&&(g.hookSpecificOutput.additionalContext=H);let Ve=c?.executionId??s,_={eventId:Se(s,e.tool_use_id),executionId:Ve,sessionId:s,projectRoot:r,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&&G==="context_gathering",mcpFallback:!d&&G==="context_gathering",kind:Rn(e.tool_name),input:e.tool_input,duration:0,blocked:g.hookSpecificOutput.permissionDecision==="deny",blockReason:g.hookSpecificOutput.permissionDecision==="deny"?x?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":h.reasonCode??"DEVFLOW_CONTEXT_REQUIRED":void 0},w=await i.sendEvent(_);w&&!_.blocked&&_n(r,s,e.tool_name,e.tool_use_id,w,_.timestamp),w&&_.blocked&&await i.completeEvent({eventId:w,sessionId:s,error:x?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":h.reasonCode??"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-_.timestamp,completedAt:Date.now()});try{let I=pe(r),v={ts:o,tool:e.tool_name,sessionId:s,skill:c?.skillName??"(none)",requiredTools:c?.requiredMcpTools??[],isMcp:d,enforce:c?.executionId!==void 0,stateless:c?.executionId===void 0&&!d&&e.tool_name!=="Skill",bypassCount:I.bypassCount??0,decision:g.hookSpecificOutput.permissionDecision,env_CLAUDE_PLUGIN_ROOT:process.env.CLAUDE_PLUGIN_ROOT??"(unset)",cwd:process.cwd()};me(ge(r),`${JSON.stringify(v)}
|
|
4
|
+
`);}catch{}return g}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 En(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{En as handlePreToolUse};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {spawn,execFileSync}from'node:child_process';import {randomUUID,createHash}from'node:crypto';import {mkdirSync,writeFileSync,existsSync}from'node:fs';import {request}from'node:http';import {createRequire}from'node:module';import {
|
|
1
|
+
import {spawn,execFileSync}from'node:child_process';import {randomUUID,createHash}from'node:crypto';import {mkdirSync,writeFileSync,existsSync}from'node:fs';import {request}from'node:http';import {createRequire}from'node:module';import {join}from'node:path';import {getDevFlowStateRoot,writeRuntimeEndpointState,readRuntimeEndpointState,updateRuntimeEndpointStatus,resolveRuntimeEndpoint}from'@devflow-tools/sdk';import {emitSemanticControlLog}from'@devflow-tools/telemetry';var g=emitSemanticControlLog;var{DatabaseSync:z}=createRequire(import.meta.url)("node:sqlite"),K=75,$=400,Y=2e3,X=300*1e3,J=1e3,Z=1e3,ee=15e3,re=["--yes","@devflow-tools/server","--devflow-instance-token"],M=process.env.CLAUDE_PROJECT_DIR||process.cwd();function h(e){let n=e instanceof Error?e.message:String(e);g({event:"hook.runtime.degraded",identity:{projectRoot:M},level:"warn",timestamp:Date.now(),data:{stage:"server_bootstrap",reason:n,fallback:"mcp_stdio_or_existing_server"}});}function d(e,n,t){g({event:e==="warn"?"hook.runtime.degraded":"hook.runtime.completed",identity:{projectRoot:M},level:e,timestamp:Date.now(),data:{stage:n,...t}});}function te(e){return createHash("sha256").update(e).digest("hex").slice(0,16)}function ne(e){let n=new z(e);n.exec(`PRAGMA busy_timeout = ${K}`);let t=n.prepare(`
|
|
2
2
|
SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'server_bootstrap_state'
|
|
3
|
-
`).get();if(t?.sql&&!t.sql.includes("'terminating'")){n.exec("BEGIN IMMEDIATE");try{n.exec("ALTER TABLE server_bootstrap_state RENAME TO server_bootstrap_state_legacy"),
|
|
3
|
+
`).get();if(t?.sql&&!t.sql.includes("'terminating'")){n.exec("BEGIN IMMEDIATE");try{n.exec("ALTER TABLE server_bootstrap_state RENAME TO server_bootstrap_state_legacy"),L(n),n.exec(`
|
|
4
4
|
INSERT INTO server_bootstrap_state (
|
|
5
5
|
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
6
6
|
created_at, updated_at
|
|
@@ -9,7 +9,7 @@ import {spawn,execFileSync}from'node:child_process';import {randomUUID,createHas
|
|
|
9
9
|
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
10
10
|
created_at, updated_at
|
|
11
11
|
FROM server_bootstrap_state_legacy
|
|
12
|
-
`),n.exec("DROP TABLE server_bootstrap_state_legacy"),n.exec("COMMIT");}catch(r){try{n.exec("ROLLBACK");}catch{}throw r}}else t||
|
|
12
|
+
`),n.exec("DROP TABLE server_bootstrap_state_legacy"),n.exec("COMMIT");}catch(r){try{n.exec("ROLLBACK");}catch{}throw r}}else t||L(n);return n}function L(e){e.exec(`
|
|
13
13
|
CREATE TABLE IF NOT EXISTS server_bootstrap_state (
|
|
14
14
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
15
15
|
token TEXT NOT NULL,
|
|
@@ -21,7 +21,7 @@ import {spawn,execFileSync}from'node:child_process';import {randomUUID,createHas
|
|
|
21
21
|
created_at INTEGER NOT NULL,
|
|
22
22
|
updated_at INTEGER NOT NULL
|
|
23
23
|
)
|
|
24
|
-
`);}function
|
|
24
|
+
`);}function oe(e){return e.prepare(`
|
|
25
25
|
SELECT
|
|
26
26
|
token,
|
|
27
27
|
state,
|
|
@@ -33,46 +33,46 @@ import {spawn,execFileSync}from'node:child_process';import {randomUUID,createHas
|
|
|
33
33
|
updated_at AS updatedAt
|
|
34
34
|
FROM server_bootstrap_state
|
|
35
35
|
WHERE id = 1
|
|
36
|
-
`).get()}function
|
|
37
|
-
`)){let r=t.match(/^\s*(\d+)\s+(\d+)\s+(.+)$/);if(!r)continue;let o=Number(r[1]),
|
|
36
|
+
`).get()}function p(e){return Number(e.changes)}function se(e){if(!Number.isSafeInteger(e)||e<=1)return false;try{return process.kill(e,0),!0}catch{return false}}function G(){let e=execFileSync("ps",["-axo","pid=,pgid=,command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:500}),n=[];for(let t of e.split(`
|
|
37
|
+
`)){let r=t.match(/^\s*(\d+)\s+(\d+)\s+(.+)$/);if(!r)continue;let o=Number(r[1]),c=Number(r[2]);!Number.isSafeInteger(o)||!Number.isSafeInteger(c)||n.push({pid:o,processGroupId:c,command:r[3]});}return n}function ie(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function x(e,n){let t=ie(n);return new RegExp(`(?:^|\\s)--devflow-instance-token(?:=|\\s+)${t}(?:\\s|$)`).test(e)}function S(e){return /(?:@devflow-tools\/server|devflow-server|[\\/]apps[\\/]server[\\/]dist[\\/]main\.js|[\\/]@devflow-tools[\\/]server[\\/]dist[\\/]main\.js)/.test(e)}function A(e){return /(?:^|\s)(?:\S*[\\/])?devflow-server(?:-child)?(?:\s|$)|[\\/]apps[\\/]server[\\/]dist[\\/]main\.js|[\\/]@devflow-tools[\\/]server[\\/]dist[\\/]main\.js/.test(e)}function ae(e){let n=G().filter(r=>S(r.command)&&x(r.command,e)),t=new Map;for(let r of n){let o=t.get(r.processGroupId)??[];o.push(r),t.set(r.processGroupId,o);}return [...t.entries()].map(([r,o])=>({processGroupId:r,processes:o})).sort((r,o)=>o.processes.length-r.processes.length)}function R(e,n){return ae(e).find(t=>n===void 0||t.processGroupId===n)}function E(e,n){let t=I(e,n);if(!t)return;let r=t.processes.find(o=>o.pid!==t.wrapperPid&&A(o.command))??t.processes.find(o=>o.pid===t.wrapperPid&&A(o.command));if(r)return {wrapperPid:t.wrapperPid,processGroupId:t.processGroupId,serverPid:r.pid,processes:t.processes}}function I(e,n){let t=R(e,n);if(!t)return;let r=t.processes.find(o=>o.pid===t.processGroupId&&S(o.command));if(r)return {wrapperPid:r.pid,processGroupId:r.processGroupId,processes:t.processes}}function T(e){if(!se(e))return false;try{return execFileSync("ps",["-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:250}).trim().includes("server-bootstrap")}catch{return false}}function U(){return new Promise(e=>{let n=false,t=r=>{n||(n=true,e(r));};try{let r=process.env.DEVFLOW_SERVER_BOOTSTRAP_HEALTH_URL??new URL("/api/health",D()).toString(),o=request(r,{method:"GET",timeout:$},c=>{c.resume(),t((c.statusCode??500)>=200&&(c.statusCode??500)<300);});o.on("timeout",()=>o.destroy(new Error("health timeout"))),o.on("error",()=>t(!1)),o.end();}catch{t(false);}})}async function ce(e){let n=false;try{e.exec("BEGIN IMMEDIATE"),n=!0;let t=await U(),r=oe(e);if(t){if(r?.state==="running"||r?.state==="launching"){let s=E(r.token,r.processGroupId??void 0);if(s){e.prepare(`
|
|
38
38
|
UPDATE server_bootstrap_state
|
|
39
39
|
SET state = 'running', owner_pid = ?, wrapper_pid = ?, process_group_id = ?, server_pid = ?,
|
|
40
40
|
updated_at = ?
|
|
41
41
|
WHERE id = 1 AND token = ? AND state = ?
|
|
42
|
-
`).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token,r.state);let i=
|
|
42
|
+
`).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token,r.state);let i=D();writeRuntimeEndpointState({url:i,port:Number(new URL(i).port||13337),pid:s.serverPid,processGroupId:s.processGroupId,ownerToken:r.token,status:"healthy"});}else r.state==="running"&&e.prepare(`
|
|
43
43
|
DELETE FROM server_bootstrap_state
|
|
44
44
|
WHERE id = 1 AND token = ? AND state = 'running'
|
|
45
|
-
`).run(r.token);}return e.exec("COMMIT"),n=!1,{action:"skip"}}if(r?.state==="launching"){if(
|
|
45
|
+
`).run(r.token);}return e.exec("COMMIT"),n=!1,{action:"skip"}}if(r?.state==="launching"){if(T(r.ownerPid))return e.exec("COMMIT"),n=!1,{action:"skip"};let s=r.processGroupId??void 0,i=E(r.token,s);if(i){let u=e.prepare(`
|
|
46
46
|
UPDATE server_bootstrap_state
|
|
47
47
|
SET state = 'running', owner_pid = ?, wrapper_pid = ?, process_group_id = ?,
|
|
48
48
|
server_pid = ?, updated_at = ?
|
|
49
49
|
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
50
|
-
`).run(process.pid,i.wrapperPid,i.processGroupId,i.serverPid,Date.now(),r.token,r.ownerPid);if(
|
|
50
|
+
`).run(process.pid,i.wrapperPid,i.processGroupId,i.serverPid,Date.now(),r.token,r.ownerPid);if(p(u)!==1)throw new Error("launch intent changed before adoption");return e.exec("COMMIT"),n=!1,d("info","server_process_adopted",{processGroupId:i.processGroupId}),{action:"skip"}}let a=I(r.token,s);if(a&&Date.now()-r.createdAt<X)return e.exec("COMMIT"),n=!1,{action:"skip"};if(a){let u=e.prepare(`
|
|
51
51
|
UPDATE server_bootstrap_state
|
|
52
52
|
SET state = 'terminating', owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
53
53
|
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
54
|
-
`).run(process.pid,a.processGroupId,Date.now(),r.token,r.ownerPid);if(
|
|
54
|
+
`).run(process.pid,a.processGroupId,Date.now(),r.token,r.ownerPid);if(p(u)!==1)throw new Error("launch intent changed before cleanup claim");return e.exec("COMMIT"),n=!1,{action:"cleanup",token:r.token,processGroupId:a.processGroupId}}e.prepare(`
|
|
55
55
|
DELETE FROM server_bootstrap_state
|
|
56
56
|
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
57
|
-
`).run(r.token,r.ownerPid);}else if(r?.state==="terminating"){if(
|
|
57
|
+
`).run(r.token,r.ownerPid);}else if(r?.state==="terminating"){if(T(r.ownerPid))return e.exec("COMMIT"),n=!1,{action:"skip"};let s=R(r.token);if(s){let i=e.prepare(`
|
|
58
58
|
UPDATE server_bootstrap_state
|
|
59
59
|
SET owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
60
60
|
WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
|
|
61
|
-
`).run(process.pid,s.processGroupId,Date.now(),r.token,r.ownerPid);if(
|
|
61
|
+
`).run(process.pid,s.processGroupId,Date.now(),r.token,r.ownerPid);if(p(i)!==1)throw new Error("cleanup ownership changed during recovery");return e.exec("COMMIT"),n=!1,{action:"cleanup",token:r.token,processGroupId:s.processGroupId}}e.prepare(`
|
|
62
62
|
DELETE FROM server_bootstrap_state
|
|
63
63
|
WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
|
|
64
64
|
`).run(r.token,r.ownerPid);}else if(r?.state==="running"){let s=E(r.token);if(s)return e.prepare(`
|
|
65
65
|
UPDATE server_bootstrap_state
|
|
66
66
|
SET owner_pid = ?, wrapper_pid = ?, process_group_id = ?, server_pid = ?, updated_at = ?
|
|
67
67
|
WHERE id = 1 AND token = ? AND state = 'running'
|
|
68
|
-
`).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token),e.exec("COMMIT"),n=!1,{action:"skip"};let i=R(r.token);if(i&&!
|
|
68
|
+
`).run(process.pid,s.wrapperPid,s.processGroupId,s.serverPid,Date.now(),r.token),e.exec("COMMIT"),n=!1,{action:"skip"};let i=R(r.token);if(i&&!T(r.ownerPid)){let a=e.prepare(`
|
|
69
69
|
UPDATE server_bootstrap_state
|
|
70
70
|
SET state = 'terminating', owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
71
71
|
WHERE id = 1 AND token = ? AND state = 'running' AND owner_pid = ?
|
|
72
|
-
`).run(process.pid,i.processGroupId,Date.now(),r.token,r.ownerPid);if(
|
|
72
|
+
`).run(process.pid,i.processGroupId,Date.now(),r.token,r.ownerPid);if(p(a)!==1)throw new Error("running cleanup ownership changed");return e.exec("COMMIT"),n=!1,{action:"cleanup",token:r.token,processGroupId:i.processGroupId}}e.prepare(`
|
|
73
73
|
DELETE FROM server_bootstrap_state
|
|
74
74
|
WHERE id = 1 AND token = ? AND state = 'running' AND owner_pid = ?
|
|
75
|
-
`).run(r.token,r.ownerPid);}let o=randomUUID(),
|
|
75
|
+
`).run(r.token,r.ownerPid);}let o=randomUUID(),c=Date.now();return e.prepare(`
|
|
76
76
|
INSERT INTO server_bootstrap_state (
|
|
77
77
|
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
78
78
|
created_at, updated_at
|
|
@@ -86,24 +86,24 @@ import {spawn,execFileSync}from'node:child_process';import {randomUUID,createHas
|
|
|
86
86
|
server_pid = NULL,
|
|
87
87
|
created_at = excluded.created_at,
|
|
88
88
|
updated_at = excluded.updated_at
|
|
89
|
-
`).run(o,process.pid,
|
|
90
|
-
`);let t=process.env.DEVFLOW_SERVER_BOOTSTRAP_TEST_CONTINUE_FILE;if(!t)return;if(!await
|
|
89
|
+
`).run(o,process.pid,c,c),e.exec("COMMIT"),n=!1,{action:"launch",token:o}}finally{if(n)try{e.exec("ROLLBACK");}catch{}}}function pe(e){return new Promise((n,t)=>{let r;try{let o=de(e);r=spawn(o.command,o.args,{detached:!0,env:{...process.env,DEVFLOW_INSTANCE_TOKEN:e},stdio:["ignore","inherit","inherit"]});}catch(o){t(o);return}r.once("spawn",()=>n(r)),r.once("error",t);})}function de(e){if(!ue()){let n=createRequire(import.meta.url),r=[process.env.DEVFLOW_SERVER_ENTRY,le(()=>n.resolve("@devflow-tools/server/dist/main.js")),join(process.cwd(),"apps","server","dist","main.js"),join(process.cwd(),"node_modules","@devflow-tools","server","dist","main.js")].filter(o=>!!o).find(o=>existsSync(o));if(r)return {command:process.execPath,args:[r,"--devflow-instance-token",e]}}return {command:"npx",args:[...re,e]}}function ue(){return process.env.DEVFLOW_SERVER_BOOTSTRAP_FORCE_NPX==="1"||!!process.env.DEVFLOW_TEST_NPX_TRACE||Object.keys(process.env).some(e=>e.startsWith("DEVFLOW_SERVER_BOOTSTRAP_TEST_"))}function le(e){try{return e()}catch{return}}function D(){let e=resolveRuntimeEndpoint();return e.source==="environment"?e.url:readRuntimeEndpointState()?.url??e.url}async function f(e,n){let t=Date.now()+n;for(;Date.now()<t;){if(e())return true;await new Promise(r=>setTimeout(r,10));}return e()}async function k(e){let n=process.env[e];if(!n)return;writeFileSync(n,`${process.pid}
|
|
90
|
+
`);let t=process.env.DEVFLOW_SERVER_BOOTSTRAP_TEST_CONTINUE_FILE;if(!t)return;if(!await f(()=>existsSync(t),ee))throw new Error(`test checkpoint timed out: ${e}`)}async function _e(e,n){let t;return await f(()=>{let o=E(e,n);return o?(t=o,true):false},Y)?t:void 0}function Ee(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
|
|
91
91
|
UPDATE server_bootstrap_state
|
|
92
92
|
SET wrapper_pid = ?, process_group_id = ?, server_pid = NULL, updated_at = ?
|
|
93
93
|
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
94
|
-
`).run(t.wrapperPid,t.processGroupId,Date.now(),n,process.pid);if(
|
|
94
|
+
`).run(t.wrapperPid,t.processGroupId,Date.now(),n,process.pid);if(p(o)!==1)throw new Error("launch intent ownership changed before wrapper persistence");e.exec("COMMIT"),r=!1;}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function fe(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
|
|
95
95
|
UPDATE server_bootstrap_state
|
|
96
96
|
SET state = 'running', wrapper_pid = ?, process_group_id = ?, server_pid = ?,
|
|
97
97
|
updated_at = ?
|
|
98
98
|
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
99
|
-
`).run(t.wrapperPid,t.processGroupId,t.serverPid,Date.now(),n,process.pid);if(
|
|
99
|
+
`).run(t.wrapperPid,t.processGroupId,t.serverPid,Date.now(),n,process.pid);if(p(o)!==1)throw new Error("launch intent ownership changed before promotion");e.exec("COMMIT"),r=!1;}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function me(e,n){let t=false;try{e.exec("BEGIN IMMEDIATE"),t=!0,e.prepare(`
|
|
100
100
|
DELETE FROM server_bootstrap_state
|
|
101
101
|
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
102
|
-
`).run(n,process.pid),e.exec("COMMIT"),t=!1;}finally{if(t)try{e.exec("ROLLBACK");}catch{}}}function
|
|
102
|
+
`).run(n,process.pid),e.exec("COMMIT"),t=!1;}finally{if(t)try{e.exec("ROLLBACK");}catch{}}}function we(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
|
|
103
103
|
UPDATE server_bootstrap_state
|
|
104
104
|
SET state = 'terminating', owner_pid = ?, updated_at = ?
|
|
105
105
|
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
106
|
-
`).run(process.pid,Date.now(),n,t);return e.exec("COMMIT"),r=!1,
|
|
106
|
+
`).run(process.pid,Date.now(),n,t);return e.exec("COMMIT"),r=!1,p(o)===1}finally{if(r)try{e.exec("ROLLBACK");}catch{}}}function ge(e,n){let t=false;try{e.exec("BEGIN IMMEDIATE"),t=!0;let r=e.prepare(`
|
|
107
107
|
DELETE FROM server_bootstrap_state
|
|
108
108
|
WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
|
|
109
|
-
`).run(n,process.pid);return e.exec("COMMIT"),t=!1,
|
|
109
|
+
`).run(n,process.pid);return e.exec("COMMIT"),t=!1,p(r)===1}finally{if(t)try{e.exec("ROLLBACK");}catch{}}}function m(e){return G().filter(n=>n.processGroupId===e)}function N(e,n){return m(e).some(t=>S(t.command)&&x(t.command,n))}async function Te(e,n){if(!N(e,n))return false;d("warn","server_process_cleanup",{processGroupId:e});try{process.kill(-e,"SIGTERM");}catch{}if(await f(()=>m(e).length===0,J))return true;if(!N(e,n))return false;try{process.kill(-e,"SIGKILL");}catch{}return f(()=>m(e).length===0,Z)}async function O(e,n,t){return m(t).length===0||await Te(t,n)?ge(e,n):false}async function ve(){let e=getDevFlowStateRoot();mkdirSync(e,{recursive:true});let n=ne(join(e,"server-bootstrap.sqlite")),t,r,o=false;try{for(;;){let a=await ce(n);if(a.action==="skip")return;if(a.action==="cleanup"){if(!await O(n,a.token,a.processGroupId))throw new Error("claimed server process group cleanup did not complete");continue}t=a.token;break}if(await k("DEVFLOW_SERVER_BOOTSTRAP_TEST_INTENT_READY_FILE"),r=await pe(t),!r.pid)throw new Error("server launcher returned no PID");let c=r.pid,s=D();writeRuntimeEndpointState({url:s,port:Number(new URL(s).port||13337),pid:r.pid,processGroupId:c,ownerToken:t,status:"launching"});let i=await _e(t,c);if(!i){let a=I(t,c);if(!a)throw new Error("npx process group ownership could not be validated");Ee(n,t,a),r.unref(),d("warn","server_launch_warming",{wrapperPid:a.wrapperPid});return}await k("DEVFLOW_SERVER_BOOTSTRAP_TEST_AFTER_SPAWN_READY_FILE"),fe(n,t,i),o=!0,writeRuntimeEndpointState({url:s,port:Number(new URL(s).port||13337),pid:i.serverPid,processGroupId:i.processGroupId,ownerToken:t,status:await U()?"healthy":"launching"}),r.unref(),d("info","server_launch_background",{wrapperPid:i.wrapperPid,serverPid:i.serverPid});}catch(c){if(t&&r?.pid&&!o){let s=false;try{s=we(n,t,process.pid);}catch(i){h(i);}s?(await O(n,t,r.pid)||d("warn","server_cleanup_incomplete",{processGroupId:r.pid}),readRuntimeEndpointState()?.ownerToken===t&&updateRuntimeEndpointStatus("stopped")):(d("warn","server_cleanup_claim_lost",{tokenHash:te(t)}),r.unref());}else if(t&&!r){try{me(n,t);}catch(i){h(i);}readRuntimeEndpointState()?.ownerToken===t&&updateRuntimeEndpointStatus("stopped");}throw c}finally{try{n.close();}catch{}}}ve().catch(h).then(()=>{process.exitCode=0;},()=>{process.exitCode=0;});
|