@devflow-tools/devflow 0.18.73 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/acceptance-manifest.json +24 -6
- package/dist/cli.js +77 -72
- package/dist/dashboard/404.html +1 -1
- package/dist/dashboard/__next.__PAGE__.txt +1 -1
- package/dist/dashboard/__next._full.txt +1 -1
- package/dist/dashboard/__next._tree.txt +1 -1
- package/dist/dashboard/_next/static/chunks/{968-e7efadf9f1a30259.js → 968-98c23a99cb0f4832.js} +2 -2
- package/dist/dashboard/_next/static/chunks/app/intelligence/{memory/page-d74930294a785071.js → knowledge/page-433475a9552451da.js} +1 -1
- package/dist/dashboard/_next/static/chunks/app/intelligence/{page-d74930294a785071.js → memory/page-433475a9552451da.js} +1 -1
- package/dist/dashboard/_next/static/chunks/app/intelligence/{knowledge/page-d74930294a785071.js → page-433475a9552451da.js} +1 -1
- package/dist/dashboard/_next/static/chunks/{main-09b1ccc91836f96c.js → main-2bb696a9b2dd088b.js} +1 -1
- package/dist/dashboard/_not-found/__next._full.txt +1 -1
- package/dist/dashboard/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/dist/dashboard/_not-found/__next._tree.txt +1 -1
- package/dist/dashboard/_not-found.html +1 -1
- package/dist/dashboard/_not-found.txt +1 -1
- package/dist/dashboard/accuracy/__next._full.txt +1 -1
- package/dist/dashboard/accuracy/__next._tree.txt +1 -1
- package/dist/dashboard/accuracy/__next.accuracy.__PAGE__.txt +1 -1
- package/dist/dashboard/accuracy.html +1 -1
- package/dist/dashboard/accuracy.txt +1 -1
- package/dist/dashboard/benchmark/__next._full.txt +1 -1
- package/dist/dashboard/benchmark/__next._tree.txt +1 -1
- package/dist/dashboard/benchmark/__next.benchmark.__PAGE__.txt +1 -1
- package/dist/dashboard/benchmark.html +1 -1
- package/dist/dashboard/benchmark.txt +1 -1
- package/dist/dashboard/context/__next._full.txt +1 -1
- package/dist/dashboard/context/__next._tree.txt +1 -1
- package/dist/dashboard/context/__next.context.__PAGE__.txt +1 -1
- package/dist/dashboard/context.html +1 -1
- package/dist/dashboard/context.txt +1 -1
- package/dist/dashboard/doctor/__next._full.txt +1 -1
- package/dist/dashboard/doctor/__next._tree.txt +1 -1
- package/dist/dashboard/doctor/__next.doctor.__PAGE__.txt +1 -1
- package/dist/dashboard/doctor.html +1 -1
- package/dist/dashboard/doctor.txt +1 -1
- package/dist/dashboard/executions/__next._full.txt +1 -1
- package/dist/dashboard/executions/__next._tree.txt +1 -1
- package/dist/dashboard/executions/__next.executions.__PAGE__.txt +1 -1
- package/dist/dashboard/executions.html +1 -1
- package/dist/dashboard/executions.txt +1 -1
- package/dist/dashboard/graph/__next._full.txt +1 -1
- package/dist/dashboard/graph/__next._tree.txt +1 -1
- package/dist/dashboard/graph/__next.graph.__PAGE__.txt +1 -1
- package/dist/dashboard/graph.html +1 -1
- package/dist/dashboard/graph.txt +1 -1
- package/dist/dashboard/index.html +1 -1
- package/dist/dashboard/index.txt +1 -1
- package/dist/dashboard/intelligence/__next._full.txt +2 -2
- package/dist/dashboard/intelligence/__next._tree.txt +1 -1
- package/dist/dashboard/intelligence/__next.intelligence.__PAGE__.txt +2 -2
- package/dist/dashboard/intelligence/knowledge/__next._full.txt +2 -2
- package/dist/dashboard/intelligence/knowledge/__next._tree.txt +1 -1
- package/dist/dashboard/intelligence/knowledge/__next.intelligence.knowledge.__PAGE__.txt +2 -2
- package/dist/dashboard/intelligence/knowledge.html +1 -1
- package/dist/dashboard/intelligence/knowledge.txt +2 -2
- package/dist/dashboard/intelligence/memory/__next._full.txt +2 -2
- package/dist/dashboard/intelligence/memory/__next._tree.txt +1 -1
- package/dist/dashboard/intelligence/memory/__next.intelligence.memory.__PAGE__.txt +2 -2
- package/dist/dashboard/intelligence/memory.html +1 -1
- package/dist/dashboard/intelligence/memory.txt +2 -2
- package/dist/dashboard/intelligence.html +1 -1
- package/dist/dashboard/intelligence.txt +2 -2
- package/dist/dashboard/knowledge/__next._full.txt +1 -1
- package/dist/dashboard/knowledge/__next._tree.txt +1 -1
- package/dist/dashboard/knowledge/__next.knowledge.__PAGE__.txt +1 -1
- package/dist/dashboard/knowledge.html +1 -1
- package/dist/dashboard/knowledge.txt +1 -1
- package/dist/dashboard/memory/__next._full.txt +1 -1
- package/dist/dashboard/memory/__next._tree.txt +1 -1
- package/dist/dashboard/memory/__next.memory.__PAGE__.txt +1 -1
- package/dist/dashboard/memory.html +1 -1
- package/dist/dashboard/memory.txt +1 -1
- package/dist/dashboard/replay/__next._full.txt +1 -1
- package/dist/dashboard/replay/__next._tree.txt +1 -1
- package/dist/dashboard/replay/__next.replay.__PAGE__.txt +1 -1
- package/dist/dashboard/replay.html +1 -1
- package/dist/dashboard/replay.txt +1 -1
- package/dist/dashboard/runs/_/__next._full.txt +1 -1
- package/dist/dashboard/runs/_/__next._tree.txt +1 -1
- package/dist/dashboard/runs/_/__next.runs.$d$id.__PAGE__.txt +1 -1
- package/dist/dashboard/runs/_.html +1 -1
- package/dist/dashboard/runs/_.txt +1 -1
- package/dist/dashboard/runs/__next._full.txt +1 -1
- package/dist/dashboard/runs/__next._tree.txt +1 -1
- package/dist/dashboard/runs/__next.runs.__PAGE__.txt +1 -1
- package/dist/dashboard/runs.html +1 -1
- package/dist/dashboard/runs.txt +1 -1
- package/dist/dashboard/settings/__next._full.txt +1 -1
- package/dist/dashboard/settings/__next._tree.txt +1 -1
- package/dist/dashboard/settings/__next.settings.__PAGE__.txt +1 -1
- package/dist/dashboard/settings.html +1 -1
- package/dist/dashboard/settings.txt +1 -1
- package/dist/dashboard/timeline/__next._full.txt +1 -1
- package/dist/dashboard/timeline/__next._tree.txt +1 -1
- package/dist/dashboard/timeline/__next.timeline.__PAGE__.txt +1 -1
- package/dist/dashboard/timeline.html +1 -1
- package/dist/dashboard/timeline.txt +1 -1
- package/dist/dashboard/tool-metrics/__next._full.txt +1 -1
- package/dist/dashboard/tool-metrics/__next._tree.txt +1 -1
- package/dist/dashboard/tool-metrics/__next.tool-metrics.__PAGE__.txt +1 -1
- package/dist/dashboard/tool-metrics.html +1 -1
- package/dist/dashboard/tool-metrics.txt +1 -1
- package/dist/dashboard/workflows/__next._full.txt +1 -1
- package/dist/dashboard/workflows/__next._tree.txt +1 -1
- package/dist/dashboard/workflows/__next.workflows.__PAGE__.txt +1 -1
- package/dist/dashboard/workflows.html +1 -1
- package/dist/dashboard/workflows.txt +1 -1
- package/dist/hooks/hook-daemon.js +28 -27
- package/dist/hooks/post-tool-use-failure.js +2 -2
- package/dist/hooks/post-tool-use.js +4 -4
- package/dist/hooks/pre-tool-use.js +5 -4
- package/dist/hooks/session-end.js +6 -6
- package/dist/hooks/stop.js +9 -9
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/dist/command-registry.json +7 -7
- package/dist/plugin/dist/hooks/hook-daemon.js +28 -27
- package/dist/plugin/dist/hooks/post-tool-use-failure.js +2 -2
- package/dist/plugin/dist/hooks/post-tool-use.js +4 -4
- package/dist/plugin/dist/hooks/pre-tool-use.js +5 -4
- package/dist/plugin/dist/hooks/session-end.js +6 -6
- package/dist/plugin/dist/hooks/stop.js +9 -9
- package/dist/plugin/dist/runtime-manifest.json +7 -7
- package/dist/plugin/hooks/README.md +15 -0
- package/dist/plugin/hooks/constitution.md +7 -16
- package/dist/plugin/hooks/hooks.json +11 -6
- package/dist/plugin/hooks/post-tool-use +7 -0
- package/dist/plugin/hooks/post-tool-use-failure +7 -0
- package/dist/plugin/hooks/pre-compact +7 -0
- package/dist/plugin/hooks/pre-tool-use +17 -9
- package/dist/plugin/hooks/runtime-node +11 -0
- package/dist/plugin/hooks/session-end +7 -0
- package/dist/plugin/hooks/session-start +28 -27
- package/dist/plugin/hooks/stop +7 -0
- package/dist/plugin/hooks/user-prompt-submit +7 -0
- package/dist/plugin/package.json +14 -14
- package/package.json +17 -17
- package/plugin-registry.json +29 -29
- /package/dist/dashboard/_next/static/{Pxwskm195oqVNNqbq-7Fo → x_Tki-qOI_7GKLgz0OV8p}/_buildManifest.js +0 -0
- /package/dist/dashboard/_next/static/{Pxwskm195oqVNNqbq-7Fo → x_Tki-qOI_7GKLgz0OV8p}/_ssgManifest.js +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {createHash as createHash$1}from'node:crypto';import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync,rmSync,linkSync,renameSync,statSync}from'fs';import {join as join$1,dirname as dirname$1}from'path';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {getLocalApiKey,getDevFlowStateRoot,projectClaudeToolName,resolveClaudeToolName,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir,readRuntimeState}from'@devflow-tools/sdk';import {request}from'node:http';import {existsSync
|
|
2
|
-
`;rotateDiagnosticLogFile({path:e,maxBytes:50*1024*1024,maxFiles:5,incomingBytes:Buffer.byteLength(n)}),appendFileSync(e,n);}catch{}}function gt(i){return new Promise(t=>setTimeout(t,i))}var pe=1e4,bt=3e4,U=500,H=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,n,o,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let c={executionId:t,sessionId:e,skillName:n,startedAt:o,projectRoot:r,requiredMcpTools:s};this.commitOrCache("execution_start",c)&&this.postHttp("/api/telemetry/skill-execution/start",c);}async sendExecutionComplete(t,e="completed",n=Date.now(),o){let r={executionId:t,status:e,finishedAt:n,metadata:o},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(t,e,n){let o={id:t,projectRoot:e,startedAt:n,label:e.split("/").pop()??"unknown"},r=this.commitOrCache("session_start",o);return r&&this.postHttp("/api/telemetry/sessions",o),r}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let n={sessionId:t,finishedAt:e},o=this.commitOrCache("session_end",n);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),o}async flushCache(){try{let e=this.getDatabase(),n=e.listTelemetryFailures({unresolvedOnly:!0,limit:U}).reverse();for(let o of n)try{this.applyOperation(o.operation,o.payload),e.resolveTelemetryFailure(o.id);}catch{}e.trimTelemetryFailures(U);}catch{}let t=(existsSync(this.cacheDir)?readdirSync(this.cacheDir):[]).filter(e=>e.endsWith(".json")).map(e=>{let n=join$1(this.cacheDir,e);try{return {cacheFile:n,envelope:_t(JSON.parse(readFileSync(n,"utf8")))}}catch{return null}}).filter(e=>e!==null).sort((e,n)=>e.envelope.timestamp-n.envelope.timestamp||ge(e.envelope.operation)-ge(n.envelope.operation));for(let{cacheFile:e,envelope:n}of t)try{let o=this.getDatabase();o.insertTelemetryFailure({id:n.id,operation:n.operation,payload:n.payload,error:n.failure,createdAt:n.timestamp}),this.applyOperation(n.operation,n.payload),o.resolveTelemetryFailure(n.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(n){return this.cacheOperation(t,e,n),false}}applyOperation(t,e){let n=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(n,e),n.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(n,e),n.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":n.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":n.ensureSession(e),n.insertRun({id:fe(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!n.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,failureCategory:e.failureCategory,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":n.closeSession(e.sessionId,e.finishedAt),n.updateRun(fe(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let n=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!n)throw new Error("Canonical session ID is required for telemetry");let o=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:n,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,n){let o=Date.now(),r={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:o};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:o}),s.trimTelemetryFailures(U),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(r,null,2),{mode:384}),this.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-U)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},bt).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(t,e){ce(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=pe?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,pe)}...`}}};function ge(i){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(i)}function fe(i){return `hook-run:${i}`}function _t(i){if(!i||typeof i!="object")throw new Error("Invalid telemetry cache envelope");let t=i;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 T(i){return i??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function w(i){return getProjectStateDir(T(i))}var D=emitSemanticControlLog;var kt=2,St=1;function Ot(){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 me(i=Ot()){let t=[join$1(i,"dist","command-registry.json"),join$1(i,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let n=JSON.parse(readFileSync(e,"utf8"));if(n.version!==kt&&n.version!==St||!At(n.commands)){D({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:"contract_mismatch",registryPath:e}});continue}return n.commands}catch(n){D({event:"hook.runtime.degraded",identity:{projectRoot:process.env.CLAUDE_PROJECT_DIR||process.cwd()},level:"warn",timestamp:Date.now(),data:{stage:"command_registry",reason:n.message,fallback:"next_registry_candidate"}});}return null}function At(i){return !i||typeof i!="object"||Array.isArray(i)?false:Object.values(i).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return q(e.mcpTools)&&q(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||q(e.runtimePackages))&&(e.hostTools===void 0||Ct(e.hostTools))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function Ct(i){return !!i&&typeof i=="object"&&!Array.isArray(i)&&Object.entries(i).every(([t,e])=>t.length>0&&q(e))}function q(i){return Array.isArray(i)&&i.every(t=>typeof t=="string"&&t.length>0)}function he(i){let t=me();return t?t[i]?.mcpTools??[]:[]}function _e(i){return Buffer.from(i,"utf8").toString("base64url")}function jt(i,t,e){let n=t?.trim();if(n){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(n)?n:`tool-${createHash("sha256").update(n.slice(0,1024)).digest("hex").slice(0,32)}`;return `${i}:${o}`}return `${i}:legacy-${e}-${randomUUID().slice(0,8)}`}function xe(i){return `${i}:legacy-journal`}var S=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(w(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let n=this.get(e);if(n)return n.lastActivityAt=Date.now(),this.persist(n),n;let o=Date.now(),r={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:o,lastActivityAt:o};return this.sessions.set(e,r),this.persist(r),r}startExecution(t,e,n){let o=this.registerSession(t);return (!o.executionId||o.skillName!==e)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=e,o.requiredMcpTools=[...new Set(n)],delete o.contextInitialization,o.lastActivityAt=Date.now(),this.persist(o),o}beginContextInitialization(t,e){let n=this.registerSession(t);return n.contextInitialization={startedAt:Date.now(),...e?{toolUseId:e}:{}},n.lastActivityAt=Date.now(),this.persist(n),n}completeContextInitialization(t,e){let n=this.get(t);return n?(e&&n.contextInitialization?.toolUseId&&n.contextInitialization.toolUseId!==e||(delete n.contextInitialization,n.lastActivityAt=Date.now(),this.persist(n)),n):null}bindTaskIdentity(t,e){let n=this.registerSession(t);return n.activeTurnId=e.turnId,n.activeRequestId=e.requestId,n.intentArtifactHash=e.intentArtifactHash,n.lastActivityAt=Date.now(),this.persist(n),n}get(t){let e=t.trim();if(!e)return null;let n=this.sessions.get(e);if(n)return this.replayEvidenceJournal(n),n;let o=this.snapshotPath(e);if(!existsSync(o))return null;try{let r=JSON.parse(readFileSync(o,"utf8"));return r.sessionId!==e||r.projectRoot!==this.projectRoot?null:(r.requiredMcpTools=Array.isArray(r.requiredMcpTools)?r.requiredMcpTools:[],r.evidenceObligations=Re(r.evidenceObligations),r.evidenceDegradations=Ee(r.evidenceDegradations),r.evidenceOutcomes=we(r.evidenceOutcomes),this.replayEvidenceJournal(r),this.sessions.set(e,r),r)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let n=structuredClone(e);return delete e.executionId,delete e.skillName,delete e.contextInitialization,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),n}addEvidenceObligation(t,e,n=Date.now(),o){let r=this.registerSession(t),c=(o?void 0:r.evidenceObligations.find(l=>l.contractId===e.id))?.obligationId??jt(e.id,o,n);this.appendEvidenceEvent(t,{kind:"add",obligationId:c,contractId:e.id,at:n,contract:e},`add\0${c}`),this.replayEvidenceJournal(r);let a=r.evidenceObligations.find(l=>l.obligationId===c);return a?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(a)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,n,o,r=Date.now()){let s=this.get(t),c=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!c)return null;let a=/^[a-f0-9]{64}$/.test(o)?o:"";if(!a)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:c.contractId,at:r,fingerprint:a,violations:n.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${a}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let l=s.evidenceObligations.find(d=>d.obligationId===e);return l?structuredClone(l):null}resolveEvidenceObligation(t,e){let n=this.get(t);if(!n)return false;let o=n.evidenceObligations.find(s=>s.obligationId===e);if(!o)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve\0${e}`),this.replayEvidenceJournal(n),n.lastActivityAt=r,this.persist(n),true}resolveDegradedEvidence(t,e){let n=this.get(t),o=n?.evidenceDegradations.find(s=>s.obligationId===e);if(!n||!o)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve-degraded\0${e}\0${r}`),this.replayEvidenceJournal(n),n.lastActivityAt=r,this.persist(n),true}degradeEvidenceObligation(t,e,n,o=Date.now()){let r=this.get(t),s=r?.evidenceObligations.find(a=>a.obligationId===e);if(!r||!s)return false;let c=n.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:o,reason:c},`degrade\0${e}\0${c}`),this.replayEvidenceJournal(r),r.lastActivityAt=o,this.persist(r),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${_e(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",_e(t))}appendEvidenceEvent(t,e,n){let o=this.evidenceJournalDir(t);mkdirSync(o,{recursive:true,mode:448});let r=createHash("sha256").update(n).digest("hex"),s=join$1(o,`${e.kind}-${r}.json`);if(existsSync(s))return;let c=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(c,JSON.stringify(e),{mode:384});try{linkSync(c,s);}catch(a){if(a.code!=="EEXIST")throw a}finally{rmSync(c,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Re(t.evidenceObligations),t.evidenceDegradations=Ee(t.evidenceDegradations),t.evidenceOutcomes=we(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let n;try{n=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let o=n.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let c=Pt(JSON.parse(s));return c?[c]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||De(r.kind)-De(s.kind));for(let r of o)this.applyEvidenceEvent(t,r);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let n=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(n)return;let s=t.evidenceObligations.find(c=>c.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let o=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!o||n||o.correctionFingerprint===e.fingerprint)return;o.attempt+=1,o.correctionRequested=true,o.correctionRequestedAt=e.at,o.correctionFingerprint=e.fingerprint,o.violations=e.violations;return}let r=o?.attempt??n?.attempt??0;if(e.kind==="resolve"&&n?.status==="degraded")t.evidenceOutcomes=t.evidenceOutcomes.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations=t.evidenceDegradations.filter(s=>s.obligationId!==e.obligationId);else if(n)return;e.kind==="degrade"?(t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r,contract:o?.contract})):t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}});}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),n=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(n,JSON.stringify(t),{mode:384}),renameSync(n,e);}};function Re(i){return Array.isArray(i)?i.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!ke(e.contract))return [];let n=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:xe(e.contractId),o=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,r=e.correctionFingerprint??o;return r!==void 0&&!/^[a-f0-9]{64}$/.test(r)?[]:[{...e,obligationId:n,correctionFingerprint:r}]}).slice(-8):[]}function Ee(i){return Array.isArray(i)?i.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function we(i){return Array.isArray(i)?i.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(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 Pt(i){if(!i||typeof i!="object")return null;let t=i,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let o={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:xe(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return ke(t.contract)?{kind:e,...o,contract:t.contract}:null;if(e==="correction"){let r=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)&&Array.isArray(t.violations)&&t.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:e,...o,fingerprint:r,violations:t.violations}:null}return e==="resolve"?{kind:e,...o}:typeof t.reason=="string"&&t.reason.length<=240?{kind:e,...o,reason:t.reason}:null}function De(i){return i==="add"?0:i==="correction"?1:2}function ke(i){if(!i||typeof i!="object")return false;let t=i,e=t.requiredSections,n=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(n)&&n.length<=16&&n.every(o=>typeof o=="string"&&o.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function J(i){if(!i||typeof i!="object"||Array.isArray(i))return {};let t=i,e={};for(let n of ["lastMcpCall","bypassCount"])if(n in t){let o=t[n];if(o==null)continue;e[n]=typeof o=="number"&&Number.isFinite(o)&&o>=0?o:0;}return e}function $t(i,t){return i.lastMcpCall===t.lastMcpCall&&i.bypassCount===t.bypassCount}function Se(i,t,e){let n=e instanceof Error?e.message:String(e);D({event:"hook.runtime.degraded",identity:{projectRoot:i},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:n,fallback:"fail_open"}});}function Oe(i,t,e){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let o={},r=n.updateHookReceipt(i,c=>(o=J(c),J(t(o)))),s=J(r);return {receipt:s,applied:!0,changed:!$t(o,s)}}catch(o){return Se(i,e,o),{receipt:{},applied:false,changed:false}}finally{try{n?.close();}catch{}}}function Ae(i){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),J(t.getHookReceipt(i))}catch(e){return Se(i,"update",e),{}}finally{try{t?.close();}catch{}}}function Mt(i,t){return Oe(i,()=>t,"write").applied}function Nt(i,t){return Oe(i,t,"update")}var Q={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},Ut=new Set(["Write","Edit","NotebookEdit"]),Ht=new Set(["failed","timeout","unavailable"]);function qt(i){switch(i){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var B=class{constructor(t,e,n){this.projectRoot=t;this.sessionId=e;this.executionId=n;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let n=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(n&&n.expiresAt>Date.now())return "context_ready";n&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}let e=new S(this.projectRoot).get(this.sessionId);return e?.executionId===this.executionId&&e.contextInitialization?"context_initializing":"context_gathering"}getContextReceipt(){if(!this.sessionId||!this.executionId)return null;let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);return e&&e.expiresAt>Date.now()?e:(e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId),null)}catch{return null}finally{try{t?.close();}catch{}}}evaluate(t,e){let n=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(n==="context_initializing"&&Q[t])return {permissionDecision:"deny",reasonCode:"DEVFLOW_CONTEXT_INITIALIZING",reason:`DevFlow context initialization is in progress. Wait for ${projectClaudeToolName("get_project_context")} to complete, then retry ${t}.`};if(n==="context_gathering"&&Q[t])return {permissionDecision:"deny",reasonCode:"DEVFLOW_CONTEXT_REQUIRED",reason:`DevFlow context required. Call ${projectClaudeToolName("get_project_context")}, then retry ${t}.`};if(n==="context_ready"){if(Ut.has(t)){let a=this.evaluateRequiredAction();if(a)return a}return {permissionDecision:"allow"}}let o=Q[t];if(!o)return {permissionDecision:"allow"};let r=Nt(this.projectRoot,a=>({...a,bypassCount:(a.bypassCount??0)+1}));if(!r.applied)return {permissionDecision:"allow"};let s=r.receipt.bypassCount??0,c=qt(t);return s>=c?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 ${projectClaudeToolName(o)} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){Mt(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(t,e,n,o){if(!this.sessionId||!this.executionId)return false;let r;try{r=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let s=r.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(!s||s.expiresAt<=Date.now()||s.canonicalAction?.tool!==t)return !1;let c=Date.now(),a=o?.trim()?`${o.trim()}:${e}`:`${t}:${e}:${c}`,l=s.actionAttempts??[];return r.upsertContextReceipt({...s,actionAttempts:l.some(d=>d.id===a||o&&d.toolUseId===o&&d.status===e)?l:[...l,{id:a,tool:t,status:e,attemptedAt:c,toolUseId:o,reason:n?.slice(0,500)}].slice(-20),actionSatisfiedAt:e==="succeeded"?c:s.actionSatisfiedAt,actionDegradation:e==="succeeded"?void 0:s.actionDegradation}),!0}catch{return false}finally{try{r?.close();}catch{}}}evaluateRequiredAction(){let t=this.getContextReceipt(),e=t?.canonicalAction;if(!t||!e||!e.required||e.status!=="required")return null;let n=e.binding;if(n.requiredContextReceipt!==t.contextHash||n.projectRoot!==this.projectRoot||n.sessionId!==this.sessionId||n.requestId!==t.requestId||n.executionId&&n.executionId!==this.executionId)return {permissionDecision:"deny",reasonCode:"DEVFLOW_ACTION_BINDING_STALE",reason:`DevFlow canonical action binding is stale or mismatched. Call ${projectClaudeToolName("get_project_context")} again before writing.`};if(t.actionSatisfiedAt)return null;if(t.actionDegradation?.authorizedByContextReceipt===t.contextHash)return {permissionDecision:"allow",additionalContext:`DevFlow degraded fallback authorized by context receipt ${t.contextHash}: ${t.actionDegradation.reason}`};let o=(t.actionAttempts??[]).filter(r=>r.tool===e.tool&&Ht.has(r.status));if(o.length>0){let r=o.at(-1),s={missedTool:e.tool,failedAttemptCount:o.length,reason:`${r.status}:${r.reason??"canonical domain action did not complete"}`,authorizedByContextReceipt:t.contextHash,authorizedAt:Date.now()};return this.persistDegradation(t,s),{permissionDecision:"allow",additionalContext:`DevFlow canonical tool ${projectClaudeToolName(e.tool)} ${r.status}; degraded direct write authorized by context receipt ${t.contextHash}. Preserve the action contract and verification plan.`}}return {permissionDecision:"deny",reasonCode:"DEVFLOW_REQUIRED_ACTION",reason:`DevFlow required action not completed. Call ${projectClaudeToolName(e.tool)} using context receipt ${t.contextHash}, then retry the write. Direct fallback is allowed only after unavailable, failed, or timeout evidence.`}}persistDegradation(t,e){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let o=n.getContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!o||o.contextHash!==t.contextHash||o.actionDegradation)return;n.upsertContextReceipt({...o,actionDegradation:e});let r=n.getSkillExecution(t.executionId);if(!r)return;let s=r.metadata&&typeof r.metadata=="object"?r.metadata:{},c=Array.isArray(s.requiredActionDegradations)?s.requiredActionDegradations:[];n.updateSkillExecution(t.executionId,{missedMcpTools:[...new Set([...r.missedMcpTools??[],e.missedTool])],failedToolCalls:Math.max(r.failedToolCalls??0,e.failedAttemptCount),fallbackCount:(r.fallbackCount??0)+1,fallbackReasons:[...new Set([...r.fallbackReasons??[],`required_action_${e.reason}`])],metadata:{...s,requiredActionDegradations:[...c,e]}});}catch{}finally{try{n?.close();}catch{}}}};var Xt=10*1024*1024,Qt=5;function Zt(i){return createHash$1("sha256").update(i).digest("hex").slice(0,16)}function Ce(i){return join(homedir(),".devflow","logs","hook-debug",`${Zt(i)}.jsonl`)}function Te(i,t,e={}){let n=e.maxBytes??Xt,o=e.maxFiles??Qt;mkdirSync$1(dirname(i),{recursive:true,mode:448});let r=Buffer.byteLength(t);rotateDiagnosticLogFile({path:i,maxBytes:n,maxFiles:o,incomingBytes:r}),appendFileSync(i,t,{mode:384}),chmodSync(i,384);}var Z="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 Le(i){let t=i.trim().replace(/^\//,"");if(!t.startsWith("devflow:"))return null;let e=t.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(e)?`devflow:${e.toLowerCase()}`:null}function je(i,t){return t?`evt_tool_${createHash("sha256").update(`${i}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var rn=new Set(["Write","Edit","NotebookEdit"]),Pe=`Claude native memory writes are disabled for this project. Use DevFlow explicit memory or ${projectClaudeToolName("memory_commit_turn")} so a canonical receipt is created.`;function He(i){if(!rn.has(i.toolName))return null;let t=sn(i.toolInput);if(!t)return null;let e=an(t,i.projectRoot),n=resolve(i.projectRoot,".claude");if($e(e,n)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return Pe;let o=resolve(i.home??homedir(),".claude","projects");return $e(e,o)&&relative(o,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?Pe:null}function sn(i){for(let t of ["file_path","notebook_path","path"]){let e=i[t];if(typeof e=="string"&&e.trim())return e.trim()}return null}function an(i,t){return resolve(isAbsolute(i)?i:resolve(t,i))}function $e(i,t){let e=relative(t,i);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function Be(i){let t=mn(i.toolName,i.toolInput),e=t?hn(i.projectRoot,i.toolName,i.toolInput):void 0;if(!t||!e||!i.toolUseId)return {allowed:true};let n=vn(e),o,r=0,s,c;try{c=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:100,readonly:!0});let l=c.getActiveContextReceipt(i.projectRoot,i.sessionId,i.executionId);o=l?.contextHash,r=l?.issuedAt??0,s=l?.canonicalAction?.binding.operationTargets?.find(d=>bn(i.projectRoot,d.path,e));}catch{}finally{try{c?.close();}catch{}}let a={toolUseId:i.toolUseId,sessionId:i.sessionId,executionId:i.executionId,operation:t,path:e,before:n,contextReceipt:o,observedAt:Date.now()};if(En(i.projectRoot,a),t==="edit"||t==="write"||t==="delete"){let l=wn(i.projectRoot,e),d=l?.success&&l.operation==="delete"&&!l.after.exists&&l.completedAt>=r,u=s?.expectedState==="existing"&&!n.exists||s?.expectedState==="missing"&&n.exists||!!(s?.contentHash&&n.hash!==s.contentHash);if(d||s?.expectedState==="existing"&&!n.exists)return qe(i,a,"DEVFLOW_FILE_STATE_DELETED","The target was deleted after the active Context receipt. Refresh project context before editing or recreating it.");if(u)return qe(i,a,"DEVFLOW_FILE_STATE_STALE","The target state no longer matches the active Context receipt. Refresh project context before overwriting it.")}return Ve(i,a,true),{allowed:true,pending:a}}function qe(i,t,e,n){return Ve(i,t,false,e),{allowed:false,reasonCode:e,reason:n,pending:t}}function Ve(i,t,e,n){D({event:"canonical.action.validated",identity:{projectRoot:i.projectRoot,sessionId:i.sessionId,executionId:i.executionId,contextReceipt:t.contextReceipt},level:e?"info":"warn",timestamp:Date.now(),data:{stage:"host_file_state_precondition",valid:e,operation:t.operation,targetPath:relative(i.projectRoot,t.path),targetExists:t.before.exists,targetHash:t.before.hash,reason:n,toolUseId:t.toolUseId}});}function mn(i,t){if(i==="Read")return "read";if(i==="Edit"||i==="NotebookEdit")return "edit";if(i==="Write")return "write";if(i==="Delete"||i==="Bash"&&ze(t.command))return "delete"}function hn(i,t,e){let n=yn(e,["file_path","filePath","notebook_path","path","targetPath"])??(t==="Bash"?ze(e.command):void 0);if(!n)return;let o=isAbsolute(n)?normalize(n):resolve(i,n),r=relative(i,o);return r.startsWith("..")||isAbsolute(r)?void 0:o}function ze(i){return typeof i!="string"?void 0:/(?:^|[;&|]\s*)\s*(?:rm|unlink)\s+(?:-[A-Za-z]+\s+)*(?:--\s+)?(["']?)([^\s;&|"']+)\1/u.exec(i)?.[2]}function yn(i,t){for(let e of t){let n=i[e];if(typeof n=="string"&&n.trim())return n.trim()}}function vn(i){if(!existsSync$1(i))return {exists:false};try{return {exists:!0,hash:createHash$1("sha256").update(readFileSync$1(i)).digest("hex")}}catch{return {exists:true}}}function bn(i,t,e){return (isAbsolute(t)?normalize(t):resolve(i,t))===normalize(e)}function Ge(i){return join(w(i),"file-state")}function Ye(i){return join(Ge(i),"pending.json")}function _n(i){return join(Ge(i),"observations.jsonl")}function Rn(i){try{return JSON.parse(readFileSync$1(Ye(i),"utf8"))}catch{return {}}}function En(i,t){let e=Ye(i);mkdirSync$1(dirname(e),{recursive:true});let n=Rn(i);n[t.toolUseId]=t,Dn(e,JSON.stringify(n));}function wn(i,t){try{let e=readFileSync$1(_n(i),"utf8").trim().split(`
|
|
3
|
-
`);for(let n=e.length-1;n>=0;n-=1){let o=JSON.parse(e[n]);if(o.path===t)return o}}catch{}}function Dn(i,t){let e=`${i}.${process.pid}.${Date.now()}.tmp`;writeFileSync$1(e,t,{encoding:"utf8",mode:384}),renameSync$1(e,i);}var Sn=new Set(["delivered","cancelled","rejected"]),On=new Set(["cancelled","rejected"]),An=new Set(["Write","Edit","NotebookEdit","Bash"]);function Cn(i,t){if(i!=="Bash"||typeof t?.command!="string")return false;let e=t.command.trim(),o="git show [A-Za-z0-9._/:@{}^~+\\-]+(?: 2>/dev/null)?";return new RegExp(`^${o}(?: \\|\\| ${o})*$`,"u").test(e)?true:/[;&|<>`$()]|\\/u.test(e)?false:/^(?:ls|pwd|find|rg|grep|cat|sed|head|tail|wc)(?:\s|$)/u.test(e)||/^git\s+(?:show|status|diff|log|branch)(?:\s|$)/u.test(e)}function oe(i,t,e,n,o){if(e.includes("delivery_rebind_session")||!An.has(e)||!t.trim()||Cn(e,o))return null;let r=join(i,".devflow","delivery-line","state.db");if(!existsSync$1(r))return null;let s;try{s=new DatabaseSync(r,{readOnly:!0,timeout:250});let c=s.prepare("SELECT id, payload, updated_at FROM delivery_cases").all(),a=new Set;if(!!s.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'delivery_workflow_bindings'").get()){let f=s.prepare("SELECT case_id, source_path, aliases FROM delivery_workflow_bindings WHERE status = 'enforced'").all();for(let g of f){let b=[];try{b=JSON.parse(g.aliases);}catch{}(g.source_path===i||b.includes(i))&&a.add(g.case_id);}}let d=[];for(let f of c){let g=JSON.parse(f.payload),b=a.has(f.id);(g.sessionId===t||t===f.id||b)&&d.push({id:f.id,payload:g,updatedAt:typeof f.updated_at=="number"?f.updated_at:typeof g.updatedAt=="number"?g.updatedAt:0});let y=typeof g.stage=="string"?g.stage:"unknown";if(!Sn.has(y)){if(n&&y==="executing"){let m=s.prepare("SELECT id, lease_owner, fencing_token FROM delivery_tasks WHERE case_id = ? AND lease_expires_at > ? AND lease_owner IS NOT NULL AND fencing_token > 0 LIMIT 1").get(f.id,Date.now()),v=typeof g.sessionId=="string"?g.sessionId:void 0,j=typeof g.executionId=="string"?g.executionId:void 0,x=n===m?.id||n===m?.lease_owner||n===j,P=t===f.id||t===v;if(m?.id&&x&&P)return null}if(g.sessionId===t||t===f.id||b)return {code:"DELIVERY_AUTHORITY_REQUIRED",caseId:f.id,stage:y,message:`Delivery case ${f.id} is ${y}; use the Delivery task lease before modifying files.`}}}let u=d.sort((f,g)=>g.updatedAt-f.updatedAt)[0],p=typeof u?.payload.stage=="string"?u.payload.stage:void 0;return u&&p&&On.has(p)?{code:"DELIVERY_AUTHORITY_REQUIRED",caseId:u.id,stage:p,message:`Delivery case ${u.id} is ${p}; start a new Delivery case or session before modifying files.`}:null}catch{return {code:"DELIVERY_AUTHORITY_UNAVAILABLE",caseId:"unknown",stage:"unknown",message:"Delivery state cannot be read; file writes are blocked until runtime health is restored."}}finally{s?.close();}}function F(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function re(i){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:i}}}function Nn(i){let t=w(i);return existsSync(t)||mkdirSync(t,{recursive:true}),t}function Un(i,t,e,n,o,r){let s=join$1(Nn(i),"event-map.json"),c=[];try{existsSync(s)&&(c=JSON.parse(readFileSync(s,"utf-8")));}catch{}c.push({sessionId:t,toolName:e,toolUseId:n,eventId:o,timestamp:r}),writeFileSync(s,JSON.stringify(c));}function Hn(i){switch(i){case "Read":case "Glob":return "file_read";case "Write":case "Edit":case "NotebookEdit":return "file_write";case "Bash":return "bash_command";case "Agent":return "subagent";case "Skill":return "skill_invoke";default:return "tool_use"}}function qn(i,t,e){if(t!=="Read"||typeof e.file_path!="string"||!e.file_path.trim())return null;let n=e.file_path.startsWith("/")?e.file_path:join$1(i,e.file_path);try{if(statSync(n).isDirectory())return `Read accepts files, but "${e.file_path}" is a directory. Use Glob or Bash ls to inspect directory entries, then Read one file.`}catch{return null}return null}function Wn(){let i=process.env.CLAUDE_PLUGIN_ROOT;if(!i)return null;let t=join$1(i,"package.json"),e=join$1(i,".mcp.json");try{let n=JSON.parse(readFileSync(t,"utf8")),r=JSON.parse(readFileSync(e,"utf8")).mcpServers?.devflow,s=r?.args;if(r?.command==="node"&&Array.isArray(s)&&s[0]==="${CLAUDE_PLUGIN_ROOT}/node_modules/@devflow-tools/mcp-server/bin/devflow-mcp.cjs")return existsSync(join$1(i,"node_modules/@devflow-tools/mcp-server/bin/devflow-mcp.cjs"))?null:"bundled DevFlow MCP runtime is not installed";let a=Array.isArray(s)?s.indexOf("--package"):-1,l=a>=0&&typeof s?.[a+1]=="string"?s[a+1]:void 0,d=typeof n.version=="string"?`@devflow-tools/mcp-server@${n.version}`:void 0;return l?d&&l!==d?`DevFlow MCP version mismatch (${l} vs ${d})`:null:"DevFlow MCP package configuration is missing"}catch{return "DevFlow MCP configuration could not be inspected"}}function Jn(){let i=process.env.CLAUDE_PLUGIN_ROOT?.trim();if(!i)return null;try{let t=join$1(i,"dist","runtime-manifest.json"),e=JSON.parse(readFileSync(t,"utf8")),n=typeof e.bundleHashes?.mcp=="string"?e.bundleHashes.mcp:void 0,o=join$1(i,"node_modules","@devflow-tools","mcp-server","dist","delivery-tools.js"),r=existsSync(o)?createHash$1("sha256").update(readFileSync(o)).digest("hex"):"missing";return !n||n!==r?"DevFlow runtime build does not match the active plugin manifest":null}catch{return "DevFlow runtime manifest is missing or invalid"}}function Bn(i,t,e){return new Set(["Write","Edit","NotebookEdit"]).has(i)?true:i==="Bash"?!Ke(i,t):!!(e?.startsWith("delivery_")&&e!=="delivery_status")}function Ke(i,t){return i==="Grep"||i==="Glob"?true:i!=="Bash"||typeof t.command!="string"?false:/^(?:ls|pwd|find|rg|grep|git\s+(?:status|diff|log|branch)|cat|sed|head|tail|wc)\b/u.test(t.command.trim())}async function Vn(i){let t=Fe();try{if(!i||i.trim()==="")return F();let e=JSON.parse(i),n=Date.now();try{maybeRunDiagnosticLogCleanup(T(),{now:n});}catch{}let o=T(),r=new H,s=resolveClaudeToolName(e.tool_name,e.tool_input),c=s.status==="unsupported"?void 0:s.canonicalName;c&&(typeof e.tool_input.projectRoot!="string"||!e.tool_input.projectRoot.trim())&&(e.tool_input.projectRoot=o);let a=e.session_id?.trim();if(!a)return re(Z);let l=new S(o),d=l.get(a)!==null;if(l.registerSession(a),d||await r.sendSessionStart(a,o,Date.now()),e.tool_name==="Skill"){let _=e.tool_input?.skill,h=_?Le(_):null;if(h){let R=l.get(a)?.executionId,E=l.startExecution(a,h,he(h));E.executionId&&E.executionId!==R&&await r.sendExecutionStart(E.executionId,a,h,E.lastActivityAt,o,E.requiredMcpTools);}}let u=l.get(a);c==="get_project_context"&&l.beginContextInitialization(a,e.tool_use_id),c&&(e.tool_input._devflow_session_id=a,e.tool_input._devflow_execution_id=u?.executionId??a,u?.activeTurnId&&(e.tool_input._devflow_turn_id=u.activeTurnId),u?.activeRequestId&&(e.tool_input._devflow_request_id=u.activeRequestId),u?.intentArtifactHash&&(e.tool_input._devflow_intent_artifact_hash=u.intentArtifactHash),u?.skillName&&(e.tool_input._devflow_active_skill=u.skillName),e.tool_use_id&&(e.tool_input._devflow_tool_use_id=e.tool_use_id));let p=e.tool_name.startsWith("mcp__"),f=c,g=l.get(a),b=new B(o,a,g?.executionId),y=b.getPhase(),m,v,j=qn(o,e.tool_name,e.tool_input),x=oe(o,a,e.tool_name,g?.executionId,e.tool_input),P=!x&&Bn(e.tool_name,e.tool_input,f)?Jn():null;if(P)v="DEVFLOW_RUNTIME_VERSION_MISMATCH",m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:`${P}. Update or restart the DevFlow plugin before approving, executing, or modifying files.`}};else if(j)v="DEVFLOW_DIRECTORY_READ_INVALID",m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:j}};else if(x)v=x.code,m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:`${x.message} Resolve the case blocker or obtain an authorized task lease before retrying.`}};else {let _=He({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:o}),h=Be({projectRoot:o,sessionId:a,executionId:g?.executionId,toolUseId:e.tool_use_id,toolName:e.tool_name,toolInput:e.tool_input}),R=_?{permissionDecision:"deny",reason:_}:h.allowed?b.evaluate(e.tool_name,p):{permissionDecision:"deny",reason:h.reason,reasonCode:h.reasonCode},E=R.permissionDecision==="deny"&&!p&&Ke(e.tool_name,e.tool_input)?Wn():null;E?(m=re(`DevFlow MCP is unavailable or stale: ${E}. This read-only fallback is temporary; refresh the plugin installation and call ${projectClaudeToolName("get_project_context")} before editing.`),v=void 0):R.permissionDecision==="deny"?(v=_?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":R.reasonCode??"DEVFLOW_CONTEXT_REQUIRED",m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:R.reason??"MCP context required"}}):R.additionalContext?m=re(R.additionalContext):m=F();}c&&(m.hookSpecificOutput.updatedInput=e.tool_input),t&&m.hookSpecificOutput.permissionDecision==="allow"&&(m.hookSpecificOutput.additionalContext=Z);let Xe=g?.executionId??a,C={eventId:je(a,e.tool_use_id),executionId:Xe,sessionId:a,projectRoot:o,toolUseId:e.tool_use_id,timestamp:Date.now(),toolName:e.tool_name,toolType:p?"mcp":e.tool_name==="Agent"?"subagent":"direct",isMcpTool:p,mcpToolName:f,mcpEnforced:p&&(y==="context_gathering"||y==="context_initializing"),mcpFallback:!p&&(y==="context_gathering"||y==="context_initializing"),kind:Hn(e.tool_name),input:e.tool_input,duration:0,blocked:m.hookSpecificOutput.permissionDecision==="deny",blockReason:m.hookSpecificOutput.permissionDecision==="deny"?v??"DEVFLOW_CONTEXT_REQUIRED":void 0},$=await r.sendEvent(C);$&&!C.blocked&&Un(o,a,e.tool_name,e.tool_use_id,$,C.timestamp),$&&C.blocked&&await r.completeEvent({eventId:$,sessionId:a,error:v??"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-C.timestamp,completedAt:Date.now()});try{let _=Ae(o),h={ts:n,tool:e.tool_name,sessionId:a,skill:u?.skillName??"(none)",requiredTools:u?.requiredMcpTools??[],isMcp:p,enforce:u?.executionId!==void 0,stateless:u?.executionId===void 0&&!p&&e.tool_name!=="Skill",bypassCount:_.bypassCount??0,decision:m.hookSpecificOutput.permissionDecision,env_CLAUDE_PLUGIN_ROOT:process.env.CLAUDE_PLUGIN_ROOT??"(unset)",cwd:process.cwd()};Te(Ce(o),`${JSON.stringify(h)}
|
|
4
|
-
`);}catch{}return
|
|
1
|
+
import {createHash as createHash$1}from'node:crypto';import {existsSync as existsSync$1,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync,rmSync,linkSync,renameSync,statSync}from'fs';import {join as join$1,dirname as dirname$1}from'path';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {getLocalApiKey,getDevFlowStateRoot,projectClaudeToolName,resolveClaudeToolName,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir,readRuntimeState}from'@devflow-tools/sdk';import {request}from'node:http';import {existsSync,mkdirSync as mkdirSync$1,appendFileSync,chmodSync,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 {randomUUID,createHash}from'crypto';import {homedir}from'node:os';import {DatabaseSync}from'node:sqlite';function M(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 vt=getLocalApiKey(),K=join(getDevFlowStateRoot(),"errors");async function de(n,t,e={}){let o=e.endpoint??process.env.DEVFLOW_SERVER_URL?.trim()??bt();if(!o)return {delivered:false,suppressed:false,fallbackReason:"runtime_not_ready"};let i=e.timeout??1500,r=e.durableMirror??true,s=e.maxRetries??(r?0:2),a=e.circuitBreaker??true,c=acquireRuntimeHttpCircuit(o,n);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let l;for(let u=0;u<=s;u+=1)try{return await _t(o,n,t,i),a&®isterRuntimeHttpSuccess(o,n).transitioned&&M("http_circuit_transition",{endpoint:o,path:new URL(n,o).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(p){l=p instanceof Error?p:new Error(String(p)),u<s&&await Rt(Math.min(100*2**u,1e3));}if(!l)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return ce(n,l),{delivered:false,suppressed:false,fallbackReason:l.message};let d=registerRuntimeHttpFailure(o,n,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return d.transitioned&&(ce(n,l),M("http_circuit_transition",{endpoint:o,path:new URL(n,o).pathname,previous:c.state.status,status:"open",failures:d.state.failures,openUntil:d.state.openUntil,fallbackReason:d.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:d.state.fallbackReason}}function bt(){let n=readRuntimeState();return n?.status==="ready"&&n.dashboardAvailable?n.url:void 0}function _t(n,t,e,o){return new Promise((i,r)=>{let s=JSON.stringify(e),a=new URL(t,n),c=false,l=u=>{c||(c=true,u?r(u):i());},d=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":vt,"Content-Length":Buffer.byteLength(s)},timeout:o},u=>{u.on("error",l),u.on("end",()=>{let p=u.statusCode??0;l(p>=200&&p<300?void 0:new Error(`HTTP ${p}`));}),u.resume();});d.on("error",l),d.on("timeout",()=>d.destroy(new Error(`HTTP mirror timed out after ${o}ms`))),d.write(s),d.end();})}function ce(n,t){try{existsSync(K)||mkdirSync$1(K,{recursive:!0});let e=join(K,"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 ge=1e4,St=3e4,H=500,U=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,i,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:o,startedAt:i,projectRoot:r,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",o=Date.now(),i){let r={executionId:t,status:e,finishedAt:o,metadata:i},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(t,e,o){let i={id:t,projectRoot:e,startedAt:o,label:e.split("/").pop()??"unknown"},r=this.commitOrCache("session_start",i);return r&&this.postHttp("/api/telemetry/sessions",i),r}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let o={sessionId:t,finishedAt:e},i=this.commitOrCache("session_end",o);return i&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),i}async flushCache(){try{let e=this.getDatabase(),o=e.listTelemetryFailures({unresolvedOnly:!0,limit:H}).reverse();for(let i of o)try{this.applyOperation(i.operation,i.payload),e.resolveTelemetryFailure(i.id);}catch{}e.trimTelemetryFailures(H);}catch{}let t=(existsSync$1(this.cacheDir)?readdirSync(this.cacheDir):[]).filter(e=>e.endsWith(".json")).map(e=>{let o=join$1(this.cacheDir,e);try{return {cacheFile:o,envelope:It(JSON.parse(readFileSync(o,"utf8")))}}catch{return null}}).filter(e=>e!==null).sort((e,o)=>e.envelope.timestamp-o.envelope.timestamp||me(e.envelope.operation)-me(o.envelope.operation));for(let{cacheFile:e,envelope:o}of t)try{let i=this.getDatabase();i.insertTelemetryFailure({id:o.id,operation:o.operation,payload:o.payload,error:o.failure,createdAt:o.timestamp}),this.applyOperation(o.operation,o.payload),i.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:he(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(he(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let o=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!o)throw new Error("Canonical session ID is required for telemetry");let i=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:o,projectRoot:i,label:i==="unknown"?void 0:i.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,o){let i=Date.now(),r={id:`failure:${i}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:o instanceof Error?o.message:String(o),timestamp:i};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:i}),s.trimTelemetryFailures(H),this.scheduleRetry();return}catch{}try{existsSync$1(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${i}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(r,null,2),{mode:384}),this.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-H)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},St).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){de(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ge?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ge)}...`}}};function me(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function he(n){return `hook-run:${n}`}function It(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 F(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function E(n){return getProjectStateDir(F(n))}var h=emitSemanticControlLog;var Lt=2,jt=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 ye(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$1(e))continue;let o=JSON.parse(readFileSync(e,"utf8"));if(o.version!==Lt&&o.version!==jt||!Mt(o.commands)){h({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){h({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 Mt(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 q(e.mcpTools)&&q(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||q(e.runtimePackages))&&(e.hostTools===void 0||Nt(e.hostTools))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function Nt(n){return !!n&&typeof n=="object"&&!Array.isArray(n)&&Object.entries(n).every(([t,e])=>t.length>0&&q(e))}function q(n){return Array.isArray(n)&&n.every(t=>typeof t=="string"&&t.length>0)}function ve(n){let t=ye();return t?t[n]?.mcpTools??[]:[]}function we(n){return Buffer.from(n,"utf8").toString("base64url")}function Jt(n,t,e){let o=t?.trim();if(o){let i=/^[a-zA-Z0-9:._-]{1,192}$/.test(o)?o:`tool-${createHash("sha256").update(o.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${i}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function Ie(n){return `${n}:legacy-journal`}var I=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(E(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let o=this.get(e);if(o)return o.lastActivityAt=Date.now(),this.persist(o),o;let i=Date.now(),r={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:i,lastActivityAt:i};return this.sessions.set(e,r),this.persist(r),r}startExecution(t,e,o){let i=this.registerSession(t);return (!i.executionId||i.skillName!==e)&&(i.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),i.skillName=e,i.requiredMcpTools=[...new Set(o)],delete i.contextInitialization,i.lastActivityAt=Date.now(),this.persist(i),i}beginContextInitialization(t,e){let o=this.registerSession(t);return o.contextInitialization={startedAt:Date.now(),...e?{toolUseId:e}:{}},o.lastActivityAt=Date.now(),this.persist(o),o}completeContextInitialization(t,e){let o=this.get(t);return o?(e&&o.contextInitialization?.toolUseId&&o.contextInitialization.toolUseId!==e||(delete o.contextInitialization,o.lastActivityAt=Date.now(),this.persist(o)),o):null}bindTaskIdentity(t,e){let o=this.registerSession(t);return o.activeTurnId=e.turnId,o.activeRequestId=e.requestId,o.intentArtifactHash=e.intentArtifactHash,o.lastActivityAt=Date.now(),this.persist(o),o}get(t){let e=t.trim();if(!e)return null;let o=this.sessions.get(e);if(o)return this.replayEvidenceJournal(o),o;let i=this.snapshotPath(e);if(!existsSync$1(i))return null;try{let r=JSON.parse(readFileSync(i,"utf8"));return r.sessionId!==e||r.projectRoot!==this.projectRoot?null:(r.requiredMcpTools=Array.isArray(r.requiredMcpTools)?r.requiredMcpTools:[],r.evidenceObligations=ke(r.evidenceObligations),r.evidenceDegradations=Ee(r.evidenceDegradations),r.evidenceOutcomes=De(r.evidenceOutcomes),this.replayEvidenceJournal(r),this.sessions.set(e,r),r)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let o=structuredClone(e);return delete e.executionId,delete e.skillName,delete e.contextInitialization,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),o}addEvidenceObligation(t,e,o=Date.now(),i){let r=this.registerSession(t),a=(i?void 0:r.evidenceObligations.find(l=>l.contractId===e.id))?.obligationId??Jt(e.id,i,o);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:o,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let c=r.evidenceObligations.find(l=>l.obligationId===a);return c?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(c)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,o,i,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(i)?i:"";if(!c)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:c,violations:o.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let l=s.evidenceObligations.find(d=>d.obligationId===e);return l?structuredClone(l):null}resolveEvidenceObligation(t,e){let o=this.get(t);if(!o)return false;let i=o.evidenceObligations.find(s=>s.obligationId===e);if(!i)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:i.contractId,at:r},`resolve\0${e}`),this.replayEvidenceJournal(o),o.lastActivityAt=r,this.persist(o),true}resolveDegradedEvidence(t,e){let o=this.get(t),i=o?.evidenceDegradations.find(s=>s.obligationId===e);if(!o||!i)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:i.contractId,at:r},`resolve-degraded\0${e}\0${r}`),this.replayEvidenceJournal(o),o.lastActivityAt=r,this.persist(o),true}degradeEvidenceObligation(t,e,o,i=Date.now()){let r=this.get(t),s=r?.evidenceObligations.find(c=>c.obligationId===e);if(!r||!s)return false;let a=o.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:i,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(r),r.lastActivityAt=i,this.persist(r),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${we(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",we(t))}appendEvidenceEvent(t,e,o){let i=this.evidenceJournalDir(t);mkdirSync(i,{recursive:true,mode:448});let r=createHash("sha256").update(o).digest("hex"),s=join$1(i,`${e.kind}-${r}.json`);if(existsSync$1(s))return;let a=join$1(i,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=ke(t.evidenceObligations),t.evidenceDegradations=Ee(t.evidenceDegradations),t.evidenceOutcomes=De(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync$1(e))return;let o;try{o=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let i=o.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=Bt(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||xe(r.kind)-xe(s.kind));for(let r of i)this.applyEvidenceEvent(t,r);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let o=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(o)return;let s=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let i=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!i||o||i.correctionFingerprint===e.fingerprint)return;i.attempt+=1,i.correctionRequested=true,i.correctionRequestedAt=e.at,i.correctionFingerprint=e.fingerprint,i.violations=e.violations;return}let r=i?.attempt??o?.attempt??0;if(e.kind==="resolve"&&o?.status==="degraded")t.evidenceOutcomes=t.evidenceOutcomes.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations=t.evidenceDegradations.filter(s=>s.obligationId!==e.obligationId);else if(o)return;e.kind==="degrade"?(t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r,contract:i?.contract})):t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}});}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),o=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384}),renameSync(o,e);}};function ke(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)||!Oe(e.contract))return [];let o=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:Ie(e.contractId),i=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,r=e.correctionFingerprint??i;return r!==void 0&&!/^[a-f0-9]{64}$/.test(r)?[]:[{...e,obligationId:o,correctionFingerprint:r}]}).slice(-8):[]}function Ee(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function De(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function Bt(n){if(!n||typeof n!="object")return null;let t=n,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let i={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:Ie(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return Oe(t.contract)?{kind:e,...i,contract:t.contract}:null;if(e==="correction"){let r=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)&&Array.isArray(t.violations)&&t.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:e,...i,fingerprint:r,violations:t.violations}:null}return e==="resolve"?{kind:e,...i}:typeof t.reason=="string"&&t.reason.length<=240?{kind:e,...i,reason:t.reason}:null}function xe(n){return n==="add"?0:n==="correction"?1:2}function Oe(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,o=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(o)&&o.length<=16&&o.every(i=>typeof i=="string"&&i.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function B(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let t=n,e={};for(let o of ["lastMcpCall","bypassCount"])if(o in t){let i=t[o];if(i==null)continue;e[o]=typeof i=="number"&&Number.isFinite(i)&&i>=0?i:0;}return e}function Wt(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function Ae(n,t,e){let o=e instanceof Error?e.message:String(e);h({event:"hook.runtime.degraded",identity:{projectRoot:n},level:"warn",timestamp:Date.now(),data:{stage:"enforcement_receipt",operation:t,reason:o,fallback:"fail_open"}});}function Ce(n,t,e){let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let i={},r=o.updateHookReceipt(n,a=>(i=B(a),B(t(i)))),s=B(r);return {receipt:s,applied:!0,changed:!Wt(i,s)}}catch(i){return Ae(n,e,i),{receipt:{},applied:false,changed:false}}finally{try{o?.close();}catch{}}}function Te(n){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),B(t.getHookReceipt(n))}catch(e){return Ae(n,"update",e),{}}finally{try{t?.close();}catch{}}}function Vt(n,t){return Ce(n,()=>t,"write").applied}function zt(n,t){return Ce(n,t,"update")}var Z={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"},Gt=new Set(["Write","Edit","NotebookEdit"]),Kt=new Set(["failed","timeout","unavailable"]);function Yt(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 W=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 o=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(o&&o.expiresAt>Date.now())return "context_ready";o&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}let e=new I(this.projectRoot).get(this.sessionId);return e?.executionId===this.executionId&&e.contextInitialization?"context_initializing":"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_initializing"&&Z[t])return {permissionDecision:"allow",additionalContext:`DevFlow context initialization is in progress; wait for ${projectClaudeToolName("get_project_context")} to complete before broad discovery with ${t}.`};if(o==="context_gathering"&&Z[t])return {permissionDecision:"allow",additionalContext:`DevFlow tip: call ${projectClaudeToolName("get_project_context")} first for scoped context instead of broad ${t} discovery.`};if(o==="context_ready"){if(Gt.has(t)){let c=this.evaluateRequiredAction();if(c)return c}return {permissionDecision:"allow"}}let i=Z[t];if(!i)return {permissionDecision:"allow"};let r=zt(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!r.applied)return {permissionDecision:"allow"};let s=r.receipt.bypassCount??0,a=Yt(t);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 ${projectClaudeToolName(i)} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){Vt(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}recordDomainActionOutcome(t,e,o,i){if(!this.sessionId||!this.executionId)return false;let r;try{r=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let s=r.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(!s||s.expiresAt<=Date.now()||s.canonicalAction?.tool!==t)return !1;let a=Date.now(),c=i?.trim()?`${i.trim()}:${e}`:`${t}:${e}:${a}`,l=s.actionAttempts??[];return r.upsertContextReceipt({...s,actionAttempts:l.some(d=>d.id===c||i&&d.toolUseId===i&&d.status===e)?l:[...l,{id:c,tool:t,status:e,attemptedAt:a,toolUseId:i,reason:o?.slice(0,500)}].slice(-20),actionSatisfiedAt:e==="succeeded"?a:s.actionSatisfiedAt,actionDegradation:e==="succeeded"?void 0:s.actionDegradation}),!0}catch{return false}finally{try{r?.close();}catch{}}}evaluateRequiredAction(){let t=this.getContextReceipt(),e=t?.canonicalAction;if(!t||!e||!e.required||e.status!=="required")return null;let o=e.binding;if(o.requiredContextReceipt!==t.contextHash||o.projectRoot!==this.projectRoot||o.sessionId!==this.sessionId||o.requestId!==t.requestId||o.executionId&&o.executionId!==this.executionId)return {permissionDecision:"deny",reasonCode:"DEVFLOW_ACTION_BINDING_STALE",reason:`DevFlow canonical action binding is stale or mismatched. Call ${projectClaudeToolName("get_project_context")} again before writing.`};if(t.actionSatisfiedAt)return null;if(t.actionDegradation?.authorizedByContextReceipt===t.contextHash)return {permissionDecision:"allow",additionalContext:`DevFlow degraded fallback authorized by context receipt ${t.contextHash}: ${t.actionDegradation.reason}`};let i=(t.actionAttempts??[]).filter(r=>r.tool===e.tool&&Kt.has(r.status));if(i.length>0){let r=i.at(-1),s={missedTool:e.tool,failedAttemptCount:i.length,reason:`${r.status}:${r.reason??"canonical domain action did not complete"}`,authorizedByContextReceipt:t.contextHash,authorizedAt:Date.now()};return this.persistDegradation(t,s),{permissionDecision:"allow",additionalContext:`DevFlow canonical tool ${projectClaudeToolName(e.tool)} ${r.status}; degraded direct write authorized by context receipt ${t.contextHash}. Preserve the action contract and verification plan.`}}return {permissionDecision:"deny",reasonCode:"DEVFLOW_REQUIRED_ACTION",reason:`DevFlow required action not completed. Call ${projectClaudeToolName(e.tool)} using context receipt ${t.contextHash}, then retry the write. Direct fallback is allowed only after unavailable, failed, or timeout evidence.`}}persistDegradation(t,e){let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let i=o.getContextReceipt(t.projectRoot,t.sessionId,t.executionId);if(!i||i.contextHash!==t.contextHash||i.actionDegradation)return;o.upsertContextReceipt({...i,actionDegradation:e});let r=o.getSkillExecution(t.executionId);if(!r)return;let s=r.metadata&&typeof r.metadata=="object"?r.metadata:{},a=Array.isArray(s.requiredActionDegradations)?s.requiredActionDegradations:[];o.updateSkillExecution(t.executionId,{missedMcpTools:[...new Set([...r.missedMcpTools??[],e.missedTool])],failedToolCalls:Math.max(r.failedToolCalls??0,e.failedAttemptCount),fallbackCount:(r.fallbackCount??0)+1,fallbackReasons:[...new Set([...r.fallbackReasons??[],`required_action_${e.reason}`])],metadata:{...s,requiredActionDegradations:[...a,e]}});}catch{}finally{try{o?.close();}catch{}}}};var sn=10*1024*1024,an=5;function cn(n){return createHash$1("sha256").update(n).digest("hex").slice(0,16)}function Fe(n){return join(homedir(),".devflow","logs","hook-debug",`${cn(n)}.jsonl`)}function Pe(n,t,e={}){let o=e.maxBytes??sn,i=e.maxFiles??an;mkdirSync$1(dirname(n),{recursive:true,mode:448});let r=Buffer.byteLength(t);rotateDiagnosticLogFile({path:n,maxBytes:o,maxFiles:i,incomingBytes:r}),appendFileSync(n,t,{mode:384}),chmodSync(n,384);}var ee="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function Le(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function je(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 $e(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 fn=new Set(["Write","Edit","NotebookEdit"]),Me=`Claude native memory writes are disabled for this project. Use DevFlow explicit memory or ${projectClaudeToolName("memory_commit_turn")} so a canonical receipt is created.`;function Je(n){if(!fn.has(n.toolName))return null;let t=gn(n.toolInput);if(!t)return null;let e=mn(t,n.projectRoot),o=resolve(n.projectRoot,".claude");if(Ne(e,o)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return Me;let i=resolve(n.home??homedir(),".claude","projects");return Ne(e,i)&&relative(i,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?Me:null}function gn(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 mn(n,t){return resolve(isAbsolute(n)?n:resolve(t,n))}function Ne(n,t){let e=relative(t,n);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function ze(n){let t=kn(n.toolName,n.toolInput),e=t?En(n.projectRoot,n.toolName,n.toolInput):void 0;if(!t||!e||!n.toolUseId)return {allowed:true};let o=xn(e),i,r=0,s,a;try{a=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:100,readonly:!0});let l=a.getActiveContextReceipt(n.projectRoot,n.sessionId,n.executionId);i=l?.contextHash,r=l?.issuedAt??0,s=l?.canonicalAction?.binding.operationTargets?.find(d=>Sn(n.projectRoot,d.path,e));}catch{}finally{try{a?.close();}catch{}}let c={toolUseId:n.toolUseId,sessionId:n.sessionId,executionId:n.executionId,operation:t,path:e,before:o,contextReceipt:i,observedAt:Date.now()};if(An(n.projectRoot,c),t==="edit"||t==="write"||t==="delete"){let l=Cn(n.projectRoot,e),d=l?.success&&l.operation==="delete"&&!l.after.exists&&l.completedAt>=r,u=s?.expectedState==="existing"&&!o.exists||s?.expectedState==="missing"&&o.exists||!!(s?.contentHash&&o.hash!==s.contentHash);if(d||s?.expectedState==="existing"&&!o.exists)return Be(n,c,"DEVFLOW_FILE_STATE_DELETED","The target was deleted after the active Context receipt. Refresh project context before editing or recreating it.");if(u)return Be(n,c,"DEVFLOW_FILE_STATE_STALE","The target state no longer matches the active Context receipt. Refresh project context before overwriting it.")}return Ge(n,c,true),{allowed:true,pending:c}}function Be(n,t,e,o){return Ge(n,t,false,e),{allowed:false,reasonCode:e,reason:o,pending:t}}function Ge(n,t,e,o){h({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 kn(n,t){if(n==="Read")return "read";if(n==="Edit"||n==="NotebookEdit")return "edit";if(n==="Write")return "write";if(n==="Delete"||n==="Bash"&&Ke(t.command))return "delete"}function En(n,t,e){let o=Dn(e,["file_path","filePath","notebook_path","path","targetPath"])??(t==="Bash"?Ke(e.command):void 0);if(!o)return;let i=isAbsolute(o)?normalize(o):resolve(n,o),r=relative(n,i);return r.startsWith("..")||isAbsolute(r)?void 0:i}function Ke(n){return typeof n!="string"?void 0:/(?:^|[;&|]\s*)\s*(?:rm|unlink)\s+(?:-[A-Za-z]+\s+)*(?:--\s+)?(["']?)([^\s;&|"']+)\1/u.exec(n)?.[2]}function Dn(n,t){for(let e of t){let o=n[e];if(typeof o=="string"&&o.trim())return o.trim()}}function xn(n){if(!existsSync(n))return {exists:false};try{return {exists:!0,hash:createHash$1("sha256").update(readFileSync$1(n)).digest("hex")}}catch{return {exists:true}}}function Sn(n,t,e){return (isAbsolute(t)?normalize(t):resolve(n,t))===normalize(e)}function Ye(n){return join(E(n),"file-state")}function Qe(n){return join(Ye(n),"pending.json")}function In(n){return join(Ye(n),"observations.jsonl")}function On(n){try{return JSON.parse(readFileSync$1(Qe(n),"utf8"))}catch{return {}}}function An(n,t){let e=Qe(n);mkdirSync$1(dirname(e),{recursive:true});let o=On(n);o[t.toolUseId]=t,Tn(e,JSON.stringify(o));}function Cn(n,t){try{let e=readFileSync$1(In(n),"utf8").trim().split(`
|
|
3
|
+
`);for(let o=e.length-1;o>=0;o-=1){let i=JSON.parse(e[o]);if(i.path===t)return i}}catch{}}function Tn(n,t){let e=`${n}.${process.pid}.${Date.now()}.tmp`;writeFileSync$1(e,t,{encoding:"utf8",mode:384}),renameSync$1(e,n);}var jn=new Set(["delivered","cancelled","rejected"]),$n=new Set(["cancelled","rejected"]),Mn=new Set(["Write","Edit","NotebookEdit","Bash"]);function Nn(n,t){if(n!=="Bash"||typeof t?.command!="string")return false;let e=t.command.trim(),i="git show [A-Za-z0-9._/:@{}^~+\\-]+(?: 2>/dev/null)?";return new RegExp(`^${i}(?: \\|\\| ${i})*$`,"u").test(e)?true:/[;&|<>`$()]|\\/u.test(e)?false:/^(?:ls|pwd|find|rg|grep|cat|sed|head|tail|wc)(?:\s|$)/u.test(e)||/^git\s+(?:show|status|diff|log|branch)(?:\s|$)/u.test(e)}function re(n,t,e,o,i){if(e.includes("delivery_rebind_session")||!Mn.has(e)||!t.trim()||Nn(e,i))return null;let r=join(n,".devflow","delivery-line","state.db");if(!existsSync(r))return null;let s;try{s=new DatabaseSync(r,{readOnly:!0,timeout:250});let a=s.prepare("SELECT id, payload, updated_at FROM delivery_cases").all(),c=new Set;if(!!s.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'delivery_workflow_bindings'").get()){let m=s.prepare("SELECT case_id, source_path, aliases FROM delivery_workflow_bindings WHERE status = 'enforced'").all();for(let f of m){let R=[];try{R=JSON.parse(f.aliases);}catch{}(f.source_path===n||R.includes(n))&&c.add(f.case_id);}}let d=[];for(let m of a){let f=JSON.parse(m.payload),R=c.has(m.id);(f.sessionId===t||t===m.id||R)&&d.push({id:m.id,payload:f,updatedAt:typeof m.updated_at=="number"?m.updated_at:typeof f.updatedAt=="number"?f.updatedAt:0});let y=typeof f.stage=="string"?f.stage:"unknown";if(!jn.has(y)){if(o&&y==="executing"){let g=s.prepare("SELECT id, lease_owner, fencing_token FROM delivery_tasks WHERE case_id = ? AND lease_expires_at > ? AND lease_owner IS NOT NULL AND fencing_token > 0 LIMIT 1").get(m.id,Date.now()),v=typeof f.sessionId=="string"?f.sessionId:void 0,L=typeof f.executionId=="string"?f.executionId:void 0,x=o===g?.id||o===g?.lease_owner||o===L,j=t===m.id||t===v;if(g?.id&&x&&j)return null}if(f.sessionId===t||t===m.id||R)return {code:"DELIVERY_AUTHORITY_REQUIRED",caseId:m.id,stage:y,message:`Delivery case ${m.id} is ${y}; use the Delivery task lease before modifying files.`}}}let u=d.sort((m,f)=>f.updatedAt-m.updatedAt)[0],p=typeof u?.payload.stage=="string"?u.payload.stage:void 0;return u&&p&&$n.has(p)?{code:"DELIVERY_AUTHORITY_REQUIRED",caseId:u.id,stage:p,message:`Delivery case ${u.id} is ${p}; start a new Delivery case or session before modifying files.`}:null}catch(a){return h({event:"hook.runtime.degraded",identity:{projectRoot:n},level:"warn",timestamp:Date.now(),data:{stage:"delivery_authority",operation:"delivery_write_block",reason:a instanceof Error?a.message:String(a),fallback:"fail_open_unverified_write"}}),null}finally{s?.close();}}function Xe(n=process.env){if(n.DEVFLOW_DISABLED==="1")return true;try{return existsSync(join(getDevFlowStateRoot({env:n}),"disable"))}catch{return false}}var Vn=250;function tt(n,t=process.env){let e=et(join(getDevFlowStateRoot({env:t}),"config.json")),o=et(join(n,".devflow","config.json")),i=se(t.DEVFLOW_HOOK_PROFILE)??se(o.profile)??se(e.profile)??"standard",r=Number(t.DEVFLOW_HOOK_ACK_BUDGET_MS??o.acknowledgementBudgetMs??e.acknowledgementBudgetMs),s=Number.isSafeInteger(r)&&r>0?Math.min(r,5e3):Vn,a=new Set([...ae(e.disabledHandlers),...ae(o.disabledHandlers),...ae(t.DEVFLOW_DISABLED_HOOK_HANDLERS?.split(","))].map(zn).filter(c=>!!c));return {profile:i,acknowledgementBudgetMs:s,disabledHandlers:a}}function et(n){if(!existsSync(n))return {};try{let e=JSON.parse(readFileSync$1(n,"utf8")).hooks;return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}catch{return {}}}function se(n){return n==="minimal"||n==="standard"||n==="strict"||n==="advise"?n:void 0}function ae(n){return Array.isArray(n)?n.filter(t=>typeof t=="string"):[]}function zn(n){let t=n.trim().replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/_/g,"-").toLowerCase();return ({sessionstart:"session-start",userpromptsubmit:"user-prompt-submit",pretooluse:"pre-tool-use",posttooluse:"post-tool-use",posttoolusefailure:"post-tool-use-failure",sessionend:"session-end",precompact:"pre-compact",memorysnapshot:"memory-snapshot"}[t.replace(/-/g,"")]??t)||void 0}function nt(n){return n==="advise"}function ot(n){h({event:"hook.enforcement.shadow",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId},level:"warn",timestamp:Date.now(),data:{tool:n.toolName,code:n.code??"DEVFLOW_POLICY",reason:n.reason.slice(0,500)}});try{process.stderr.write(`[devflow][shadow] would deny ${n.toolName}: ${n.reason}
|
|
4
|
+
`);}catch{}return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:`DevFlow shadow enforcement: this call would be denied under enforce mode (${n.code??"DEVFLOW_POLICY"}). Proceeding; the decision is recorded for graduation review.`}}}function C(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function z(n){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:n}}}function to(n){let t=E(n);return existsSync$1(t)||mkdirSync(t,{recursive:true}),t}function no(n,t,e,o,i,r){let s=join$1(to(n),"event-map.json"),a=[];try{existsSync$1(s)&&(a=JSON.parse(readFileSync(s,"utf-8")));}catch{}a.push({sessionId:t,toolName:e,toolUseId:o,eventId:i,timestamp:r}),a.length>1e3&&a.splice(0,a.length-1e3),writeFileSync(s,JSON.stringify(a));}function oo(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"}}function io(n,t,e){if(t!=="Read"||typeof e.file_path!="string"||!e.file_path.trim())return null;let o=e.file_path.startsWith("/")?e.file_path:join$1(n,e.file_path);try{if(statSync(o).isDirectory())return `Read accepts files, but "${e.file_path}" is a directory. Use Glob or Bash ls to inspect directory entries, then Read one file.`}catch{return null}return null}function ro(){let n=process.env.CLAUDE_PLUGIN_ROOT;if(!n)return null;let t=join$1(n,"package.json"),e=join$1(n,".mcp.json");try{let o=JSON.parse(readFileSync(t,"utf8")),r=JSON.parse(readFileSync(e,"utf8")).mcpServers?.devflow,s=r?.args;if(r?.command==="node"&&Array.isArray(s)&&s[0]==="${CLAUDE_PLUGIN_ROOT}/node_modules/@devflow-tools/mcp-server/bin/devflow-mcp.cjs")return existsSync$1(join$1(n,"node_modules/@devflow-tools/mcp-server/bin/devflow-mcp.cjs"))?null:"bundled DevFlow MCP runtime is not installed";let c=Array.isArray(s)?s.indexOf("--package"):-1,l=c>=0&&typeof s?.[c+1]=="string"?s[c+1]:void 0,d=typeof o.version=="string"?`@devflow-tools/mcp-server@${o.version}`:void 0;return l?d&&l!==d?`DevFlow MCP version mismatch (${l} vs ${d})`:null:"DevFlow MCP package configuration is missing"}catch{return "DevFlow MCP configuration could not be inspected"}}function so(){let n=process.env.CLAUDE_PLUGIN_ROOT?.trim();if(!n)return null;try{let t=join$1(n,"dist","runtime-manifest.json"),e=JSON.parse(readFileSync(t,"utf8")),o=typeof e.bundleHashes?.mcp=="string"?e.bundleHashes.mcp:void 0,i=join$1(n,"node_modules","@devflow-tools","mcp-server","dist","delivery-tools.js"),r=existsSync$1(i)?createHash$1("sha256").update(readFileSync(i)).digest("hex"):"missing";return !o||o!==r?"DevFlow runtime build does not match the active plugin manifest":null}catch{return "DevFlow runtime manifest is missing or invalid"}}function ao(n,t,e){return new Set(["Write","Edit","NotebookEdit"]).has(n)?true:n==="Bash"?!it(n,t):!!(e?.startsWith("delivery_")&&e!=="delivery_status")}function it(n,t){return n==="Grep"||n==="Glob"?true:n!=="Bash"||typeof t.command!="string"?false:/^(?:ls|pwd|find|rg|grep|git\s+(?:status|diff|log|branch)|cat|sed|head|tail|wc)\b/u.test(t.command.trim())}async function co(n){if(Xe())return C();let t=Le();try{if(!n||n.trim()==="")return C();let e=JSON.parse(n),o=Date.now();try{maybeRunDiagnosticLogCleanup(F(),{now:o});}catch{}let i=F(),r=new U,s=resolveClaudeToolName(e.tool_name,e.tool_input),a=s.status==="unsupported"?void 0:s.canonicalName;a&&(typeof e.tool_input.projectRoot!="string"||!e.tool_input.projectRoot.trim())&&(e.tool_input.projectRoot=i);let c=e.session_id?.trim();if(!c)return z(ee);let l=new I(i),d=l.get(c)!==null;if(l.registerSession(c),d||await r.sendSessionStart(c,i,Date.now()),e.tool_name==="Skill"){let b=e.tool_input?.skill,_=b?je(b):null;if(_){let k=l.get(c)?.executionId,w=l.startExecution(c,_,ve(_));w.executionId&&w.executionId!==k&&await r.sendExecutionStart(w.executionId,c,_,w.lastActivityAt,i,w.requiredMcpTools);}}let u=l.get(c);a==="get_project_context"&&l.beginContextInitialization(c,e.tool_use_id),a&&(e.tool_input._devflow_session_id=c,e.tool_input._devflow_execution_id=u?.executionId??c,u?.activeTurnId&&(e.tool_input._devflow_turn_id=u.activeTurnId),u?.activeRequestId&&(e.tool_input._devflow_request_id=u.activeRequestId),u?.intentArtifactHash&&(e.tool_input._devflow_intent_artifact_hash=u.intentArtifactHash),u?.skillName&&(e.tool_input._devflow_active_skill=u.skillName),e.tool_use_id&&(e.tool_input._devflow_tool_use_id=e.tool_use_id));let p=e.tool_name.startsWith("mcp__"),m=a,f=l.get(c),R=new W(i,c,f?.executionId),y=R.getPhase(),g,v,L=io(i,e.tool_name,e.tool_input),x=re(i,c,e.tool_name,f?.executionId,e.tool_input),j=!x&&ao(e.tool_name,e.tool_input,m)?so():null;if(j)g=z(`DevFlow runtime build mismatch: ${j}. Refresh the plugin installation before relying on delivery_* results; file edits remain allowed.`);else if(L)v="DEVFLOW_DIRECTORY_READ_INVALID",g={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:L}};else if(x)v=x.code,g={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:`${x.message} Resolve the case blocker or obtain an authorized task lease before retrying.`}};else {let b=Je({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:i}),_=ze({projectRoot:i,sessionId:c,executionId:f?.executionId,toolUseId:e.tool_use_id,toolName:e.tool_name,toolInput:e.tool_input}),k=b?{permissionDecision:"deny",reason:b}:_.allowed?R.evaluate(e.tool_name,p):{permissionDecision:"deny",reason:_.reason,reasonCode:_.reasonCode},w=!p&&it(e.tool_name,e.tool_input)&&(y==="context_gathering"||y==="context_initializing")?ro():null;w?(g=z(`DevFlow MCP is unavailable or stale: ${w}. This read-only fallback is temporary; refresh the plugin installation and call ${projectClaudeToolName("get_project_context")} before editing.`),v=void 0):k.permissionDecision==="deny"?(v=b?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":k.reasonCode??"DEVFLOW_CONTEXT_REQUIRED",g={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:k.reason??"MCP context required"}}):k.additionalContext?g=z(k.additionalContext):g=C();}if(g.hookSpecificOutput.permissionDecision==="deny"&&nt(tt(i).profile)){let b=g.hookSpecificOutput.permissionDecisionReason??"policy deny";g=ot({projectRoot:i,sessionId:c,toolName:e.tool_name,code:v,reason:b}),v=void 0;}a&&(g.hookSpecificOutput.updatedInput=e.tool_input),t&&g.hookSpecificOutput.permissionDecision==="allow"&&(g.hookSpecificOutput.additionalContext=ee);let rt=f?.executionId??c,T={eventId:$e(c,e.tool_use_id),executionId:rt,sessionId:c,projectRoot:i,toolUseId:e.tool_use_id,timestamp:Date.now(),toolName:e.tool_name,toolType:p?"mcp":e.tool_name==="Agent"?"subagent":"direct",isMcpTool:p,mcpToolName:m,mcpEnforced:p&&(y==="context_gathering"||y==="context_initializing"),mcpFallback:!p&&(y==="context_gathering"||y==="context_initializing"),kind:oo(e.tool_name),input:e.tool_input,duration:0,blocked:g.hookSpecificOutput.permissionDecision==="deny",blockReason:g.hookSpecificOutput.permissionDecision==="deny"?v??"DEVFLOW_CONTEXT_REQUIRED":void 0},$=await r.sendEvent(T);$&&!T.blocked&&no(i,c,e.tool_name,e.tool_use_id,$,T.timestamp),$&&T.blocked&&await r.completeEvent({eventId:$,sessionId:c,error:v??"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-T.timestamp,completedAt:Date.now()});try{let b=Te(i),_={ts:o,tool:e.tool_name,sessionId:c,skill:u?.skillName??"(none)",requiredTools:u?.requiredMcpTools??[],isMcp:p,enforce:u?.executionId!==void 0,stateless:u?.executionId===void 0&&!p&&e.tool_name!=="Skill",bypassCount:b.bypassCount??0,decision:g.hookSpecificOutput.permissionDecision,env_CLAUDE_PLUGIN_ROOT:process.env.CLAUDE_PLUGIN_ROOT??"(unset)",cwd:process.cwd()};Pe(Fe(i),`${JSON.stringify(_)}
|
|
5
|
+
`);}catch{}return g}catch{try{let e=JSON.parse(n),o=F(),i=re(o,String(e.session_id??""),String(e.tool_name??""),void 0,e.tool_input);if(i)return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:i.message}}}catch{}return C()}}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 co(t);n(JSON.stringify(e));}),process.stdin.on("error",()=>{n(JSON.stringify(C())),process.exit(0);}),setTimeout(()=>{n(JSON.stringify(C())),process.exit(0);},4e3).unref();}export{co as handlePreToolUse};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {getLocalApiKey,getDevFlowStateRoot,getProjectStateDir,claudeCodeRuntimeAdapter,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,readRuntimeState}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase,retrievalLedgerTransitionId}from'@devflow-tools/database';import {MemoryGate}from'@devflow-tools/memory-engine';import {existsSync as existsSync$1,readFileSync,rmSync as rmSync$1,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1,unlinkSync as unlinkSync$1}from'fs';import {join as join$1}from'path';import {request}from'node:http';import {existsSync,mkdirSync,writeFileSync,renameSync,unlinkSync,rmSync,statSync,openSync,readSync,closeSync,lstatSync,constants,fstatSync,appendFileSync}from'node:fs';import {join}from'node:path';import {emitSemanticControlLog,rotateDiagnosticLogFile}from'@devflow-tools/telemetry';import {createHash}from'node:crypto';import {randomUUID,createHash as createHash$1}from'crypto';import'@devflow-tools/task-runtime';import {DatabaseSync}from'node:sqlite';function Z(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function
|
|
2
|
-
`;rotateDiagnosticLogFile({path:e,maxBytes:50*1024*1024,maxFiles:5,incomingBytes:Buffer.byteLength(i)}),appendFileSync(e,i);}catch{}}function ft(n){return new Promise(t=>setTimeout(t,n))}var Ie=1e4,vt=3e4,Q=500,ee=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,i,o,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:i,startedAt:o,projectRoot:r,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",i=Date.now(),o){let r={executionId:t,status:e,finishedAt:i,metadata:o},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(t,e,i){let o={id:t,projectRoot:e,startedAt:i,label:e.split("/").pop()??"unknown"},r=this.commitOrCache("session_start",o);return r&&this.postHttp("/api/telemetry/sessions",o),r}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let i={sessionId:t,finishedAt:e},o=this.commitOrCache("session_end",i);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),o}async flushCache(){try{let e=this.getDatabase(),i=e.listTelemetryFailures({unresolvedOnly:!0,limit:Q}).reverse();for(let o of i)try{this.applyOperation(o.operation,o.payload),e.resolveTelemetryFailure(o.id);}catch{}e.trimTelemetryFailures(Q);}catch{}let t=(existsSync$1(this.cacheDir)?readdirSync(this.cacheDir):[]).filter(e=>e.endsWith(".json")).map(e=>{let i=join$1(this.cacheDir,e);try{return {cacheFile:i,envelope:bt(JSON.parse(readFileSync(i,"utf8")))}}catch{return null}}).filter(e=>e!==null).sort((e,i)=>e.envelope.timestamp-i.envelope.timestamp||_e(e.envelope.operation)-_e(i.envelope.operation));for(let{cacheFile:e,envelope:i}of t)try{let o=this.getDatabase();o.insertTelemetryFailure({id:i.id,operation:i.operation,payload:i.payload,error:i.failure,createdAt:i.timestamp}),this.applyOperation(i.operation,i.payload),o.resolveTelemetryFailure(i.id),unlinkSync$1(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(i){return this.cacheOperation(t,e,i),false}}applyOperation(t,e){let i=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(i,e),i.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(i,e),i.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":i.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":i.ensureSession(e),i.insertRun({id:we(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!i.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,failureCategory:e.failureCategory,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":i.closeSession(e.sessionId,e.finishedAt),i.updateRun(we(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let i=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!i)throw new Error("Canonical session ID is required for telemetry");let o=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:i,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,i){let o=Date.now(),r={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:i instanceof Error?i.message:String(i),timestamp:o};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:o}),s.trimTelemetryFailures(Q),this.scheduleRetry();return}catch{}try{existsSync$1(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync$1(s,JSON.stringify(r,null,2),{mode:384}),this.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-Q)))unlinkSync$1(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},vt).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){W(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=Ie?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,Ie)}...`}}};function _e(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function we(n){return `hook-run:${n}`}function bt(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}async function Re(n){let t=!n.memory,e=n.memory??new MemoryGate(n.projectRoot),i=0,o=0;try{await e.forceWarmUp(),n.trigger==="session_end"&&(i=await e.releasePendingDistillLeases(n.sessionId)),o=e.getPendingEventCount(n.sessionId,n.trigger!=="session_end");}finally{t&&e.close();}let r=Date.now(),s=n.trigger==="session_end"&&n.sessionId?`distill:session_end:${createHash("sha256").update(`${n.projectRoot}\0${n.sessionId}`).digest("hex").slice(0,24)}`:`distill:${r}:${Math.random().toString(36).slice(2,10)}`,a={id:s,pendingEvents:o,releasedLeases:i,trigger:n.trigger,sessionId:n.sessionId,details:n.details};try{let d=openGlobalDevFlowDatabase();try{d.recordMemoryDistillCheckpoint({id:s,projectRoot:n.projectRoot,sessionId:n.sessionId,trigger:n.trigger,pendingEvents:o,releasedLeases:i,details:n.details,createdAt:r}),d.insertEvent({kind:"memory_distill_requested",timestamp:r,success:!0,metadata:{...a,projectRoot:n.projectRoot}});}finally{d.close();}}catch(d){throw d}return a}function Ae(n){return Buffer.from(n,"utf8").toString("base64url")}function Et(n,t,e){let i=t?.trim();if(i){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(i)?i:`tool-${createHash$1("sha256").update(i.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${o}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function $e(n){return `${n}:legacy-journal`}var G=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(z(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let i=this.get(e);if(i)return i.lastActivityAt=Date.now(),this.persist(i),i;let o=Date.now(),r={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:o,lastActivityAt:o};return this.sessions.set(e,r),this.persist(r),r}startExecution(t,e,i){let o=this.registerSession(t);return (!o.executionId||o.skillName!==e)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=e,o.requiredMcpTools=[...new Set(i)],delete o.contextInitialization,o.lastActivityAt=Date.now(),this.persist(o),o}beginContextInitialization(t,e){let i=this.registerSession(t);return i.contextInitialization={startedAt:Date.now(),...e?{toolUseId:e}:{}},i.lastActivityAt=Date.now(),this.persist(i),i}completeContextInitialization(t,e){let i=this.get(t);return i?(e&&i.contextInitialization?.toolUseId&&i.contextInitialization.toolUseId!==e||(delete i.contextInitialization,i.lastActivityAt=Date.now(),this.persist(i)),i):null}bindTaskIdentity(t,e){let i=this.registerSession(t);return i.activeTurnId=e.turnId,i.activeRequestId=e.requestId,i.intentArtifactHash=e.intentArtifactHash,i.lastActivityAt=Date.now(),this.persist(i),i}get(t){let e=t.trim();if(!e)return null;let i=this.sessions.get(e);if(i)return this.replayEvidenceJournal(i),i;let o=this.snapshotPath(e);if(!existsSync$1(o))return null;try{let r=JSON.parse(readFileSync(o,"utf8"));return r.sessionId!==e||r.projectRoot!==this.projectRoot?null:(r.requiredMcpTools=Array.isArray(r.requiredMcpTools)?r.requiredMcpTools:[],r.evidenceObligations=xe(r.evidenceObligations),r.evidenceDegradations=Te(r.evidenceDegradations),r.evidenceOutcomes=De(r.evidenceOutcomes),this.replayEvidenceJournal(r),this.sessions.set(e,r),r)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let i=structuredClone(e);return delete e.executionId,delete e.skillName,delete e.contextInitialization,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),i}addEvidenceObligation(t,e,i=Date.now(),o){let r=this.registerSession(t),a=(o?void 0:r.evidenceObligations.find(u=>u.contractId===e.id))?.obligationId??Et(e.id,o,i);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:i,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let d=r.evidenceObligations.find(u=>u.obligationId===a);return d?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(d)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,i,o,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(g=>g.obligationId===e);if(!s||!a)return null;let d=/^[a-f0-9]{64}$/.test(o)?o:"";if(!d)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:d,violations:i.slice(0,16).map(g=>g.slice(0,240))},`correction\0${e}\0${d}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let u=s.evidenceObligations.find(g=>g.obligationId===e);return u?structuredClone(u):null}resolveEvidenceObligation(t,e){let i=this.get(t);if(!i)return false;let o=i.evidenceObligations.find(s=>s.obligationId===e);if(!o)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve\0${e}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}resolveDegradedEvidence(t,e){let i=this.get(t),o=i?.evidenceDegradations.find(s=>s.obligationId===e);if(!i||!o)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve-degraded\0${e}\0${r}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}degradeEvidenceObligation(t,e,i,o=Date.now()){let r=this.get(t),s=r?.evidenceObligations.find(d=>d.obligationId===e);if(!r||!s)return false;let a=i.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:o,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(r),r.lastActivityAt=o,this.persist(r),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync$1(this.snapshotPath(e),{force:true}),rmSync$1(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${Ae(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Ae(t))}appendEvidenceEvent(t,e,i){let o=this.evidenceJournalDir(t);mkdirSync$1(o,{recursive:true,mode:448});let r=createHash$1("sha256").update(i).digest("hex"),s=join$1(o,`${e.kind}-${r}.json`);if(existsSync$1(s))return;let a=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(d){if(d.code!=="EEXIST")throw d}finally{rmSync$1(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=xe(t.evidenceObligations),t.evidenceDegradations=Te(t.evidenceDegradations),t.evidenceOutcomes=De(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync$1(e))return;let i;try{i=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let o=i.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=At(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||Ce(r.kind)-Ce(s.kind));for(let r of o)this.applyEvidenceEvent(t,r);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let i=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(i)return;let s=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let o=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!o||i||o.correctionFingerprint===e.fingerprint)return;o.attempt+=1,o.correctionRequested=true,o.correctionRequestedAt=e.at,o.correctionFingerprint=e.fingerprint,o.violations=e.violations;return}let r=o?.attempt??i?.attempt??0;if(e.kind==="resolve"&&i?.status==="degraded")t.evidenceOutcomes=t.evidenceOutcomes.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations=t.evidenceDegradations.filter(s=>s.obligationId!==e.obligationId);else if(i)return;e.kind==="degrade"?(t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r,contract:o?.contract})):t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}});}persist(t){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),i=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(i,JSON.stringify(t),{mode:384}),renameSync$1(i,e);}};function xe(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)||!qe(e.contract))return [];let i=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:$e(e.contractId),o=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,r=e.correctionFingerprint??o;return r!==void 0&&!/^[a-f0-9]{64}$/.test(r)?[]:[{...e,obligationId:i,correctionFingerprint:r}]}).slice(-8):[]}function Te(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function De(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function At(n){if(!n||typeof n!="object")return null;let t=n,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let o={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:$e(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return qe(t.contract)?{kind:e,...o,contract:t.contract}:null;if(e==="correction"){let r=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)&&Array.isArray(t.violations)&&t.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:e,...o,fingerprint:r,violations:t.violations}:null}return e==="resolve"?{kind:e,...o}:typeof t.reason=="string"&&t.reason.length<=240?{kind:e,...o,reason:t.reason}:null}function Ce(n){return n==="add"?0:n==="correction"?1:2}function qe(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,i=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(i)&&i.length<=16&&i.every(o=>typeof o=="string"&&o.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function Fe(n,t){let e=Ot(n);mkdirSync(e,{recursive:true,mode:448});let i=join(e,`${t.receiptId}.json`);if(existsSync(i))return t.receiptId;let o=`${i}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384});try{renameSync(o,i);}catch(r){try{unlinkSync(o);}catch{}if(!existsSync(i))throw r}return t.receiptId}function Ot(n){return join(z(n),"session-finalize-pending")}var _=emitSemanticControlLog;var Nt=512*1024,zt=500;var Ht=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function Ut(n){let t=false,e=[],i=[];for(let o of n){if(/^\s*```/.test(o)){t=!t,e.push(""),i.push(o.replace(/^\s*```+[^\s`]*/,"").replace(/```+\s*$/,"").trim());continue}e.push(t?"":o.replace(/`[^`]*`/g,"").trim()),i.push(o.replace(/`([^`]*)`/g,(r,s)=>Bt(s)?"":s).trim());}return {headingLines:e,claimLines:i}}function Bt(n){let t=n.trim().slice(0,256);return !t||/\s/.test(t)||n.trim().length>256?false:/^[A-Za-z_$][\w$.-]*$/.test(t)||/^(['"])[^'"`]*\1$/.test(t)}function Jt(n,t){if(!n||n.length>4096)return {degradationReason:"transcript_path_missing"};let e;try{let i=lstatSync(n);if(!i.isFile()||i.isSymbolicLink())return {degradationReason:"transcript_path_unsafe"};e=openSync(n,constants.O_RDONLY|(constants.O_NOFOLLOW??0));let o=fstatSync(e);if(!o.isFile()||o.dev!==i.dev||o.ino!==i.ino)return {degradationReason:"transcript_path_changed"};let r=Math.min(o.size,Nt),s=Buffer.alloc(r),a=0;for(;a<r;){let h=readSync(e,s,a,r-a,o.size-r+a);if(h===0)break;a+=h;}let d=s.subarray(0,a).toString("utf8");o.size>r&&(d=d.slice(Math.max(0,d.indexOf(`
|
|
3
|
-
`)+1)));let u=d.split(/\r?\n/).slice(-
|
|
4
|
-
`):"";if(g.trim()){let c=g.trim(),y=typeof a.id=="string"&&a.id?`message:${a.id}`:typeof r.uuid=="string"&&r.uuid?`uuid:${r.uuid}`:`record:${String(r.timestamp??"")}:${i}:${createHash("sha256").update(o).digest("hex")}`,v=createHash("sha256").update(c).digest("hex"),
|
|
5
|
-
`).slice(0,4e3);if(!n||typeof n!="object")return "";let t=n;return [t.text,t.content,t.message].map(
|
|
6
|
-
`).slice(0,4e3)}var cn={open:["intent_bound"],intent_bound:["context_ready","context_degraded"],context_ready:["action_required","action_not_required"],context_degraded:["action_required","action_not_required"],action_required:["action_satisfied","action_degraded","action_failed"],action_not_required:["memory_decided","memory_quarantined"],action_satisfied:["memory_decided","memory_quarantined"],action_degraded:["memory_decided","memory_quarantined"],action_failed:["action_satisfied","action_degraded"],memory_decided:["closed","closed_with_degradation","closed_with_retry_work"],memory_quarantined:["closed_with_degradation","closed_with_retry_work"],closed:[],closed_with_degradation:[],closed_with_retry_work:[]};function Ve(n){return dn(n)}function dn(n){let t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=mn(t,n.artifact);if(gn(e.toState))return e;let i=t.getContextReceiptForRequest(n.artifact.projectRoot,n.artifact.sessionId,n.artifact.requestId),o=t.getMemoryTurn(n.artifact.turnId),r=n.artifact.intent==="memory"||o?.source==="explicit_intent";if(!i&&!r)return e;let s=i?ln(n.artifact,i):"context_ready";e.toState==="intent_bound"&&(e=E(t,e,n,s,r?"task_context_not_required":s==="context_ready"?"canonical_context_receipt_ready":"canonical_context_receipt_degraded"));let a=i?un(n.artifact,i):"action_not_required";if((e.toState==="context_ready"||e.toState==="context_degraded")&&(a==="action_not_required"?e=E(t,e,n,"action_not_required","task_action_not_required"):e=E(t,e,n,"action_required","canonical_action_obligation_present")),e.toState==="action_required"){if(a==="action_required")return e;if(a==="action_failed")return E(t,e,n,"action_failed","canonical_action_attempt_failed");a==="action_degraded"?e=E(t,e,n,"action_degraded","canonical_action_unavailable_or_degraded"):a==="action_satisfied"&&(e=E(t,e,n,"action_satisfied","canonical_action_succeeded"));}if(e.toState==="action_failed")if(a==="action_satisfied")e=E(t,e,n,"action_satisfied","canonical_action_retry_succeeded");else if(a==="action_degraded")e=E(t,e,n,"action_degraded","canonical_action_retry_degraded");else return e;let d=s==="context_degraded"||a==="action_degraded";return ["action_not_required","action_satisfied","action_degraded"].includes(e.toState)&&(e=E(t,e,n,n.memoryStatus==="pending"?"memory_quarantined":"memory_decided",n.memoryStatus==="pending"?n.reason:`canonical_memory_${n.memoryStatus}`)),e.toState==="memory_decided"?E(t,e,n,d?"closed_with_degradation":"closed",n.reason):e.toState==="memory_quarantined"?E(t,e,n,n.retryOwned?"closed_with_retry_work":"closed_with_degradation",n.retryOwned?"durable_retry_owner_confirmed":"terminal_obligation_unowned"):e}finally{t.close();}}function ln(n,t){return n.intent==="memory"||n.intent==="knowledge"||(t.selectedFiles?.length??0)>0?"context_ready":"context_degraded"}function un(n,t){let e=t.canonicalAction,o=(e?(t.actionAttempts??[]).filter(r=>r.tool===e.tool):[]).at(-1);return t.actionSatisfiedAt||o?.status==="succeeded"?"action_satisfied":o&&["failed","timeout","unavailable"].includes(o.status)?"action_failed":t.actionDegradation||e?.status==="degraded"||e?.status==="unsupported"?"action_degraded":e?.required||fn(n)?"action_required":"action_not_required"}function fn(n){return ["create","modify","debug","test","format"].includes(n.action)||["feature","refactor","performance"].includes(n.intent)}function mn(n,t){let e=n.getLatestTerminalTransition(t.projectRoot,t.sessionId,t.turnId);if(!e)throw new Error(`TERMINAL_INTENT_STATE_MISSING:${t.turnId}`);return e}function E(n,t,e,i,o){if(!cn[t.toState]?.includes(i))throw new Error(`TERMINAL_PATH_UNAVAILABLE:${t.toState}->${i}`);let r=t.sequence+1,s=`terminal:${createHash("sha256").update(`${e.artifact.artifactHash}\0${r}\0${i}`).digest("hex").slice(0,24)}`,a=n.appendTerminalTransition({projectRoot:e.artifact.projectRoot,projectId:e.artifact.projectId,hostId:e.artifact.hostId,sessionId:e.artifact.sessionId,turnId:e.artifact.turnId,requestId:e.artifact.requestId,executionId:e.artifact.executionId,sequence:r,fromState:t.toState,toState:i,receiptId:s,sourceReceiptId:e.memoryReceiptId??t.receiptId,reason:o,payload:{memoryStatus:e.memoryStatus,retryOwned:e.retryOwned??false,sourceIntentHash:e.artifact.artifactHash},createdAt:Date.now()});return _({event:"terminal.state.transitioned",identity:{projectRoot:e.artifact.projectRoot,projectId:e.artifact.projectId,hostId:e.artifact.hostId,sessionId:e.artifact.sessionId,turnId:e.artifact.turnId,requestId:e.artifact.requestId,...e.artifact.executionId?{executionId:e.artifact.executionId}:{}},level:i==="closed"?"info":i.includes("degradation")||i.includes("retry")||i==="action_failed"?"warn":"info",timestamp:Date.now(),data:{fromState:t.toState,nextState:i,receiptId:s,reason:o}}),a}function gn(n){return n==="closed"||n==="closed_with_degradation"||n==="closed_with_retry_work"}function We(n,t){let e=join(n,".devflow","delivery-line","state.db");if(!existsSync(e)||!t.trim())return 0;let i;try{i=new DatabaseSync(e,{timeout:250});let o=i.prepare("SELECT id, payload FROM delivery_cases WHERE id = ? OR json_extract(payload, '$.sessionId') = ?").all(t,t),r=0,s=!!i.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'delivery_events'").get();for(let a of o){let d="incomplete";try{let u=JSON.parse(a.payload);d=u.evidence?.some(g=>g.metadata?.trust==="external-untrusted")?"untrusted":u.stage==="delivered"?"clean":"incomplete";}catch{}if(r+=Number(i.prepare("UPDATE delivery_tasks SET lease_owner = NULL, lease_expires_at = NULL WHERE case_id = ? AND lease_owner IS NOT NULL").run(a.id).changes),s){let u=`session.closed:${a.id}:${t}`;i.prepare("INSERT OR IGNORE INTO delivery_events (id,case_id,idempotency_key,actor,type,payload,created_at,processed_at) VALUES (?,?,?,?,?,?,?,NULL)").run(u,a.id,u,JSON.stringify({id:"devflow:session-end",kind:"system"}),"session.closed",JSON.stringify({sessionId:t,releasedLeases:r,outcome:d}),Date.now());}}return r}catch{return 0}finally{i?.close();}}function _n(n){let t={committed:0,skipped:0,pending:0},e=[];for(let i of n)t[i.status]+=1,i.receiptId&&e.push(i.receiptId);return {memoryReceiptIds:[...new Set(e)],missingMemoryDecisionCount:t.pending,memoryTurnOutcomes:t}}function A(n){return (n instanceof Error?n.message:String(n)).trim().slice(0,240)||"memory_lifecycle_unavailable"}var M=class extends Error{constructor(t,e){super(`session_finalize_${t}:${e}`),this.name="SessionFinalizationRetryableError",this.category=`session_finalize_${t}`;}};function Y(n){let t;try{t=openGlobalDevFlowDatabase();let e=(n.executionId?t.getSkillExecution(n.executionId):null)??t.getLatestSkillExecutionForSession(n.sessionId),i={stage:n.stage,reason:n.reason,degradedAt:Date.now()};e&&t.mergeSkillExecutionMetadata(e.executionId,{...n.metadata,sessionFinalizationDegradations:[i]}),t.insertEvent({kind:"session_finalize_degraded",timestamp:i.degradedAt,success:!1,metadata:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:e?.executionId,...i}}),_({event:"hook.session_end.degraded",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:e?.executionId},level:"warn",timestamp:i.degradedAt,data:{stage:n.stage,reason:n.reason}});}catch{}finally{t?.close();}}function wn(n,t=Z(),e=true,i,o=true){let r;try{r=JSON.parse(n);}catch{return null}let s=r.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${t}\0${s}`).digest("hex").slice(0,24)}`,d={inputJson:n,sessionId:s,cleanupSharedState:e,executionId:i};try{We(t,s);}catch{}let u;try{u=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let g=u.requestSessionClosure({receiptId:a,projectRoot:t,sessionId:s,payload:d}),c=u.getWorkByIdempotencyKey(a),y={status:g.state==="closed"||g.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:c?.state??"pending",closureState:g.state,pendingWorkCount:g.pendingWorkCount,...c?.id?{workItemId:c.id}:{}};return _({event:"hook.session_end.completed",identity:{projectRoot:t,sessionId:s,executionId:i,terminalReceipt:a},level:y.status==="completed"?"info":"debug",timestamp:Date.now(),data:{stage:"enqueue",...y}}),y}catch(g){if(!o)throw g;return Fe(t,{receiptId:a,...d}),_({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:s,executionId:i,terminalReceipt:a},level:"warn",timestamp:Date.now(),data:{stage:"enqueue",reason:A(g),fallback:"durable_spool"}}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{u?.close();}}async function fr(n,t=Z(),e=true,i){let o;try{o=JSON.parse(n);}catch{return}let r=o.session_id?.trim();if(!r)return;let s=new G(t),a=s.get(r),d=Je({projectRoot:t,sessionId:r,transcriptPath:o.transcript_path}),u={evidenceDegradations:a?.evidenceDegradations??[],evidenceContractOutcomes:a?.evidenceOutcomes??[],pendingEvidenceContractIds:a?.evidenceObligations.map(h=>h.contractId)??[],transcriptReconciliation:d},g=i?.telemetry??new ee,c=!i?.telemetry,y=false,v;try{try{await g.flushAndAggregate();}catch{}let h=Date.now(),b=i?.executionId??a?.executionId,D;try{let m=openGlobalDevFlowDatabase();try{D=m.listSessionMemoryTurnsForReconciliation(t,r);for(let l of D){let p=`memory:${l.turnId}`,f=m.getSessionObligation(t,r,p);f?f.state==="open"&&l.status!=="pending"&&m.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:p,state:"satisfied",receiptId:l.receiptId,reason:l.reason,resolvedAt:l.decidedAt}):m.upsertSessionObligation({obligationId:p,projectRoot:t,sessionId:r,turnId:l.turnId,kind:"memory_decision",state:l.status==="pending"?"open":"satisfied",payload:{eventId:l.eventId,promptHash:l.promptHash},receiptId:l.receiptId,reason:l.reason,createdAt:l.createdAt,updatedAt:l.decidedAt??l.createdAt,resolvedAt:l.decidedAt});}}finally{m.close();}}catch(m){let l=A(m),p={...u,memoryEventReconciliation:{status:"degraded",stage:"turn_load",reason:l,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw Y({projectRoot:t,sessionId:r,executionId:b,stage:"turn_load",reason:l,metadata:p}),new M("turn_load",l)}let C=_n(D),O=i?.memory??(v=new MemoryGate(t)),I={status:"completed"};try{I=typeof O.reconcileTurnObservationLineage=="function"?{status:"completed",...await O.reconcileTurnObservationLineage(D)}:{status:"unsupported_adapter",committed:0,skipped:0,quarantined:0,unlinked:0};}catch(m){let l=A(m);throw I={status:"degraded",reason:l},Y({projectRoot:t,sessionId:r,executionId:b,stage:"memory_lineage",reason:l,metadata:{...C,...u,memoryLineageReconciliation:I}}),new M("memory_lineage",l)}let q={status:"unknown",selected:0,consumed:0,unknown:0,positive:0,negative:0};try{let m=Le(o.transcript_path),l=openGlobalDevFlowDatabase(),p="unknown",f="no_terminal_host_action_evidence",J,T,$,L=[],ne=[];try{let P=l.listHostActionsForSession(t,r,b),ge=P.filter(S=>S.state==="verified"),ie=P.filter(S=>["failed","cancelled","degraded"].includes(S.state));ie.length>0?(p="negative",f=`terminal_host_action_${ie[0].state}`):ge.length>0&&(p="positive",f="host_action_verified");let K=ie[0]??ge.at(-1);if(J=K?.runId,T=K?.contextReceipt,$=K?.evidenceHash,ne=P.flatMap(S=>{let N=S.report.toolUseIds;return Array.isArray(N)?N.filter(V=>typeof V=="string"):[]}),!K&&b){let S=l.getSkillExecution(b),N=S?.metadata&&typeof S.metadata=="object"&&Array.isArray(S.metadata.policyVerificationOutcomes)?S.metadata.policyVerificationOutcomes:[],V=N.find(j=>j.status==="failed"),re=N.filter(j=>j.status==="passed");V?(p="negative",f="policy_verification_failed",$=typeof V.receiptId=="string"?V.receiptId:void 0):re.length>0&&(p="positive",f="policy_verification_passed",$=typeof re.at(-1)?.receiptId=="string"?String(re.at(-1).receiptId):void 0),T=l.getActiveContextReceipt(t,r,b)?.contextHash,ne=N.map(j=>j.command).filter(j=>typeof j=="string");}T&&(L=l.getSemanticExecutionContextByHash(T)?.dispositions.filter(S=>S.requirement==="required").map(S=>S.channel)??[]);}finally{l.close();}let me=He({projectRoot:t,sessionId:r,executionId:b,outcome:p,outcomeReason:f,verificationReceipt:$,requiredChannels:L,finishedAt:h}),Ye=await O.attributeRetrievalBenefits({sessionId:r,executionId:b,outcome:p,outcomeReason:f,workflowRunId:J,contextReceipt:T,toolEvidence:ne,verificationReceipt:$,consumedSourceIds:me.consumedSources.filter(P=>P.sourceType==="memory").map(P=>P.sourceId)});q={status:m?"evaluated":"unknown",...Ye,retrievalLedger:me};}catch(m){q={...q,status:"degraded",reason:A(m)};}let w;try{w=await O.reconcileDecidedTurnEventWindows(r,D,h);}catch(m){let l=A(m),p={...C,...u,memoryEventReconciliation:{status:"degraded",stage:"event_reconciliation",reason:l,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw Y({projectRoot:t,sessionId:r,executionId:b,stage:"event_reconciliation",reason:l,metadata:p}),new M("event_reconciliation",l)}let x;try{x=await Re({projectRoot:t,sessionId:r,trigger:"session_end",memory:O,details:{eventReconciliation:w},strictPersistence:!0});}catch(m){let l=A(m),p={...C,...u,memoryEventReconciliation:{status:"completed",...w,checkpointPending:null},memoryCheckpointDegradation:l};throw Y({projectRoot:t,sessionId:r,executionId:b,stage:"checkpoint",reason:l,metadata:p}),new M("checkpoint",l)}let U={memoryLineageReconciliation:I,memoryBenefitAttribution:q,memoryEventReconciliation:{status:"completed",...w,checkpointPending:x.pendingEvents},memoryDistillCheckpoint:x};try{let m=openGlobalDevFlowDatabase();try{let l=`session-finalize:${r}:events`,p=Math.max(Number(x.pendingEvents??0),Number(w.remainingUndecided??0)),f=m.getSessionObligation(t,r,l);p>0?m.upsertSessionObligation({obligationId:l,projectRoot:t,sessionId:r,executionId:b,kind:"session_finalize",state:"open",payload:{pendingEvents:p,reconciliation:w,checkpointId:x.id},reason:"active_unprocessed_session_events",createdAt:f?.createdAt??h,updatedAt:h}):f?.state==="open"&&m.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:l,state:"satisfied",reason:"session_events_reconciled",resolvedAt:h});}finally{m.close();}}catch(m){_({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:b},level:"warn",timestamp:Date.now(),data:{stage:"obligation_persistence",reason:A(m)}});}try{await O.closeSession(r),v&&(v.close(),v=void 0);}catch(m){let l=A(m),p={...C,...u,...U,memorySessionCloseDegradation:l};throw Y({projectRoot:t,sessionId:r,executionId:b,stage:"memory_close",reason:l,metadata:p}),new M("memory_close",l)}let k={...C,...u,...U},B=[];try{let m=openGlobalDevFlowDatabase();try{let l=new Map(m.listLatestTaskIntentArtifacts(t,r).map(p=>[p.turnId,p]));for(let p of D){let f=l.get(p.turnId);if(!f)continue;let T=[m.getWorkByIdempotencyKey(`memory-turn:capture_prompt:${p.turnId}`),m.getWorkByIdempotencyKey(`memory-turn:commit_explicit:${p.turnId}`)].filter(Boolean).some(L=>L.state==="pending"||L.state==="leased"||L.state==="failed"),$=Ve({artifact:f,memoryStatus:p.status,memoryReceiptId:p.receiptId,retryOwned:T,reason:p.status==="pending"?"session_end_memory_pending":"session_end_reconciled"});B.push({turnId:p.turnId,state:$.toState,receiptId:$.receiptId});}}finally{m.close();}}catch(m){B.push({state:"terminal_integrity_failure",reason:A(m)});}k.terminalOutcomes=B,y=!0;let R;try{R=openGlobalDevFlowDatabase();let m=b;if(m)try{R.reconcileSkillExecution(m,"completed",h,k);let f=R.getSkillExecution(m);await W("/api/telemetry/skill-execution/complete",{executionId:m,finishedAt:h,status:"completed",summary:{totalToolCalls:f?.totalToolCalls??0,mcpToolCalls:f?.mcpToolCalls??0,directToolCalls:f?.directToolCalls??0,subagentCount:f?.subagentCount??0,totalDuration:f?.totalDuration??0,mcpComplianceRate:f?.mcpComplianceRate??0,missedTools:f?.missedMcpTools??[],actualFailureCount:f?.failedToolCalls??0,fallbackCount:f?.fallbackCount??0,fallbackReasons:f?.fallbackReasons??[]},metadata:k},{fallbackReason:"skill_execution_already_reconciled_locally"});}catch{}let l=R.reconcileRunningSkillExecutionsForSession(r,h,{closureReason:"session_finalize",...k});for(let f of l)await W("/api/telemetry/skill-execution/complete",{executionId:f.executionId,finishedAt:f.finishedAt,status:f.status,summary:{totalToolCalls:f.totalToolCalls??0,mcpToolCalls:f.mcpToolCalls??0,directToolCalls:f.directToolCalls??0,subagentCount:f.subagentCount??0,totalDuration:f.totalDuration??0,mcpComplianceRate:f.mcpComplianceRate??0,missedTools:f.missedMcpTools??[],actualFailureCount:f.failedToolCalls??0,fallbackCount:f.fallbackCount??0,fallbackReasons:f.fallbackReasons??[]},metadata:k},{fallbackReason:"skill_execution_already_reconciled_locally"});let p=R.getLatestSkillExecutionForSession(r);if(p&&!l.some(f=>f.executionId===p.executionId)&&R.mergeSkillExecutionMetadata(p.executionId,k),e){R.deleteHookReceipt(t);let f=z(t),J=createHash("sha256").update(t).digest("hex").slice(0,12);for(let T of [`session-id-${J}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join(f,T),{force:!0});}R.deleteContextReceipt(t,r);}catch(m){_({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:b},level:"warn",timestamp:Date.now(),data:{stage:"lifecycle_telemetry",reason:A(m),fallback:"fail_open"}});}finally{R?.close();}try{await g.endSession(r),await g.flushAndAggregate();}catch(m){_({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:b},level:"warn",timestamp:Date.now(),data:{stage:"telemetry_flush",reason:A(m),fallback:"local_state_authoritative"}});}}finally{if(v)try{v.close();}catch{}c&&g.close(),y&&s.removeSession(r),_({event:y?"hook.session_end.completed":"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:i?.executionId??a?.executionId},level:y?"info":"warn",timestamp:Date.now(),data:{stage:"finalize",criticalStagesCompleted:y,transcriptStatus:d.status}});}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{let e=wn(t.trim()||process.argv[2]||"");e&&n(JSON.stringify(e)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}export{_n as buildMemoryTurnOutcomeMetadata,wn as enqueueSessionEndFinalization,fr as handleSessionEnd};
|
|
1
|
+
import {getLocalApiKey,getDevFlowStateRoot,getProjectStateDir,claudeCodeRuntimeAdapter,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,readRuntimeState}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase,retrievalLedgerTransitionId}from'@devflow-tools/database';import {MemoryGate}from'@devflow-tools/memory-engine';import {existsSync as existsSync$1,readFileSync,rmSync as rmSync$1,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1,unlinkSync as unlinkSync$1}from'fs';import {join as join$1}from'path';import {request}from'node:http';import {existsSync,mkdirSync,writeFileSync,renameSync,unlinkSync,rmSync,statSync,openSync,readSync,closeSync,lstatSync,constants,fstatSync,appendFileSync}from'node:fs';import {join}from'node:path';import {emitSemanticControlLog,rotateDiagnosticLogFile}from'@devflow-tools/telemetry';import {createHash}from'node:crypto';import {randomUUID,createHash as createHash$1}from'crypto';import'@devflow-tools/task-runtime';import {DatabaseSync}from'node:sqlite';function Z(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function B(n){return getProjectStateDir(Z(n))}function se(n,t,e){try{let i=openGlobalDevFlowDatabase();try{i.insertEvent({kind:n,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{i.close();}}catch{}}var lt=getLocalApiKey(),ae=join(getDevFlowStateRoot(),"errors");async function V(n,t,e={}){let i=e.endpoint??process.env.DEVFLOW_SERVER_URL?.trim()??ut();if(!i)return {delivered:false,suppressed:false,fallbackReason:"runtime_not_ready"};let o=e.timeout??1500,r=e.durableMirror??true,s=e.maxRetries??(r?0:2),a=e.circuitBreaker??true,d=acquireRuntimeHttpCircuit(i,n);if(a&&!d.allowed)return {delivered:false,suppressed:true,fallbackReason:d.state.fallbackReason};let u;for(let c=0;c<=s;c+=1)try{return await ft(i,n,t,o),a&®isterRuntimeHttpSuccess(i,n).transitioned&&se("http_circuit_transition",{endpoint:i,path:new URL(n,i).pathname,previous:d.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(y){u=y instanceof Error?y:new Error(String(y)),c<s&&await mt(Math.min(100*2**c,1e3));}if(!u)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return ye(n,u),{delivered:false,suppressed:false,fallbackReason:u.message};let g=registerRuntimeHttpFailure(i,n,e.fallbackReason??(r?"local_durable_mirror":"http_delivery_failed"));return g.transitioned&&(ye(n,u),se("http_circuit_transition",{endpoint:i,path:new URL(n,i).pathname,previous:d.state.status,status:"open",failures:g.state.failures,openUntil:g.state.openUntil,fallbackReason:g.state.fallbackReason})),{delivered:false,suppressed:false,fallbackReason:g.state.fallbackReason}}function ut(){let n=readRuntimeState();return n?.status==="ready"&&n.dashboardAvailable?n.url:void 0}function ft(n,t,e,i){return new Promise((o,r)=>{let s=JSON.stringify(e),a=new URL(t,n),d=false,u=c=>{d||(d=true,c?r(c):o());},g=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":lt,"Content-Length":Buffer.byteLength(s)},timeout:i},c=>{c.on("error",u),c.on("end",()=>{let y=c.statusCode??0;u(y>=200&&y<300?void 0:new Error(`HTTP ${y}`));}),c.resume();});g.on("error",u),g.on("timeout",()=>g.destroy(new Error(`HTTP mirror timed out after ${i}ms`))),g.write(s),g.end();})}function ye(n,t){try{existsSync(ae)||mkdirSync(ae,{recursive:!0});let e=join(ae,"http-errors.log"),i=`${new Date().toISOString()} | ${n} | ${t.message}
|
|
2
|
+
`;rotateDiagnosticLogFile({path:e,maxBytes:50*1024*1024,maxFiles:5,incomingBytes:Buffer.byteLength(i)}),appendFileSync(e,i);}catch{}}function mt(n){return new Promise(t=>setTimeout(t,n))}var _e=1e4,bt=3e4,Q=500,ee=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,i,o,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:i,startedAt:o,projectRoot:r,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",i=Date.now(),o){let r={executionId:t,status:e,finishedAt:i,metadata:o},s=this.commitOrCache("execution_complete",r);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),s}async sendSessionStart(t,e,i){let o={id:t,projectRoot:e,startedAt:i,label:e.split("/").pop()??"unknown"},r=this.commitOrCache("session_start",o);return r&&this.postHttp("/api/telemetry/sessions",o),r}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let i={sessionId:t,finishedAt:e},o=this.commitOrCache("session_end",i);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),o}async flushCache(){try{let e=this.getDatabase(),i=e.listTelemetryFailures({unresolvedOnly:!0,limit:Q}).reverse();for(let o of i)try{this.applyOperation(o.operation,o.payload),e.resolveTelemetryFailure(o.id);}catch{}e.trimTelemetryFailures(Q);}catch{}let t=(existsSync$1(this.cacheDir)?readdirSync(this.cacheDir):[]).filter(e=>e.endsWith(".json")).map(e=>{let i=join$1(this.cacheDir,e);try{return {cacheFile:i,envelope:It(JSON.parse(readFileSync(i,"utf8")))}}catch{return null}}).filter(e=>e!==null).sort((e,i)=>e.envelope.timestamp-i.envelope.timestamp||we(e.envelope.operation)-we(i.envelope.operation));for(let{cacheFile:e,envelope:i}of t)try{let o=this.getDatabase();o.insertTelemetryFailure({id:i.id,operation:i.operation,payload:i.payload,error:i.failure,createdAt:i.timestamp}),this.applyOperation(i.operation,i.payload),o.resolveTelemetryFailure(i.id),unlinkSync$1(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(i){return this.cacheOperation(t,e,i),false}}applyOperation(t,e){let i=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(i,e),i.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(i,e),i.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":i.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":i.ensureSession(e),i.insertRun({id:Re(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!i.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,failureCategory:e.failureCategory,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":i.closeSession(e.sessionId,e.finishedAt),i.updateRun(Re(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let i=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!i)throw new Error("Canonical session ID is required for telemetry");let o=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:i,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,i){let o=Date.now(),r={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:i instanceof Error?i.message:String(i),timestamp:o};try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:o}),s.trimTelemetryFailures(Q),this.scheduleRetry();return}catch{}try{existsSync$1(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync$1(s,JSON.stringify(r,null,2),{mode:384}),this.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-Q)))unlinkSync$1(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},bt).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(t,e){V(t,e,{endpoint:this.apiUrl,fallbackReason:"telemetry_already_committed_locally"});}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=_e?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,_e)}...`}}};function we(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function Re(n){return `hook-run:${n}`}function It(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}async function Se(n){let t=!n.memory,e=n.memory??new MemoryGate(n.projectRoot),i=0,o=0;try{await e.forceWarmUp(),n.trigger==="session_end"&&(i=await e.releasePendingDistillLeases(n.sessionId)),o=e.getPendingEventCount(n.sessionId,n.trigger!=="session_end");}finally{t&&e.close();}let r=Date.now(),s=n.trigger==="session_end"&&n.sessionId?`distill:session_end:${createHash("sha256").update(`${n.projectRoot}\0${n.sessionId}`).digest("hex").slice(0,24)}`:`distill:${r}:${Math.random().toString(36).slice(2,10)}`,a={id:s,pendingEvents:o,releasedLeases:i,trigger:n.trigger,sessionId:n.sessionId,details:n.details};try{let d=openGlobalDevFlowDatabase();try{d.recordMemoryDistillCheckpoint({id:s,projectRoot:n.projectRoot,sessionId:n.sessionId,trigger:n.trigger,pendingEvents:o,releasedLeases:i,details:n.details,createdAt:r}),d.insertEvent({kind:"memory_distill_requested",timestamp:r,success:!0,metadata:{...a,projectRoot:n.projectRoot}});}finally{d.close();}}catch(d){throw d}return a}function Ae(n){return Buffer.from(n,"utf8").toString("base64url")}function xt(n,t,e){let i=t?.trim();if(i){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(i)?i:`tool-${createHash$1("sha256").update(i.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${o}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function qe(n){return `${n}:legacy-journal`}var G=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(B(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let i=this.get(e);if(i)return i.lastActivityAt=Date.now(),this.persist(i),i;let o=Date.now(),r={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:o,lastActivityAt:o};return this.sessions.set(e,r),this.persist(r),r}startExecution(t,e,i){let o=this.registerSession(t);return (!o.executionId||o.skillName!==e)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=e,o.requiredMcpTools=[...new Set(i)],delete o.contextInitialization,o.lastActivityAt=Date.now(),this.persist(o),o}beginContextInitialization(t,e){let i=this.registerSession(t);return i.contextInitialization={startedAt:Date.now(),...e?{toolUseId:e}:{}},i.lastActivityAt=Date.now(),this.persist(i),i}completeContextInitialization(t,e){let i=this.get(t);return i?(e&&i.contextInitialization?.toolUseId&&i.contextInitialization.toolUseId!==e||(delete i.contextInitialization,i.lastActivityAt=Date.now(),this.persist(i)),i):null}bindTaskIdentity(t,e){let i=this.registerSession(t);return i.activeTurnId=e.turnId,i.activeRequestId=e.requestId,i.intentArtifactHash=e.intentArtifactHash,i.lastActivityAt=Date.now(),this.persist(i),i}get(t){let e=t.trim();if(!e)return null;let i=this.sessions.get(e);if(i)return this.replayEvidenceJournal(i),i;let o=this.snapshotPath(e);if(!existsSync$1(o))return null;try{let r=JSON.parse(readFileSync(o,"utf8"));return r.sessionId!==e||r.projectRoot!==this.projectRoot?null:(r.requiredMcpTools=Array.isArray(r.requiredMcpTools)?r.requiredMcpTools:[],r.evidenceObligations=Te(r.evidenceObligations),r.evidenceDegradations=De(r.evidenceDegradations),r.evidenceOutcomes=Ce(r.evidenceOutcomes),this.replayEvidenceJournal(r),this.sessions.set(e,r),r)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let i=structuredClone(e);return delete e.executionId,delete e.skillName,delete e.contextInitialization,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),i}addEvidenceObligation(t,e,i=Date.now(),o){let r=this.registerSession(t),a=(o?void 0:r.evidenceObligations.find(u=>u.contractId===e.id))?.obligationId??xt(e.id,o,i);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:i,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let d=r.evidenceObligations.find(u=>u.obligationId===a);return d?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(d)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,i,o,r=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(g=>g.obligationId===e);if(!s||!a)return null;let d=/^[a-f0-9]{64}$/.test(o)?o:"";if(!d)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:d,violations:i.slice(0,16).map(g=>g.slice(0,240))},`correction\0${e}\0${d}`),this.replayEvidenceJournal(s),s.lastActivityAt=r,this.persist(s);let u=s.evidenceObligations.find(g=>g.obligationId===e);return u?structuredClone(u):null}resolveEvidenceObligation(t,e){let i=this.get(t);if(!i)return false;let o=i.evidenceObligations.find(s=>s.obligationId===e);if(!o)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve\0${e}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}resolveDegradedEvidence(t,e){let i=this.get(t),o=i?.evidenceDegradations.find(s=>s.obligationId===e);if(!i||!o)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:o.contractId,at:r},`resolve-degraded\0${e}\0${r}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}degradeEvidenceObligation(t,e,i,o=Date.now()){let r=this.get(t),s=r?.evidenceObligations.find(d=>d.obligationId===e);if(!r||!s)return false;let a=i.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:o,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(r),r.lastActivityAt=o,this.persist(r),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync$1(this.snapshotPath(e),{force:true}),rmSync$1(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${Ae(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Ae(t))}appendEvidenceEvent(t,e,i){let o=this.evidenceJournalDir(t);mkdirSync$1(o,{recursive:true,mode:448});let r=createHash$1("sha256").update(i).digest("hex"),s=join$1(o,`${e.kind}-${r}.json`);if(existsSync$1(s))return;let a=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(d){if(d.code!=="EEXIST")throw d}finally{rmSync$1(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Te(t.evidenceObligations),t.evidenceDegradations=De(t.evidenceDegradations),t.evidenceOutcomes=Ce(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync$1(e))return;let i;try{i=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let o=i.flatMap(r=>{try{let s=readFileSync(join$1(e,r),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=At(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((r,s)=>r.at-s.at||Oe(r.kind)-Oe(s.kind));for(let r of o)this.applyEvidenceEvent(t,r);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let i=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(i)return;let s=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let o=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!o||i||o.correctionFingerprint===e.fingerprint)return;o.attempt+=1,o.correctionRequested=true,o.correctionRequestedAt=e.at,o.correctionFingerprint=e.fingerprint,o.violations=e.violations;return}let r=o?.attempt??i?.attempt??0;if(e.kind==="resolve"&&i?.status==="degraded")t.evidenceOutcomes=t.evidenceOutcomes.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations=t.evidenceDegradations.filter(s=>s.obligationId!==e.obligationId);else if(i)return;e.kind==="degrade"?(t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r,contract:o?.contract})):t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}});}persist(t){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),i=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(i,JSON.stringify(t),{mode:384}),renameSync$1(i,e);}};function Te(n){return Array.isArray(n)?n.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!Pe(e.contract))return [];let i=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:qe(e.contractId),o=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,r=e.correctionFingerprint??o;return r!==void 0&&!/^[a-f0-9]{64}$/.test(r)?[]:[{...e,obligationId:i,correctionFingerprint:r}]}).slice(-8):[]}function De(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function Ce(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(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 At(n){if(!n||typeof n!="object")return null;let t=n,e=t.kind;if(e!=="add"&&e!=="correction"&&e!=="resolve"&&e!=="degrade"||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let o={obligationId:typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:qe(t.contractId),contractId:t.contractId,at:t.at};if(e==="add")return Pe(t.contract)?{kind:e,...o,contract:t.contract}:null;if(e==="correction"){let r=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)&&Array.isArray(t.violations)&&t.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:e,...o,fingerprint:r,violations:t.violations}:null}return e==="resolve"?{kind:e,...o}:typeof t.reason=="string"&&t.reason.length<=240?{kind:e,...o,reason:t.reason}:null}function Oe(n){return n==="add"?0:n==="correction"?1:2}function Pe(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,i=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(i)&&i.length<=16&&i.every(o=>typeof o=="string"&&o.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function Me(n,t){let e=$t(n);mkdirSync(e,{recursive:true,mode:448});let i=join(e,`${t.receiptId}.json`);if(existsSync(i))return t.receiptId;let o=`${i}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384});try{renameSync(o,i);}catch(r){try{unlinkSync(o);}catch{}if(!existsSync(i))throw r}return t.receiptId}function $t(n){return join(B(n),"session-finalize-pending")}var w=emitSemanticControlLog;var zt=512*1024,Ht=500;var Ut=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function Bt(n){let t=false,e=[],i=[];for(let o of n){if(/^\s*```/.test(o)){t=!t,e.push(""),i.push(o.replace(/^\s*```+[^\s`]*/,"").replace(/```+\s*$/,"").trim());continue}e.push(t?"":o.replace(/`[^`]*`/g,"").trim()),i.push(o.replace(/`([^`]*)`/g,(r,s)=>Jt(s)?"":s).trim());}return {headingLines:e,claimLines:i}}function Jt(n){let t=n.trim().slice(0,256);return !t||/\s/.test(t)||n.trim().length>256?false:/^[A-Za-z_$][\w$.-]*$/.test(t)||/^(['"])[^'"`]*\1$/.test(t)}function Wt(n,t){if(!n||n.length>4096)return {degradationReason:"transcript_path_missing"};let e;try{let i=lstatSync(n);if(!i.isFile()||i.isSymbolicLink())return {degradationReason:"transcript_path_unsafe"};e=openSync(n,constants.O_RDONLY|(constants.O_NOFOLLOW??0));let o=fstatSync(e);if(!o.isFile()||o.dev!==i.dev||o.ino!==i.ino)return {degradationReason:"transcript_path_changed"};let r=Math.min(o.size,zt),s=Buffer.alloc(r),a=0;for(;a<r;){let b=readSync(e,s,a,r-a,o.size-r+a);if(b===0)break;a+=b;}let d=s.subarray(0,a).toString("utf8");o.size>r&&(d=d.slice(Math.max(0,d.indexOf(`
|
|
3
|
+
`)+1)));let u=d.split(/\r?\n/).slice(-Ht),g=t.length>0?Math.min(...t.map(b=>b.promptedAt)):0,c=Gt(u,g),v=[...c].reverse().find(b=>Vt(b.text,t))??c.at(-1);return v?.text?{answer:v.text,fingerprint:v.fingerprint}:{degradationReason:"transcript_answer_unavailable"}}catch{return {degradationReason:"transcript_unreadable"}}finally{e!==void 0&&closeSync(e);}}function Vt(n,t){let e=new Set(t.flatMap(o=>o.contract.requiredSections)),i=Yt(Bt(n.split(/\r?\n/u)).headingLines);return [...e].every(o=>i.found.has(o))}function Ne(n){return Wt(n,[]).answer}function Gt(n,t){let e=[];for(let i=0;i<n.length;i++){let o=n[i];if(o.trim())try{let r=JSON.parse(o),s=r.message;if(!s||typeof s!="object"||s.role!=="assistant")continue;let a=s,d=Kt(r.timestamp);if(d>0&&d+5e3<t)continue;let u=s.content,g=typeof u=="string"?u:Array.isArray(u)?u.filter(c=>c&&typeof c=="object"&&c.type==="text").map(c=>c.text).filter(c=>typeof c=="string").join(`
|
|
4
|
+
`):"";if(g.trim()){let c=g.trim(),y=typeof a.id=="string"&&a.id?`message:${a.id}`:typeof r.uuid=="string"&&r.uuid?`uuid:${r.uuid}`:`record:${String(r.timestamp??"")}:${i}:${createHash("sha256").update(o).digest("hex")}`,v=createHash("sha256").update(c).digest("hex"),b=createHash("sha256").update(`${y}\0${v}`).digest("hex");e.push({text:c,timestamp:d,fingerprint:b});}}catch{continue}}return e}function Kt(n){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n!="string")return 0;let t=Date.parse(n);return Number.isFinite(t)?t:0}function Yt(n){let t=new Set,e=new Map,i;for(let o=0;o<n.length;o++){let r=n[o].trim().replace(/^#{1,6}\s*/,"").replace(/^\*\*(.*)\*\*$/,"$1").replace(/^(?:[一二三123][、..]\s*)/,"").replace(/[::]\s*$/,"").trim(),s=Ut.find(a=>r===a);s&&(i=s,t.add(s)),e.set(o,i);}return {found:t,byLine:e}}function Ue(n){let t=openGlobalDevFlowDatabase();try{let e=t.listRetrievalLedgerEvents(n),i=new Map(e.filter(c=>c.stage==="selected").map(c=>[He(c),c])),o=new Map(e.filter(c=>c.stage==="consumed").map(c=>[He(c),c])),r=0,s=0,a=0;for(let[c,y]of i){let v=o.get(c);v&&n.verificationReceipt&&t.appendRetrievalLedgerEvent({...v,id:retrievalLedgerTransitionId(v.id,"verified",n.verificationReceipt),stage:"verified",verificationReceipt:n.verificationReceipt,reasonCode:"same_task_verification_receipt",createdAt:n.finishedAt??Date.now()});let b=v&&n.verificationReceipt&&n.outcome!=="unknown"?n.outcome:"unknown",I=b==="positive"?"positive_outcome":b==="negative"?"negative_outcome":"unknown_outcome";t.appendRetrievalLedgerEvent({...y,id:retrievalLedgerTransitionId(y.id,I,n.verificationReceipt??n.sessionId),stage:I,reason:v?n.outcomeReason:"selected_not_consumed",toolEvidence:v?.toolEvidence??[],verificationReceipt:b==="unknown"?void 0:n.verificationReceipt,payload:{...y.payload,consumed:!!v},createdAt:n.finishedAt??Date.now()}),I==="positive_outcome"?r+=1:I==="negative_outcome"?s+=1:a+=1;}let d=n.requiredChannels.map(c=>{let y=[...i.values()].filter(b=>b.sourceType===c).length,v=[...o.values()].filter(b=>b.sourceType===c).length;return {channel:c,selected:y,consumed:v,verified:n.verificationReceipt?v:0}}),u={status:d.length>0&&d.every(c=>c.selected>0&&c.consumed===c.selected&&c.verified===c.selected)?"complete":"unavailable",channels:d},g={consumed:o.size,positive:r,negative:s,unknown:a,consumedSources:[...o.values()].map(c=>({sourceType:c.sourceType,sourceId:c.sourceId})),proof:u};return n.verificationReceipt&&o.size>0&&ue({event:"retrieval.attribution.transitioned",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:n.executionId,requestId:n.requestId},level:"info",timestamp:n.finishedAt??Date.now(),data:{stage:"verified",verifiedCount:o.size}}),ue({event:"task.proof.completed",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:n.executionId,requestId:n.requestId},level:u.status==="complete"?"info":"warn",timestamp:n.finishedAt??Date.now(),data:u}),ue({event:"retrieval.attribution.transitioned",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:n.executionId,requestId:n.requestId},level:a>0?"warn":"info",timestamp:n.finishedAt??Date.now(),data:{stage:"session_outcome",selectedCount:i.size,consumedCount:o.size,verifiedCount:n.verificationReceipt?o.size:0,positiveCount:r,negativeCount:s,unknownCount:a}}),g}finally{t.close();}}function He(n){return [n.requestId,n.contextReceipt,n.sourceType,n.sourceId].join("\0")}function ue(n){try{w(n);}catch{}}var sn=8*1024*1024;function We(n){if(!n.transcriptPath||!existsSync(n.transcriptPath))return {status:"unavailable",eventsRead:0,failuresFound:0,failuresRecorded:0,reason:"transcript_path_unavailable"};let t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=t.getLatestTranscriptCheckpoint({projectRoot:n.projectRoot,hostId:"claude-code",sessionId:n.sessionId,sourcePath:n.transcriptPath}),i=statSync(n.transcriptPath).size,o=Math.min(e?.byteOffset??0,i),r=Math.min(sn,i-o);if(r<=0)return {status:"completed",eventsRead:0,failuresFound:0,failuresRecorded:0,checkpointId:e?.id};let s=Buffer.alloc(r),a=openSync(n.transcriptPath,"r");try{readSync(a,s,0,r,o);}finally{closeSync(a);}let d=s.toString("utf8").split(/\r?\n/u).filter(Boolean),u=t.listLatestTaskIntentArtifacts(n.projectRoot,n.sessionId),g=new Map,c=new Set,y=0,v=0;for(let _ of d){let R;try{R=JSON.parse(_);}catch{continue}for(let P of fe(R,g)){let h=claudeCodeRuntimeAdapter.normalizeToolResult(P,{projectRoot:n.projectRoot});if(h.success||!h.error)continue;let j=h.toolUseId??h.sourceHash;if(c.has(j))continue;c.add(j),y++;let k=h.toolUseId?t.getToolCallEventByToolUseId(n.sessionId,h.toolUseId):null,E=Je(k?.input,"_devflow_turn_id"),T=Je(k?.input,"_devflow_request_id"),F=E?u.find(C=>C.turnId===E):[...u].reverse().find(C=>(!k?.executionId||C.executionId===k.executionId)&&C.createdAt<=(k?.timestamp??h.timestamp))??u.at(-1),D=`host-failure:${h.sourceHash}`;t.insertEvent({kind:"host_transcript_tool_failure",timestamp:h.timestamp,success:!1,toolName:h.canonicalName??h.requestedName,metadata:{projectRoot:n.projectRoot,sessionId:n.sessionId,turnId:E??F?.turnId,requestId:T??F?.requestId,sourceId:D,toolUseId:h.toolUseId,correlatedEventId:k?.eventId,requestedName:h.requestedName,canonicalName:h.canonicalName,failureCategory:h.failureCategory,error:h.error.slice(0,1e3)}}),w({event:"host.tool.result.reconciled",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,turnId:E??F?.turnId,requestId:T??F?.requestId,executionId:k?.executionId},level:"warn",timestamp:Date.now(),data:{toolUseId:h.toolUseId,toolName:h.canonicalName??h.requestedName,failureCategory:h.failureCategory,correlation:k?"tool_use_id":"timestamp_fallback"}}),v++;}}let b=createHash("sha256").update(s).digest("hex"),I=`transcript:${createHash("sha256").update(`${n.projectRoot}\0${n.sessionId}\0${n.transcriptPath}\0${o+r}\0${b}`).digest("hex").slice(0,24)}`;return t.appendTranscriptCheckpoint({id:I,projectRoot:n.projectRoot,hostId:"claude-code",sessionId:n.sessionId,sourcePath:n.transcriptPath,sourceHash:b,byteOffset:o+r,eventCount:d.length,createdAt:Date.now()}),w({event:"session.reconciled",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId},level:y>0?"warn":"info",timestamp:Date.now(),data:{stage:"transcript",eventsRead:d.length,failuresFound:y,failuresRecorded:v,checkpointId:I}}),{status:"completed",eventsRead:d.length,failuresFound:y,failuresRecorded:v,checkpointId:I}}catch(e){return {status:"degraded",eventsRead:0,failuresFound:0,failuresRecorded:0,reason:e instanceof Error?e.message:String(e)}}finally{t.close();}}function Je(n,t){let e=n?.[t];return typeof e=="string"&&e.trim()?e.trim():void 0}function fe(n,t,e=0){if(e>7||n===null||n===void 0)return [];if(Array.isArray(n))return n.flatMap(s=>fe(s,t,e+1));if(typeof n!="object")return [];let i=n,o=typeof i.type=="string"?i.type:"";o==="tool_use"&&typeof i.id=="string"&&typeof i.name=="string"&&t.set(i.id,i.name);let r=[];if(o==="tool_result"){let s=typeof i.tool_use_id=="string"?i.tool_use_id:void 0;r.push({tool_name:s?t.get(s)??"unknown":"unknown",tool_use_id:s,tool_response:i.content,is_error:i.is_error===true,...i.is_error===true?{error:me(i.content)||"host tool result failed"}:{},timestamp:i.timestamp});}else (i.tool_name||i.toolName)&&(i.tool_response!==void 0||i.output!==void 0||i.error!==void 0)&&r.push(i);for(let[s,a]of Object.entries(i))s==="content"&&o==="tool_result"||r.push(...fe(a,t,e+1));return r}function me(n){if(typeof n=="string")return n.slice(0,4e3);if(Array.isArray(n))return n.map(me).filter(Boolean).join(`
|
|
5
|
+
`).slice(0,4e3);if(!n||typeof n!="object")return "";let t=n;return [t.text,t.content,t.message].map(me).filter(Boolean).join(`
|
|
6
|
+
`).slice(0,4e3)}var dn={open:["intent_bound"],intent_bound:["context_ready","context_degraded"],context_ready:["action_required","action_not_required"],context_degraded:["action_required","action_not_required"],action_required:["action_satisfied","action_degraded","action_failed"],action_not_required:["memory_decided","memory_quarantined"],action_satisfied:["memory_decided","memory_quarantined"],action_degraded:["memory_decided","memory_quarantined"],action_failed:["action_satisfied","action_degraded"],memory_decided:["closed","closed_with_degradation","closed_with_retry_work"],memory_quarantined:["closed_with_degradation","closed_with_retry_work"],closed:[],closed_with_degradation:[],closed_with_retry_work:[]};function Ve(n){return ln(n)}function ln(n){let t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let e=gn(t,n.artifact);if(pn(e.toState))return e;let i=t.getContextReceiptForRequest(n.artifact.projectRoot,n.artifact.sessionId,n.artifact.requestId),o=t.getMemoryTurn(n.artifact.turnId),r=n.artifact.intent==="memory"||o?.source==="explicit_intent";if(!i&&!r)return e;let s=i?un(n.artifact,i):"context_ready";e.toState==="intent_bound"&&(e=x(t,e,n,s,r?"task_context_not_required":s==="context_ready"?"canonical_context_receipt_ready":"canonical_context_receipt_degraded"));let a=i?fn(n.artifact,i):"action_not_required";if((e.toState==="context_ready"||e.toState==="context_degraded")&&(a==="action_not_required"?e=x(t,e,n,"action_not_required","task_action_not_required"):e=x(t,e,n,"action_required","canonical_action_obligation_present")),e.toState==="action_required"){if(a==="action_required")return e;if(a==="action_failed")return x(t,e,n,"action_failed","canonical_action_attempt_failed");a==="action_degraded"?e=x(t,e,n,"action_degraded","canonical_action_unavailable_or_degraded"):a==="action_satisfied"&&(e=x(t,e,n,"action_satisfied","canonical_action_succeeded"));}if(e.toState==="action_failed")if(a==="action_satisfied")e=x(t,e,n,"action_satisfied","canonical_action_retry_succeeded");else if(a==="action_degraded")e=x(t,e,n,"action_degraded","canonical_action_retry_degraded");else return e;let d=s==="context_degraded"||a==="action_degraded";return ["action_not_required","action_satisfied","action_degraded"].includes(e.toState)&&(e=x(t,e,n,n.memoryStatus==="pending"?"memory_quarantined":"memory_decided",n.memoryStatus==="pending"?n.reason:`canonical_memory_${n.memoryStatus}`)),e.toState==="memory_decided"?x(t,e,n,d?"closed_with_degradation":"closed",n.reason):e.toState==="memory_quarantined"?x(t,e,n,n.retryOwned?"closed_with_retry_work":"closed_with_degradation",n.retryOwned?"durable_retry_owner_confirmed":"terminal_obligation_unowned"):e}finally{t.close();}}function un(n,t){return n.intent==="memory"||n.intent==="knowledge"||(t.selectedFiles?.length??0)>0?"context_ready":"context_degraded"}function fn(n,t){let e=t.canonicalAction,o=(e?(t.actionAttempts??[]).filter(r=>r.tool===e.tool):[]).at(-1);return t.actionSatisfiedAt||o?.status==="succeeded"?"action_satisfied":o&&["failed","timeout","unavailable"].includes(o.status)?"action_failed":t.actionDegradation||e?.status==="degraded"||e?.status==="unsupported"?"action_degraded":e?.required||mn(n)?"action_required":"action_not_required"}function mn(n){return ["create","modify","debug","test","format"].includes(n.action)||["feature","refactor","performance"].includes(n.intent)}function gn(n,t){let e=n.getLatestTerminalTransition(t.projectRoot,t.sessionId,t.turnId);if(!e)throw new Error(`TERMINAL_INTENT_STATE_MISSING:${t.turnId}`);return e}function x(n,t,e,i,o){if(!dn[t.toState]?.includes(i))throw new Error(`TERMINAL_PATH_UNAVAILABLE:${t.toState}->${i}`);let r=t.sequence+1,s=`terminal:${createHash("sha256").update(`${e.artifact.artifactHash}\0${r}\0${i}`).digest("hex").slice(0,24)}`,a=n.appendTerminalTransition({projectRoot:e.artifact.projectRoot,projectId:e.artifact.projectId,hostId:e.artifact.hostId,sessionId:e.artifact.sessionId,turnId:e.artifact.turnId,requestId:e.artifact.requestId,executionId:e.artifact.executionId,sequence:r,fromState:t.toState,toState:i,receiptId:s,sourceReceiptId:e.memoryReceiptId??t.receiptId,reason:o,payload:{memoryStatus:e.memoryStatus,retryOwned:e.retryOwned??false,sourceIntentHash:e.artifact.artifactHash},createdAt:Date.now()});return w({event:"terminal.state.transitioned",identity:{projectRoot:e.artifact.projectRoot,projectId:e.artifact.projectId,hostId:e.artifact.hostId,sessionId:e.artifact.sessionId,turnId:e.artifact.turnId,requestId:e.artifact.requestId,...e.artifact.executionId?{executionId:e.artifact.executionId}:{}},level:i==="closed"?"info":i.includes("degradation")||i.includes("retry")||i==="action_failed"?"warn":"info",timestamp:Date.now(),data:{fromState:t.toState,nextState:i,receiptId:s,reason:o}}),a}function pn(n){return n==="closed"||n==="closed_with_degradation"||n==="closed_with_retry_work"}function Ge(n,t){let e=join(n,".devflow","delivery-line","state.db");if(!existsSync(e)||!t.trim())return 0;let i;try{i=new DatabaseSync(e,{timeout:250});let o=i.prepare("SELECT id, payload FROM delivery_cases WHERE id = ? OR json_extract(payload, '$.sessionId') = ?").all(t,t),r=0,s=!!i.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'delivery_events'").get();for(let a of o){let d="incomplete";try{let u=JSON.parse(a.payload);d=u.evidence?.some(g=>g.metadata?.trust==="external-untrusted")?"untrusted":u.stage==="delivered"?"clean":"incomplete";}catch{}if(r+=Number(i.prepare("UPDATE delivery_tasks SET lease_owner = NULL, lease_expires_at = NULL WHERE case_id = ? AND lease_owner IS NOT NULL").run(a.id).changes),s){let u=`session.closed:${a.id}:${t}`;i.prepare("INSERT OR IGNORE INTO delivery_events (id,case_id,idempotency_key,actor,type,payload,created_at,processed_at) VALUES (?,?,?,?,?,?,?,NULL)").run(u,a.id,u,JSON.stringify({id:"devflow:session-end",kind:"system"}),"session.closed",JSON.stringify({sessionId:t,releasedLeases:r,outcome:d}),Date.now());}}return r}catch{return 0}finally{i?.close();}}function wn(n){let t={committed:0,skipped:0,pending:0},e=[];for(let i of n)t[i.status]+=1,i.receiptId&&e.push(i.receiptId);return {memoryReceiptIds:[...new Set(e)],missingMemoryDecisionCount:t.pending,memoryTurnOutcomes:t}}function A(n){return (n instanceof Error?n.message:String(n)).trim().slice(0,240)||"memory_lifecycle_unavailable"}var z=class extends Error{constructor(t,e){super(`session_finalize_${t}:${e}`),this.name="SessionFinalizationRetryableError",this.category=`session_finalize_${t}`;}};function K(n){let t;try{t=openGlobalDevFlowDatabase();let e=(n.executionId?t.getSkillExecution(n.executionId):null)??t.getLatestSkillExecutionForSession(n.sessionId),i={stage:n.stage,reason:n.reason,degradedAt:Date.now()};e&&t.mergeSkillExecutionMetadata(e.executionId,{...n.metadata,sessionFinalizationDegradations:[i]}),t.insertEvent({kind:"session_finalize_degraded",timestamp:i.degradedAt,success:!1,metadata:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:e?.executionId,...i}}),w({event:"hook.session_end.degraded",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId,executionId:e?.executionId},level:"warn",timestamp:i.degradedAt,data:{stage:n.stage,reason:n.reason}});}catch{}finally{t?.close();}}function Rn(n,t=Z(),e=true,i,o=true){let r;try{r=JSON.parse(n);}catch{return null}let s=r.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${t}\0${s}`).digest("hex").slice(0,24)}`,d={inputJson:n,sessionId:s,cleanupSharedState:e,executionId:i};try{Ge(t,s);}catch{}let u;try{u=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let g=u.requestSessionClosure({receiptId:a,projectRoot:t,sessionId:s,payload:d}),c=u.getWorkByIdempotencyKey(a),y={status:g.state==="closed"||g.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:c?.state??"pending",closureState:g.state,pendingWorkCount:g.pendingWorkCount,...c?.id?{workItemId:c.id}:{}};return w({event:"hook.session_end.completed",identity:{projectRoot:t,sessionId:s,executionId:i,terminalReceipt:a},level:y.status==="completed"?"info":"debug",timestamp:Date.now(),data:{stage:"enqueue",...y}}),y}catch(g){if(!o)throw g;return Me(t,{receiptId:a,...d}),w({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:s,executionId:i,terminalReceipt:a},level:"warn",timestamp:Date.now(),data:{stage:"enqueue",reason:A(g),fallback:"durable_spool"}}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{u?.close();}}async function gr(n,t=Z(),e=true,i){let o;try{o=JSON.parse(n);}catch{return}let r=o.session_id?.trim();if(!r)return;let s=new G(t),a=s.get(r),d=We({projectRoot:t,sessionId:r,transcriptPath:o.transcript_path}),u={evidenceDegradations:a?.evidenceDegradations??[],evidenceContractOutcomes:a?.evidenceOutcomes??[],pendingEvidenceContractIds:a?.evidenceObligations.map(I=>I.contractId)??[],transcriptReconciliation:d},g=i?.telemetry??new ee,c=!i?.telemetry,y=()=>{if(!e)return;try{let R=openGlobalDevFlowDatabase();try{R.deleteHookReceipt(t);}finally{R.close();}}catch{}let I=B(t),_=createHash("sha256").update(t).digest("hex").slice(0,12);for(let R of [`session-id-${_}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join(I,R),{force:true});},v=false,b;try{try{await g.flushAndAggregate();}catch{}let I=Date.now(),_=i?.executionId??a?.executionId,R;try{let f=openGlobalDevFlowDatabase();try{R=f.listSessionMemoryTurnsForReconciliation(t,r);for(let l of R){let p=`memory:${l.turnId}`,m=f.getSessionObligation(t,r,p);m?m.state==="open"&&l.status!=="pending"&&f.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:p,state:"satisfied",receiptId:l.receiptId,reason:l.reason,resolvedAt:l.decidedAt}):f.upsertSessionObligation({obligationId:p,projectRoot:t,sessionId:r,turnId:l.turnId,kind:"memory_decision",state:l.status==="pending"?"open":"satisfied",payload:{eventId:l.eventId,promptHash:l.promptHash},receiptId:l.receiptId,reason:l.reason,createdAt:l.createdAt,updatedAt:l.decidedAt??l.createdAt,resolvedAt:l.decidedAt});}}finally{f.close();}}catch(f){let l=A(f),p={...u,memoryEventReconciliation:{status:"degraded",stage:"turn_load",reason:l,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw K({projectRoot:t,sessionId:r,executionId:_,stage:"turn_load",reason:l,metadata:p}),new z("turn_load",l)}let P=wn(R),h=i?.memory??(b=new MemoryGate(t)),j={status:"completed"};try{j=typeof h.reconcileTurnObservationLineage=="function"?{status:"completed",...await h.reconcileTurnObservationLineage(R)}:{status:"unsupported_adapter",committed:0,skipped:0,quarantined:0,unlinked:0};}catch(f){let l=A(f);throw j={status:"degraded",reason:l},K({projectRoot:t,sessionId:r,executionId:_,stage:"memory_lineage",reason:l,metadata:{...P,...u,memoryLineageReconciliation:j}}),new z("memory_lineage",l)}let k={status:"unknown",selected:0,consumed:0,unknown:0,positive:0,negative:0};try{let f=Ne(o.transcript_path),l=openGlobalDevFlowDatabase(),p="unknown",m="no_terminal_host_action_evidence",ne,M,$,H=[],ie=[];try{let L=l.listHostActionsForSession(t,r,_),pe=L.filter(S=>S.state==="verified"),re=L.filter(S=>["failed","cancelled","degraded"].includes(S.state));re.length>0?(p="negative",m=`terminal_host_action_${re[0].state}`):pe.length>0&&(p="positive",m="host_action_verified");let Y=re[0]??pe.at(-1);if(ne=Y?.runId,M=Y?.contextReceipt,$=Y?.evidenceHash,ie=L.flatMap(S=>{let U=S.report.toolUseIds;return Array.isArray(U)?U.filter(W=>typeof W=="string"):[]}),!Y&&_){let S=l.getSkillExecution(_),U=S?.metadata&&typeof S.metadata=="object"&&Array.isArray(S.metadata.policyVerificationOutcomes)?S.metadata.policyVerificationOutcomes:[],W=U.find(N=>N.status==="failed"),oe=U.filter(N=>N.status==="passed");W?(p="negative",m="policy_verification_failed",$=typeof W.receiptId=="string"?W.receiptId:void 0):oe.length>0&&(p="positive",m="policy_verification_passed",$=typeof oe.at(-1)?.receiptId=="string"?String(oe.at(-1).receiptId):void 0),M=l.getActiveContextReceipt(t,r,_)?.contextHash,ie=U.map(N=>N.command).filter(N=>typeof N=="string");}M&&(H=l.getSemanticExecutionContextByHash(M)?.dispositions.filter(S=>S.requirement==="required").map(S=>S.channel)??[]);}finally{l.close();}let ge=Ue({projectRoot:t,sessionId:r,executionId:_,outcome:p,outcomeReason:m,verificationReceipt:$,requiredChannels:H,finishedAt:I}),Ye=await h.attributeRetrievalBenefits({sessionId:r,executionId:_,outcome:p,outcomeReason:m,workflowRunId:ne,contextReceipt:M,toolEvidence:ie,verificationReceipt:$,consumedSourceIds:ge.consumedSources.filter(L=>L.sourceType==="memory").map(L=>L.sourceId)});k={status:f?"evaluated":"unknown",...Ye,retrievalLedger:ge};}catch(f){k={...k,status:"degraded",reason:A(f)};}let E;try{E=await h.reconcileDecidedTurnEventWindows(r,R,I);}catch(f){let l=A(f),p={...P,...u,memoryEventReconciliation:{status:"degraded",stage:"event_reconciliation",reason:l,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw K({projectRoot:t,sessionId:r,executionId:_,stage:"event_reconciliation",reason:l,metadata:p}),new z("event_reconciliation",l)}let T;try{T=await Se({projectRoot:t,sessionId:r,trigger:"session_end",memory:h,details:{eventReconciliation:E},strictPersistence:!0});}catch(f){let l=A(f),p={...P,...u,memoryEventReconciliation:{status:"completed",...E,checkpointPending:null},memoryCheckpointDegradation:l};throw K({projectRoot:t,sessionId:r,executionId:_,stage:"checkpoint",reason:l,metadata:p}),new z("checkpoint",l)}let F={memoryLineageReconciliation:j,memoryBenefitAttribution:k,memoryEventReconciliation:{status:"completed",...E,checkpointPending:T.pendingEvents},memoryDistillCheckpoint:T};try{let f=openGlobalDevFlowDatabase();try{let l=`session-finalize:${r}:events`,p=Math.max(Number(T.pendingEvents??0),Number(E.remainingUndecided??0)),m=f.getSessionObligation(t,r,l);p>0?f.upsertSessionObligation({obligationId:l,projectRoot:t,sessionId:r,executionId:_,kind:"session_finalize",state:"open",payload:{pendingEvents:p,reconciliation:E,checkpointId:T.id},reason:"active_unprocessed_session_events",createdAt:m?.createdAt??I,updatedAt:I}):m?.state==="open"&&f.resolveSessionObligation({projectRoot:t,sessionId:r,obligationId:l,state:"satisfied",reason:"session_events_reconciled",resolvedAt:I});}finally{f.close();}}catch(f){w({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:_},level:"warn",timestamp:Date.now(),data:{stage:"obligation_persistence",reason:A(f)}});}try{await h.closeSession(r),b&&(b.close(),b=void 0);}catch(f){let l=A(f),p={...P,...u,...F,memorySessionCloseDegradation:l};throw K({projectRoot:t,sessionId:r,executionId:_,stage:"memory_close",reason:l,metadata:p}),new z("memory_close",l)}let D={...P,...u,...F},C=[];try{let f=openGlobalDevFlowDatabase();try{let l=new Map(f.listLatestTaskIntentArtifacts(t,r).map(p=>[p.turnId,p]));for(let p of R){let m=l.get(p.turnId);if(!m)continue;let M=[f.getWorkByIdempotencyKey(`memory-turn:capture_prompt:${p.turnId}`),f.getWorkByIdempotencyKey(`memory-turn:commit_explicit:${p.turnId}`)].filter(Boolean).some(H=>H.state==="pending"||H.state==="leased"||H.state==="failed"),$=Ve({artifact:m,memoryStatus:p.status,memoryReceiptId:p.receiptId,retryOwned:M,reason:p.status==="pending"?"session_end_memory_pending":"session_end_reconciled"});C.push({turnId:p.turnId,state:$.toState,receiptId:$.receiptId});}}finally{f.close();}}catch(f){C.push({state:"terminal_integrity_failure",reason:A(f)});}D.terminalOutcomes=C,v=!0;let O;try{O=openGlobalDevFlowDatabase();let f=_;if(f)try{O.reconcileSkillExecution(f,"completed",I,D);let m=O.getSkillExecution(f);await V("/api/telemetry/skill-execution/complete",{executionId:f,finishedAt:I,status:"completed",summary:{totalToolCalls:m?.totalToolCalls??0,mcpToolCalls:m?.mcpToolCalls??0,directToolCalls:m?.directToolCalls??0,subagentCount:m?.subagentCount??0,totalDuration:m?.totalDuration??0,mcpComplianceRate:m?.mcpComplianceRate??0,missedTools:m?.missedMcpTools??[],actualFailureCount:m?.failedToolCalls??0,fallbackCount:m?.fallbackCount??0,fallbackReasons:m?.fallbackReasons??[]},metadata:D},{fallbackReason:"skill_execution_already_reconciled_locally"});}catch{}let l=O.reconcileRunningSkillExecutionsForSession(r,I,{closureReason:"session_finalize",...D});for(let m of l)await V("/api/telemetry/skill-execution/complete",{executionId:m.executionId,finishedAt:m.finishedAt,status:m.status,summary:{totalToolCalls:m.totalToolCalls??0,mcpToolCalls:m.mcpToolCalls??0,directToolCalls:m.directToolCalls??0,subagentCount:m.subagentCount??0,totalDuration:m.totalDuration??0,mcpComplianceRate:m.mcpComplianceRate??0,missedTools:m.missedMcpTools??[],actualFailureCount:m.failedToolCalls??0,fallbackCount:m.fallbackCount??0,fallbackReasons:m.fallbackReasons??[]},metadata:D},{fallbackReason:"skill_execution_already_reconciled_locally"});let p=O.getLatestSkillExecutionForSession(r);p&&!l.some(m=>m.executionId===p.executionId)&&O.mergeSkillExecutionMetadata(p.executionId,D),O.deleteContextReceipt(t,r);}catch(f){w({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:_},level:"warn",timestamp:Date.now(),data:{stage:"lifecycle_telemetry",reason:A(f),fallback:"fail_open"}});}finally{O?.close();}try{await g.endSession(r),await g.flushAndAggregate();}catch(f){w({event:"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:_},level:"warn",timestamp:Date.now(),data:{stage:"telemetry_flush",reason:A(f),fallback:"local_state_authoritative"}});}}finally{if(b)try{b.close();}catch{}c&&g.close(),y(),v&&s.removeSession(r),w({event:v?"hook.session_end.completed":"hook.session_end.degraded",identity:{projectRoot:t,sessionId:r,executionId:i?.executionId??a?.executionId},level:v?"info":"warn",timestamp:Date.now(),data:{stage:"finalize",criticalStagesCompleted:v,transcriptStatus:d.status}});}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{let e=Rn(t.trim()||process.argv[2]||"");e&&n(JSON.stringify(e)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}export{wn as buildMemoryTurnOutcomeMetadata,Rn as enqueueSessionEndFinalization,gr as handleSessionEnd};
|