@devflow-tools/cli 0.18.3 → 0.18.4
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/README.md +19 -4
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +12 -10
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/server.d.ts +19 -5
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +31 -116
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/start.d.ts +4 -2
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +29 -56
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.d.ts +4 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +17 -9
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/stop.d.ts.map +1 -1
- package/dist/commands/stop.js +3 -2
- package/dist/commands/stop.js.map +1 -1
- package/dist/index.js +63 -18
- package/dist/index.js.map +1 -1
- package/dist/lib/messages.d.ts +38 -0
- package/dist/lib/messages.d.ts.map +1 -0
- package/dist/lib/messages.js +42 -0
- package/dist/lib/messages.js.map +1 -0
- package/dist/lib/with-server.d.ts.map +1 -1
- package/dist/lib/with-server.js +22 -8
- package/dist/lib/with-server.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/hook-daemon.js +28 -27
- 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 +1 -109
- package/dist/plugin-files/dist/hooks/session-end.js +5 -5
- package/dist/plugin-files/dist/hooks/stop.js +9 -9
- package/dist/plugin-files/dist/hooks/user-prompt-submit.js +8 -8
- package/dist/plugin-files/package.json +13 -13
- package/dist/plugin-files/skills/start/SKILL.md +20 -34
- package/package.json +27 -27
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {getLocalApiKey,getDevFlowStateRoot,
|
|
2
|
-
`;rotateDiagnosticLogFile({path:e,maxBytes:50*1024*1024,maxFiles:5,incomingBytes:Buffer.byteLength(t)}),appendFileSync(e,t);}catch{}}function
|
|
1
|
+
import {getLocalApiKey,getDevFlowStateRoot,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,readRuntimeState}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 R(s,r,e={}){let t=e.endpoint??process.env.DEVFLOW_SERVER_URL?.trim()??W();if(!t)return {delivered:false,suppressed:false,fallbackReason:"runtime_not_ready"};let 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 B(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 K(Math.min(100*2**l,1e3));}if(!d)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return v(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&&(v(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(){let s=readRuntimeState();return s?.status==="ready"&&s.dashboardAvailable?s.url:void 0}function B(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 v(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 K(s){return new Promise(r=>setTimeout(r,s))}var E=1e4,Q=3e4,g=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:g}).reverse();for(let o of t)try{this.applyOperation(o.operation,o.payload),e.resolveTelemetryFailure(o.id);}catch{}e.trimTelemetryFailures(g);}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:ee(JSON.parse(readFileSync(t,"utf8")))}}catch{return null}}).filter(e=>e!==null).sort((e,t)=>e.envelope.timestamp-t.envelope.timestamp||I(e.envelope.operation)-I(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:T(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(T(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(g),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-g)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},Q).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){R(r,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(r){let e=JSON.stringify(r);return e===void 0||e.length<=E?r:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,E)}...`}}};function I(s){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(s)}function T(s){return `hook-run:${s}`}function ee(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 S(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 C(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 O="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function x(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}async function oe(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 S({projectRoot:r,sessionId:e,trigger:"pre_compact"}),n=[x()?O:"",C(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",()=>{oe(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{oe 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 {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {getLocalApiKey,getDevFlowStateRoot,
|
|
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
|
|
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
|
|
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,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir,readRuntimeState}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 Y(n,t,e={}){let o=e.endpoint??process.env.DEVFLOW_SERVER_URL?.trim()??nt();if(!o)return {delivered:false,suppressed:false,fallbackReason:"runtime_not_ready"};let 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 ot(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 rt(Math.min(100*2**u,1e3));}if(!c)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return z(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&&(z(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(){let n=readRuntimeState();return n?.status==="ready"&&n.dashboardAvailable?n.url:void 0}function ot(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 z(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 rt(n){return new Promise(t=>setTimeout(t,n))}var ee=1e4,dt=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:ut(JSON.parse(readFileSync(o,"utf8")))}}catch{return null}}).filter(e=>e!==null).sort((e,o)=>e.envelope.timestamp-o.envelope.timestamp||te(e.envelope.operation)-te(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:ne(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(ne(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();},dt).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){Y(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ee?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ee)}...`}}};function te(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function ne(n){return `hook-run:${n}`}function ut(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 f(n){return getProjectStateDir(A(n))}var m=emitSemanticControlLog;var yt=2,bt=1;function _t(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{return join$1(dirname$1(fileURLToPath(import.meta.url)),"..","..")}catch{return process.cwd()}}function oe(n=_t()){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!==yt&&o.version!==bt||!Rt(o.commands)){m({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){m({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 Rt(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||Et(e.hostTools))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function Et(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 re(n){let t=oe();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 xt(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function se(n,t,e){let o=e instanceof Error?e.message:String(e);m({event:"hook.runtime.degraded",identity:{projectRoot:n},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:o,fallback:"fail_open"}});}function ae(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:!xt(r,s)}}catch(r){return se(n,e,r),{receipt:{},applied:false,changed:false}}finally{try{o?.close();}catch{}}}function ce(n){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),T(t.getHookReceipt(n))}catch(e){return se(n,"update",e),{}}finally{try{t?.close();}catch{}}}function wt(n,t){return ae(n,()=>t,"write").applied}function It(n,t){return ae(n,t,"update")}var ie={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},Dt=new Set(["Write","Edit","NotebookEdit"]),kt=new Set(["failed","timeout","unavailable"]);function St(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"&&ie[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(Dt.has(t)){let l=this.evaluateRequiredAction();if(l)return l}return {permissionDecision:"allow"}}let r=ie[t];if(!r)return {permissionDecision:"allow"};let i=It(this.projectRoot,l=>({...l,bypassCount:(l.bypassCount??0)+1}));if(!i.applied)return {permissionDecision:"allow"};let s=i.receipt.bypassCount??0,a=St(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(){wt(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&&kt.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,$t=5;function Nt(n){return createHash$1("sha256").update(n).digest("hex").slice(0,16)}function le(n){return join(homedir(),".devflow","logs","hook-debug",`${Nt(n)}.jsonl`)}function de(n,t,e={}){let o=e.maxBytes??Lt,r=e.maxFiles??$t;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 U="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function ue(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function me(n){return Buffer.from(n,"utf8").toString("base64url")}function Jt(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 Re(n){return `${n}:legacy-journal`}var P=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 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=he(i.evidenceObligations),i.evidenceDegradations=ve(i.evidenceDegradations),i.evidenceOutcomes=ye(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??Jt(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,`${me(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",me(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=he(t.evidenceObligations),t.evidenceDegradations=ve(t.evidenceDegradations),t.evidenceOutcomes=ye(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=Wt(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((i,s)=>i.at-s.at||be(i.kind)-be(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 he(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)||!Ee(e.contract))return [];let o=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Re(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 ve(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 ye(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 Wt(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:Re(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return Ee(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 be(n){return n==="add"?0:n==="correction"?1:2}function Ee(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 xe(n){let t=n.trim().replace(/^\//,"");if(!t.startsWith("devflow:"))return null;let e=t.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(e)?`devflow:${e.toLowerCase()}`:null}function we(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 zt=new Set(["Write","Edit","NotebookEdit"]),Ie="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 Ae(n){if(!zt.has(n.toolName))return null;let t=Kt(n.toolInput);if(!t)return null;let e=Yt(t,n.projectRoot),o=resolve(n.projectRoot,".claude");if(De(e,o)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return Ie;let r=resolve(n.home??homedir(),".claude","projects");return De(e,r)&&relative(r,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?Ie:null}function Kt(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 Yt(n,t){return resolve(isAbsolute(n)?n:resolve(t,n))}function De(n,t){let e=relative(t,n);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function je(n){let t=rn(n.toolName,n.toolInput),e=t?sn(n.projectRoot,n.toolName,n.toolInput):void 0;if(!t||!e||!n.toolUseId)return {allowed:true};let o=cn(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=>ln(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(pn(n.projectRoot,l),t==="edit"||t==="write"||t==="delete"){let c=gn(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 Ce(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 Ce(n,l,"DEVFLOW_FILE_STATE_STALE","The target state no longer matches the active Context receipt. Refresh project context before overwriting it.")}return Pe(n,l,true),{allowed:true,pending:l}}function Ce(n,t,e,o){return Pe(n,t,false,e),{allowed:false,reasonCode:e,reason:o,pending:t}}function Pe(n,t,e,o){m({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 rn(n,t){if(n==="Read")return "read";if(n==="Edit"||n==="NotebookEdit")return "edit";if(n==="Write")return "write";if(n==="Delete"||n==="Bash"&&Me(t.command))return "delete"}function sn(n,t,e){let o=an(e,["file_path","filePath","notebook_path","path","targetPath"])??(t==="Bash"?Me(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 Me(n){return typeof n!="string"?void 0:/(?:^|[;&|]\s*)\s*(?:rm|unlink)\s+(?:-[A-Za-z]+\s+)*(?:--\s+)?(["']?)([^\s;&|"']+)\1/u.exec(n)?.[2]}function an(n,t){for(let e of t){let o=n[e];if(typeof o=="string"&&o.trim())return o.trim()}}function cn(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 ln(n,t,e){return (isAbsolute(t)?normalize(t):resolve(n,t))===normalize(e)}function Le(n){return join(f(n),"file-state")}function $e(n){return join(Le(n),"pending.json")}function dn(n){return join(Le(n),"observations.jsonl")}function un(n){try{return JSON.parse(readFileSync$1($e(n),"utf8"))}catch{return {}}}function pn(n,t){let e=$e(n);mkdirSync$1(dirname(e),{recursive:true});let o=un(n);o[t.toolUseId]=t,fn(e,JSON.stringify(o));}function gn(n,t){try{let e=readFileSync$1(dn(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 fn(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 Ne(n){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:n}}}function _n(n){let t=f(n);return existsSync(t)||mkdirSync(t,{recursive:true}),t}function Rn(n,t,e,o,r,i){let s=join$1(_n(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 En(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 xn(n){let t=ue();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 Ne(U);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?xe(I):null;if(v){let qe=a.get(s)?.executionId,R=a.startExecution(s,v,re(v));R.executionId&&R.executionId!==qe&&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=Ae({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:r}),L=je({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}:L.allowed?p.evaluate(e.tool_name,d):{permissionDecision:"deny",reason:L.reason,reasonCode:L.reasonCode};h.permissionDecision==="deny"?g={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:h.reason??"MCP context required"}}:h.additionalContext?g=Ne(h.additionalContext):g=E(),e.tool_name.startsWith("mcp__devflow__")&&(g.hookSpecificOutput.updatedInput=e.tool_input),t&&g.hookSpecificOutput.permissionDecision==="allow"&&(g.hookSpecificOutput.additionalContext=U);let He=c?.executionId??s,_={eventId:we(s,e.tool_use_id),executionId:He,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:En(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&&Rn(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=ce(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()};de(le(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 xn(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{xn as handlePreToolUse};
|
|
@@ -1,109 +1 @@
|
|
|
1
|
-
import {
|
|
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"),L(n),n.exec(`
|
|
4
|
-
INSERT INTO server_bootstrap_state (
|
|
5
|
-
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
6
|
-
created_at, updated_at
|
|
7
|
-
)
|
|
8
|
-
SELECT
|
|
9
|
-
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
10
|
-
created_at, updated_at
|
|
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||L(n);return n}function L(e){e.exec(`
|
|
13
|
-
CREATE TABLE IF NOT EXISTS server_bootstrap_state (
|
|
14
|
-
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
15
|
-
token TEXT NOT NULL,
|
|
16
|
-
state TEXT NOT NULL CHECK (state IN ('launching', 'running', 'terminating')),
|
|
17
|
-
owner_pid INTEGER NOT NULL,
|
|
18
|
-
wrapper_pid INTEGER,
|
|
19
|
-
process_group_id INTEGER,
|
|
20
|
-
server_pid INTEGER,
|
|
21
|
-
created_at INTEGER NOT NULL,
|
|
22
|
-
updated_at INTEGER NOT NULL
|
|
23
|
-
)
|
|
24
|
-
`);}function oe(e){return e.prepare(`
|
|
25
|
-
SELECT
|
|
26
|
-
token,
|
|
27
|
-
state,
|
|
28
|
-
owner_pid AS ownerPid,
|
|
29
|
-
wrapper_pid AS wrapperPid,
|
|
30
|
-
process_group_id AS processGroupId,
|
|
31
|
-
server_pid AS serverPid,
|
|
32
|
-
created_at AS createdAt,
|
|
33
|
-
updated_at AS updatedAt
|
|
34
|
-
FROM server_bootstrap_state
|
|
35
|
-
WHERE id = 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
|
-
UPDATE server_bootstrap_state
|
|
39
|
-
SET state = 'running', owner_pid = ?, wrapper_pid = ?, process_group_id = ?, server_pid = ?,
|
|
40
|
-
updated_at = ?
|
|
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=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
|
-
DELETE FROM server_bootstrap_state
|
|
44
|
-
WHERE id = 1 AND token = ? AND state = 'running'
|
|
45
|
-
`).run(r.token);}return e.exec("COMMIT"),n=!1,{action:"skip"}}if(r?.state==="launching"){if(T(r.ownerPid))return e.exec("COMMIT"),n=!1,{action:"skip"};let s=r.processGroupId??void 0,i=E(r.token,s);if(i){let u=e.prepare(`
|
|
46
|
-
UPDATE server_bootstrap_state
|
|
47
|
-
SET state = 'running', owner_pid = ?, wrapper_pid = ?, process_group_id = ?,
|
|
48
|
-
server_pid = ?, updated_at = ?
|
|
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(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
|
-
UPDATE server_bootstrap_state
|
|
52
|
-
SET state = 'terminating', owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
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(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
|
-
DELETE FROM server_bootstrap_state
|
|
56
|
-
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
57
|
-
`).run(r.token,r.ownerPid);}else if(r?.state==="terminating"){if(T(r.ownerPid))return e.exec("COMMIT"),n=!1,{action:"skip"};let s=R(r.token);if(s){let i=e.prepare(`
|
|
58
|
-
UPDATE server_bootstrap_state
|
|
59
|
-
SET owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
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(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
|
-
DELETE FROM server_bootstrap_state
|
|
63
|
-
WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
|
|
64
|
-
`).run(r.token,r.ownerPid);}else if(r?.state==="running"){let s=E(r.token);if(s)return e.prepare(`
|
|
65
|
-
UPDATE server_bootstrap_state
|
|
66
|
-
SET owner_pid = ?, wrapper_pid = ?, process_group_id = ?, server_pid = ?, updated_at = ?
|
|
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&&!T(r.ownerPid)){let a=e.prepare(`
|
|
69
|
-
UPDATE server_bootstrap_state
|
|
70
|
-
SET state = 'terminating', owner_pid = ?, process_group_id = ?, updated_at = ?
|
|
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(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
|
-
DELETE FROM server_bootstrap_state
|
|
74
|
-
WHERE id = 1 AND token = ? AND state = 'running' AND owner_pid = ?
|
|
75
|
-
`).run(r.token,r.ownerPid);}let o=randomUUID(),c=Date.now();return e.prepare(`
|
|
76
|
-
INSERT INTO server_bootstrap_state (
|
|
77
|
-
id, token, state, owner_pid, wrapper_pid, process_group_id, server_pid,
|
|
78
|
-
created_at, updated_at
|
|
79
|
-
) VALUES (1, ?, 'launching', ?, NULL, NULL, NULL, ?, ?)
|
|
80
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
81
|
-
token = excluded.token,
|
|
82
|
-
state = 'launching',
|
|
83
|
-
owner_pid = excluded.owner_pid,
|
|
84
|
-
wrapper_pid = NULL,
|
|
85
|
-
process_group_id = NULL,
|
|
86
|
-
server_pid = NULL,
|
|
87
|
-
created_at = excluded.created_at,
|
|
88
|
-
updated_at = excluded.updated_at
|
|
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
|
-
UPDATE server_bootstrap_state
|
|
92
|
-
SET wrapper_pid = ?, process_group_id = ?, server_pid = NULL, updated_at = ?
|
|
93
|
-
WHERE id = 1 AND token = ? AND state = 'launching' AND owner_pid = ?
|
|
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
|
-
UPDATE server_bootstrap_state
|
|
96
|
-
SET state = 'running', wrapper_pid = ?, process_group_id = ?, server_pid = ?,
|
|
97
|
-
updated_at = ?
|
|
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(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
|
-
DELETE FROM server_bootstrap_state
|
|
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 we(e,n,t){let r=false;try{e.exec("BEGIN IMMEDIATE"),r=!0;let o=e.prepare(`
|
|
103
|
-
UPDATE server_bootstrap_state
|
|
104
|
-
SET state = 'terminating', owner_pid = ?, updated_at = ?
|
|
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,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
|
-
DELETE FROM server_bootstrap_state
|
|
108
|
-
WHERE id = 1 AND token = ? AND state = 'terminating' AND owner_pid = ?
|
|
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;});
|
|
1
|
+
import {getDevFlowStateRoot,createRuntimeManager}from'@devflow-tools/sdk';import {emitSemanticControlLog}from'@devflow-tools/telemetry';import {existsSync}from'node:fs';import {createRequire}from'node:module';import {join}from'node:path';var i=emitSemanticControlLog;join(getDevFlowStateRoot(),"runtime","hook-session-refs.json");function n(e){let t=createRequire(import.meta.url),s=[process.env.DEVFLOW_SERVER_ENTRY,v(()=>t.resolve("@devflow-tools/server/dist/main.js")),join(e,"node_modules","@devflow-tools","server","dist","main.js"),join(e,"apps","server","dist","main.js")].filter(a=>!!a).find(existsSync);if(!s)throw new Error("DevFlow server entry point is not installed or built");return {command:process.execPath,args:[s],cwd:e}}function v(e){try{return e()}catch{return}}async function u(e=process.env.CLAUDE_PROJECT_DIR?.trim()||process.cwd()){try{await createRuntimeManager().ensureRunning({reason:"hook",projectRoot:e,server:n(e)});}catch(t){let o=typeof t=="object"&&t&&"code"in t?String(t.code):"RUNTIME_PROCESS_EXITED";i({event:"context.build.degraded",identity:{projectRoot:e},level:"warn",timestamp:Date.now(),data:{reason:o}});}}(process.argv[1]?.endsWith("server-bootstrap.js")||process.argv[1]?.endsWith("server-bootstrap.ts"))&&u();export{u as bootstrapServer};
|