@devflow-tools/claude-code-plugin 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/.claude-plugin/plugin.json +1 -1
- package/dist/command-registry.json +7 -7
- 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/runtime-manifest.json +7 -7
- package/hooks/README.md +15 -0
- package/hooks/constitution.md +7 -16
- package/hooks/hooks.json +11 -6
- package/hooks/post-tool-use +7 -0
- package/hooks/post-tool-use-failure +7 -0
- package/hooks/pre-compact +7 -0
- package/hooks/pre-tool-use +17 -9
- package/hooks/runtime-node +11 -0
- package/hooks/session-end +7 -0
- package/hooks/session-start +28 -27
- package/hooks/stop +7 -0
- package/hooks/user-prompt-submit +7 -0
- package/package.json +14 -14
package/dist/hooks/stop.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {getLocalApiKey,getDevFlowStateRoot,projectClaudeToolName,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir,readRuntimeState}from'@devflow-tools/sdk';import {existsSync as existsSync$1,readFileSync as readFileSync$1,rmSync,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1}from'fs';import {join as join$1}from'path';import {randomUUID,createHash as createHash$1}from'crypto';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import'@devflow-tools/memory-engine';import {request}from'node:http';import {existsSync,mkdirSync,writeFileSync,renameSync,unlinkSync,readFileSync,openSync,constants,fstatSync,closeSync,appendFileSync,lstatSync,readSync}from'node:fs';import {join,resolve}from'node:path';import {emitSemanticControlLog,rotateDiagnosticLogFile,SemanticRuntimeEventProjector}from'@devflow-tools/telemetry';import {createHash}from'node:crypto';import {TaskKernel,TaskEventStore}from'@devflow-tools/task-runtime';import {DatabaseSync}from'node:sqlite';function _(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function w(n){return getProjectStateDir(_(n))}function U(n){return Buffer.from(n,"utf8").toString("base64url")}function Re(n,e,t){let o=e?.trim();if(o){let r=/^[a-zA-Z0-9:._-]{1,192}$/.test(o)?o:`tool-${createHash$1("sha256").update(o.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${r}`}return `${n}:legacy-${t}-${randomUUID().slice(0,8)}`}function V(n){return `${n}:legacy-journal`}var I=class{constructor(e){this.projectRoot=e;this.sessions=new Map;this.sessionsDir=join$1(w(e),"hook-sessions");}registerSession(e){let t=e.trim();if(!t)throw new Error("session_id_required");let o=this.get(t);if(o)return o.lastActivityAt=Date.now(),this.persist(o),o;let r=Date.now(),i={sessionId:t,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:r,lastActivityAt:r};return this.sessions.set(t,i),this.persist(i),i}startExecution(e,t,o){let r=this.registerSession(e);return (!r.executionId||r.skillName!==t)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=t,r.requiredMcpTools=[...new Set(o)],delete r.contextInitialization,r.lastActivityAt=Date.now(),this.persist(r),r}beginContextInitialization(e,t){let o=this.registerSession(e);return o.contextInitialization={startedAt:Date.now(),...t?{toolUseId:t}:{}},o.lastActivityAt=Date.now(),this.persist(o),o}completeContextInitialization(e,t){let o=this.get(e);return o?(t&&o.contextInitialization?.toolUseId&&o.contextInitialization.toolUseId!==t||(delete o.contextInitialization,o.lastActivityAt=Date.now(),this.persist(o)),o):null}bindTaskIdentity(e,t){let o=this.registerSession(e);return o.activeTurnId=t.turnId,o.activeRequestId=t.requestId,o.intentArtifactHash=t.intentArtifactHash,o.lastActivityAt=Date.now(),this.persist(o),o}get(e){let t=e.trim();if(!t)return null;let o=this.sessions.get(t);if(o)return this.replayEvidenceJournal(o),o;let r=this.snapshotPath(t);if(!existsSync$1(r))return null;try{let i=JSON.parse(readFileSync$1(r,"utf8"));return i.sessionId!==t||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],i.evidenceObligations=B(i.evidenceObligations),i.evidenceDegradations=J(i.evidenceDegradations),i.evidenceOutcomes=W(i.evidenceOutcomes),this.replayEvidenceJournal(i),this.sessions.set(t,i),i)}catch{return null}}completeExecution(e){let t=this.get(e);if(!t)return null;let o=structuredClone(t);return delete t.executionId,delete t.skillName,delete t.contextInitialization,t.requiredMcpTools=[],t.lastActivityAt=Date.now(),this.persist(t),o}addEvidenceObligation(e,t,o=Date.now(),r){let i=this.registerSession(e),a=(r?void 0:i.evidenceObligations.find(l=>l.contractId===t.id))?.obligationId??Re(t.id,r,o);this.appendEvidenceEvent(e,{kind:"add",obligationId:a,contractId:t.id,at:o,contract:t},`add\0${a}`),this.replayEvidenceJournal(i);let c=i.evidenceObligations.find(l=>l.obligationId===a);return c?(i.lastActivityAt=Date.now(),this.persist(i),structuredClone(c)):null}listEvidenceObligations(e){return (this.get(e)?.evidenceObligations??[]).map(t=>structuredClone(t))}markEvidenceCorrection(e,t,o,r,i=Date.now()){let s=this.get(e),a=s?.evidenceObligations.find(d=>d.obligationId===t);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(r)?r:"";if(!c)return null;this.appendEvidenceEvent(e,{kind:"correction",obligationId:t,contractId:a.contractId,at:i,fingerprint:c,violations:o.slice(0,16).map(d=>d.slice(0,240))},`correction\0${t}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=i,this.persist(s);let l=s.evidenceObligations.find(d=>d.obligationId===t);return l?structuredClone(l):null}resolveEvidenceObligation(e,t){let o=this.get(e);if(!o)return false;let r=o.evidenceObligations.find(s=>s.obligationId===t);if(!r)return false;let i=Date.now();return this.appendEvidenceEvent(e,{kind:"resolve",obligationId:t,contractId:r.contractId,at:i},`resolve\0${t}`),this.replayEvidenceJournal(o),o.lastActivityAt=i,this.persist(o),true}resolveDegradedEvidence(e,t){let o=this.get(e),r=o?.evidenceDegradations.find(s=>s.obligationId===t);if(!o||!r)return false;let i=Date.now();return this.appendEvidenceEvent(e,{kind:"resolve",obligationId:t,contractId:r.contractId,at:i},`resolve-degraded\0${t}\0${i}`),this.replayEvidenceJournal(o),o.lastActivityAt=i,this.persist(o),true}degradeEvidenceObligation(e,t,o,r=Date.now()){let i=this.get(e),s=i?.evidenceObligations.find(c=>c.obligationId===t);if(!i||!s)return false;let a=o.slice(0,240);return this.appendEvidenceEvent(e,{kind:"degrade",obligationId:t,contractId:s.contractId,at:r,reason:a},`degrade\0${t}\0${a}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}removeSession(e){let t=e.trim();t&&(this.sessions.delete(t),rmSync(this.snapshotPath(t),{force:true}),rmSync(this.evidenceJournalDir(t),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(e){return join$1(this.sessionsDir,`${U(e)}.json`)}evidenceJournalDir(e){return join$1(this.sessionsDir,"evidence-journal",U(e))}appendEvidenceEvent(e,t,o){let r=this.evidenceJournalDir(e);mkdirSync$1(r,{recursive:true,mode:448});let i=createHash$1("sha256").update(o).digest("hex"),s=join$1(r,`${t.kind}-${i}.json`);if(existsSync$1(s))return;let a=join$1(r,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(t),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(e){e.evidenceObligations=B(e.evidenceObligations),e.evidenceDegradations=J(e.evidenceDegradations),e.evidenceOutcomes=W(e.evidenceOutcomes);let t=this.evidenceJournalDir(e.sessionId);if(!existsSync$1(t))return;let o;try{o=readdirSync(t).filter(i=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(i)).slice(0,4096);}catch{return}let r=o.flatMap(i=>{try{let s=readFileSync$1(join$1(t,i),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=ke(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((i,s)=>i.at-s.at||G(i.kind)-G(s.kind));for(let i of r)this.applyEvidenceEvent(e,i);e.evidenceObligations=e.evidenceObligations.slice(-8),e.evidenceDegradations=e.evidenceDegradations.slice(-20),e.evidenceOutcomes=e.evidenceOutcomes.slice(-20);}applyEvidenceEvent(e,t){let o=e.evidenceOutcomes.find(s=>s.obligationId===t.obligationId);if(t.kind==="add"){if(o)return;let s=e.evidenceObligations.find(a=>a.obligationId===t.obligationId);s?(s.contract=t.contract,s.promptedAt=Math.min(s.promptedAt,t.at)):e.evidenceObligations.push({obligationId:t.obligationId,contractId:t.contractId,contract:t.contract,promptedAt:t.at,attempt:0,correctionRequested:false,violations:[]});return}let r=e.evidenceObligations.find(s=>s.obligationId===t.obligationId);if(t.kind==="correction"){if(!r||o||r.correctionFingerprint===t.fingerprint)return;r.attempt+=1,r.correctionRequested=true,r.correctionRequestedAt=t.at,r.correctionFingerprint=t.fingerprint,r.violations=t.violations;return}let i=r?.attempt??o?.attempt??0;if(t.kind==="resolve"&&o?.status==="degraded")e.evidenceOutcomes=e.evidenceOutcomes.filter(s=>s.obligationId!==t.obligationId),e.evidenceDegradations=e.evidenceDegradations.filter(s=>s.obligationId!==t.obligationId);else if(o)return;t.kind==="degrade"?(e.evidenceObligations=e.evidenceObligations.filter(s=>s.obligationId!==t.obligationId),e.evidenceDegradations.push({obligationId:t.obligationId,contractId:t.contractId,reason:t.reason,degradedAt:t.at,attempt:i,contract:r?.contract})):e.evidenceObligations=e.evidenceObligations.filter(s=>s.obligationId!==t.obligationId),e.evidenceOutcomes.push({obligationId:t.obligationId,contractId:t.contractId,status:t.kind==="resolve"?"resolved":"degraded",completedAt:t.at,attempt:i,...t.kind==="degrade"?{reason:t.reason}:{}});}persist(e){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let t=this.snapshotPath(e.sessionId),o=`${t}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(o,JSON.stringify(e),{mode:384}),renameSync$1(o,t);}};function B(n){return Array.isArray(n)?n.flatMap(e=>{if(!e||typeof e!="object")return [];let t=e;if(typeof t.contractId!="string"||t.contractId.length===0||t.contractId.length>128||typeof t.promptedAt!="number"||typeof t.attempt!="number"||typeof t.correctionRequested!="boolean"||!Array.isArray(t.violations)||!Y(t.contract))return [];let o=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:V(t.contractId),r=typeof t.correctionTranscriptHash=="string"?t.correctionTranscriptHash:void 0,i=t.correctionFingerprint??r;return i!==void 0&&!/^[a-f0-9]{64}$/.test(i)?[]:[{...t,obligationId:o,correctionFingerprint:i}]}).slice(-8):[]}function J(n){return Array.isArray(n)?n.filter(e=>{if(!e||typeof e!="object")return false;let t=e;return typeof t.obligationId=="string"&&typeof t.contractId=="string"&&typeof t.reason=="string"&&typeof t.degradedAt=="number"&&typeof t.attempt=="number"}).slice(-20):[]}function W(n){return Array.isArray(n)?n.filter(e=>{if(!e||typeof e!="object")return false;let t=e;return typeof t.obligationId=="string"&&typeof t.contractId=="string"&&(t.status==="resolved"||t.status==="degraded")&&typeof t.completedAt=="number"&&typeof t.attempt=="number"&&(t.reason===void 0||typeof t.reason=="string")}).slice(-20):[]}function ke(n){if(!n||typeof n!="object")return null;let e=n,t=e.kind;if(t!=="add"&&t!=="correction"&&t!=="resolve"&&t!=="degrade"||typeof e.contractId!="string"||e.contractId.length>128||typeof e.at!="number")return null;let r={obligationId:typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:V(e.contractId),contractId:e.contractId,at:e.at};if(t==="add")return Y(e.contract)?{kind:t,...r,contract:e.contract}:null;if(t==="correction"){let i=typeof e.fingerprint=="string"?e.fingerprint:e.transcriptHash;return typeof i=="string"&&/^[a-f0-9]{64}$/.test(i)&&Array.isArray(e.violations)&&e.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:t,...r,fingerprint:i,violations:e.violations}:null}return t==="resolve"?{kind:t,...r}:typeof e.reason=="string"&&e.reason.length<=240?{kind:t,...r,reason:e.reason}:null}function G(n){return n==="add"?0:n==="correction"?1:2}function Y(n){if(!n||typeof n!="object")return false;let e=n,t=e.requiredSections,o=e.prohibitedClaims;return e.version==="1.0"&&typeof e.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(e.id)&&typeof e.runtimeProfilingOccurred=="boolean"&&typeof e.samplingEvidenceOccurred=="boolean"&&Array.isArray(t)&&t.length===3&&t[0]==="\u5DE5\u5177\u53D1\u73B0"&&t[1]==="\u6A21\u578B\u5047\u8BBE"&&t[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(o)&&o.length<=16&&o.every(r=>typeof r=="string"&&r.length<=128)&&typeof e.canonicalReport=="string"&&Buffer.byteLength(e.canonicalReport,"utf8")<=48*1024&&!!e.correctionPolicy&&e.correctionPolicy.maxAttempts===1&&e.correctionPolicy.repeatedViolation==="fail_open"}function T(n,e,t){try{let o=openGlobalDevFlowDatabase();try{o.insertEvent({kind:n,timestamp:Date.now(),duration:t,success:e.success!==!1,metadata:e});}finally{o.close();}}catch{}}var Le=getLocalApiKey(),D=join(getDevFlowStateRoot(),"errors");async function k(n,e,t={}){let o=t.endpoint??process.env.DEVFLOW_SERVER_URL?.trim()??Ne();if(!o)return {delivered:false,suppressed:false,fallbackReason:"runtime_not_ready"};let r=t.timeout??1500,i=t.durableMirror??true,s=t.maxRetries??(i?0:2),a=t.circuitBreaker??true,c=acquireRuntimeHttpCircuit(o,n);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let l;for(let u=0;u<=s;u+=1)try{return await qe(o,n,e,r),a&®isterRuntimeHttpSuccess(o,n).transitioned&&T("http_circuit_transition",{endpoint:o,path:new URL(n,o).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(m){l=m instanceof Error?m:new Error(String(m)),u<s&&await He(Math.min(100*2**u,1e3));}if(!l)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return X(n,l),{delivered:false,suppressed:false,fallbackReason:l.message};let d=registerRuntimeHttpFailure(o,n,t.fallbackReason??(i?"local_durable_mirror":"http_delivery_failed"));return d.transitioned&&(X(n,l),T("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 Ne(){let n=readRuntimeState();return n?.status==="ready"&&n.dashboardAvailable?n.url:void 0}function qe(n,e,t,o){return new Promise((r,i)=>{let s=JSON.stringify(t),a=new URL(e,n),c=false,l=u=>{c||(c=true,u?i(u):r());},d=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":Le,"Content-Length":Buffer.byteLength(s)},timeout:o},u=>{u.on("error",l),u.on("end",()=>{let m=u.statusCode??0;l(m>=200&&m<300?void 0:new Error(`HTTP ${m}`));}),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 X(n,e){try{existsSync(D)||mkdirSync(D,{recursive:!0});let t=join(D,"http-errors.log"),o=`${new Date().toISOString()} | ${n} | ${e.message}
|
|
2
|
-
`;rotateDiagnosticLogFile({path:t,maxBytes:50*1024*1024,maxFiles:5,incomingBytes:Buffer.byteLength(
|
|
1
|
+
import {getLocalApiKey,getDevFlowStateRoot,projectClaudeToolName,acquireRuntimeHttpCircuit,registerRuntimeHttpSuccess,registerRuntimeHttpFailure,getProjectStateDir,readRuntimeState}from'@devflow-tools/sdk';import {existsSync as existsSync$1,readFileSync as readFileSync$1,rmSync,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1}from'fs';import {join as join$1}from'path';import {randomUUID,createHash as createHash$1}from'crypto';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import'@devflow-tools/memory-engine';import {request}from'node:http';import {existsSync,mkdirSync,writeFileSync,renameSync,unlinkSync,readFileSync,openSync,constants,fstatSync,closeSync,appendFileSync,lstatSync,readSync}from'node:fs';import {join,resolve}from'node:path';import {emitSemanticControlLog,rotateDiagnosticLogFile,SemanticRuntimeEventProjector}from'@devflow-tools/telemetry';import {createHash}from'node:crypto';import {TaskKernel,TaskEventStore}from'@devflow-tools/task-runtime';import {DatabaseSync}from'node:sqlite';function _(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function w(n){return getProjectStateDir(_(n))}function U(n){return Buffer.from(n,"utf8").toString("base64url")}function Re(n,e,t){let r=e?.trim();if(r){let o=/^[a-zA-Z0-9:._-]{1,192}$/.test(r)?r:`tool-${createHash$1("sha256").update(r.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${o}`}return `${n}:legacy-${t}-${randomUUID().slice(0,8)}`}function V(n){return `${n}:legacy-journal`}var I=class{constructor(e){this.projectRoot=e;this.sessions=new Map;this.sessionsDir=join$1(w(e),"hook-sessions");}registerSession(e){let t=e.trim();if(!t)throw new Error("session_id_required");let r=this.get(t);if(r)return r.lastActivityAt=Date.now(),this.persist(r),r;let o=Date.now(),i={sessionId:t,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:o,lastActivityAt:o};return this.sessions.set(t,i),this.persist(i),i}startExecution(e,t,r){let o=this.registerSession(e);return (!o.executionId||o.skillName!==t)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=t,o.requiredMcpTools=[...new Set(r)],delete o.contextInitialization,o.lastActivityAt=Date.now(),this.persist(o),o}beginContextInitialization(e,t){let r=this.registerSession(e);return r.contextInitialization={startedAt:Date.now(),...t?{toolUseId:t}:{}},r.lastActivityAt=Date.now(),this.persist(r),r}completeContextInitialization(e,t){let r=this.get(e);return r?(t&&r.contextInitialization?.toolUseId&&r.contextInitialization.toolUseId!==t||(delete r.contextInitialization,r.lastActivityAt=Date.now(),this.persist(r)),r):null}bindTaskIdentity(e,t){let r=this.registerSession(e);return r.activeTurnId=t.turnId,r.activeRequestId=t.requestId,r.intentArtifactHash=t.intentArtifactHash,r.lastActivityAt=Date.now(),this.persist(r),r}get(e){let t=e.trim();if(!t)return null;let r=this.sessions.get(t);if(r)return this.replayEvidenceJournal(r),r;let o=this.snapshotPath(t);if(!existsSync$1(o))return null;try{let i=JSON.parse(readFileSync$1(o,"utf8"));return i.sessionId!==t||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],i.evidenceObligations=B(i.evidenceObligations),i.evidenceDegradations=J(i.evidenceDegradations),i.evidenceOutcomes=W(i.evidenceOutcomes),this.replayEvidenceJournal(i),this.sessions.set(t,i),i)}catch{return null}}completeExecution(e){let t=this.get(e);if(!t)return null;let r=structuredClone(t);return delete t.executionId,delete t.skillName,delete t.contextInitialization,t.requiredMcpTools=[],t.lastActivityAt=Date.now(),this.persist(t),r}addEvidenceObligation(e,t,r=Date.now(),o){let i=this.registerSession(e),a=(o?void 0:i.evidenceObligations.find(l=>l.contractId===t.id))?.obligationId??Re(t.id,o,r);this.appendEvidenceEvent(e,{kind:"add",obligationId:a,contractId:t.id,at:r,contract:t},`add\0${a}`),this.replayEvidenceJournal(i);let c=i.evidenceObligations.find(l=>l.obligationId===a);return c?(i.lastActivityAt=Date.now(),this.persist(i),structuredClone(c)):null}listEvidenceObligations(e){return (this.get(e)?.evidenceObligations??[]).map(t=>structuredClone(t))}markEvidenceCorrection(e,t,r,o,i=Date.now()){let s=this.get(e),a=s?.evidenceObligations.find(d=>d.obligationId===t);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(o)?o:"";if(!c)return null;this.appendEvidenceEvent(e,{kind:"correction",obligationId:t,contractId:a.contractId,at:i,fingerprint:c,violations:r.slice(0,16).map(d=>d.slice(0,240))},`correction\0${t}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=i,this.persist(s);let l=s.evidenceObligations.find(d=>d.obligationId===t);return l?structuredClone(l):null}resolveEvidenceObligation(e,t){let r=this.get(e);if(!r)return false;let o=r.evidenceObligations.find(s=>s.obligationId===t);if(!o)return false;let i=Date.now();return this.appendEvidenceEvent(e,{kind:"resolve",obligationId:t,contractId:o.contractId,at:i},`resolve\0${t}`),this.replayEvidenceJournal(r),r.lastActivityAt=i,this.persist(r),true}resolveDegradedEvidence(e,t){let r=this.get(e),o=r?.evidenceDegradations.find(s=>s.obligationId===t);if(!r||!o)return false;let i=Date.now();return this.appendEvidenceEvent(e,{kind:"resolve",obligationId:t,contractId:o.contractId,at:i},`resolve-degraded\0${t}\0${i}`),this.replayEvidenceJournal(r),r.lastActivityAt=i,this.persist(r),true}degradeEvidenceObligation(e,t,r,o=Date.now()){let i=this.get(e),s=i?.evidenceObligations.find(c=>c.obligationId===t);if(!i||!s)return false;let a=r.slice(0,240);return this.appendEvidenceEvent(e,{kind:"degrade",obligationId:t,contractId:s.contractId,at:o,reason:a},`degrade\0${t}\0${a}`),this.replayEvidenceJournal(i),i.lastActivityAt=o,this.persist(i),true}removeSession(e){let t=e.trim();t&&(this.sessions.delete(t),rmSync(this.snapshotPath(t),{force:true}),rmSync(this.evidenceJournalDir(t),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(e){return join$1(this.sessionsDir,`${U(e)}.json`)}evidenceJournalDir(e){return join$1(this.sessionsDir,"evidence-journal",U(e))}appendEvidenceEvent(e,t,r){let o=this.evidenceJournalDir(e);mkdirSync$1(o,{recursive:true,mode:448});let i=createHash$1("sha256").update(r).digest("hex"),s=join$1(o,`${t.kind}-${i}.json`);if(existsSync$1(s))return;let a=join$1(o,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(t),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(e){e.evidenceObligations=B(e.evidenceObligations),e.evidenceDegradations=J(e.evidenceDegradations),e.evidenceOutcomes=W(e.evidenceOutcomes);let t=this.evidenceJournalDir(e.sessionId);if(!existsSync$1(t))return;let r;try{r=readdirSync(t).filter(i=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(i)).slice(0,4096);}catch{return}let o=r.flatMap(i=>{try{let s=readFileSync$1(join$1(t,i),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=ke(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((i,s)=>i.at-s.at||G(i.kind)-G(s.kind));for(let i of o)this.applyEvidenceEvent(e,i);e.evidenceObligations=e.evidenceObligations.slice(-8),e.evidenceDegradations=e.evidenceDegradations.slice(-20),e.evidenceOutcomes=e.evidenceOutcomes.slice(-20);}applyEvidenceEvent(e,t){let r=e.evidenceOutcomes.find(s=>s.obligationId===t.obligationId);if(t.kind==="add"){if(r)return;let s=e.evidenceObligations.find(a=>a.obligationId===t.obligationId);s?(s.contract=t.contract,s.promptedAt=Math.min(s.promptedAt,t.at)):e.evidenceObligations.push({obligationId:t.obligationId,contractId:t.contractId,contract:t.contract,promptedAt:t.at,attempt:0,correctionRequested:false,violations:[]});return}let o=e.evidenceObligations.find(s=>s.obligationId===t.obligationId);if(t.kind==="correction"){if(!o||r||o.correctionFingerprint===t.fingerprint)return;o.attempt+=1,o.correctionRequested=true,o.correctionRequestedAt=t.at,o.correctionFingerprint=t.fingerprint,o.violations=t.violations;return}let i=o?.attempt??r?.attempt??0;if(t.kind==="resolve"&&r?.status==="degraded")e.evidenceOutcomes=e.evidenceOutcomes.filter(s=>s.obligationId!==t.obligationId),e.evidenceDegradations=e.evidenceDegradations.filter(s=>s.obligationId!==t.obligationId);else if(r)return;t.kind==="degrade"?(e.evidenceObligations=e.evidenceObligations.filter(s=>s.obligationId!==t.obligationId),e.evidenceDegradations.push({obligationId:t.obligationId,contractId:t.contractId,reason:t.reason,degradedAt:t.at,attempt:i,contract:o?.contract})):e.evidenceObligations=e.evidenceObligations.filter(s=>s.obligationId!==t.obligationId),e.evidenceOutcomes.push({obligationId:t.obligationId,contractId:t.contractId,status:t.kind==="resolve"?"resolved":"degraded",completedAt:t.at,attempt:i,...t.kind==="degrade"?{reason:t.reason}:{}});}persist(e){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let t=this.snapshotPath(e.sessionId),r=`${t}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(r,JSON.stringify(e),{mode:384}),renameSync$1(r,t);}};function B(n){return Array.isArray(n)?n.flatMap(e=>{if(!e||typeof e!="object")return [];let t=e;if(typeof t.contractId!="string"||t.contractId.length===0||t.contractId.length>128||typeof t.promptedAt!="number"||typeof t.attempt!="number"||typeof t.correctionRequested!="boolean"||!Array.isArray(t.violations)||!Y(t.contract))return [];let r=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:V(t.contractId),o=typeof t.correctionTranscriptHash=="string"?t.correctionTranscriptHash:void 0,i=t.correctionFingerprint??o;return i!==void 0&&!/^[a-f0-9]{64}$/.test(i)?[]:[{...t,obligationId:r,correctionFingerprint:i}]}).slice(-8):[]}function J(n){return Array.isArray(n)?n.filter(e=>{if(!e||typeof e!="object")return false;let t=e;return typeof t.obligationId=="string"&&typeof t.contractId=="string"&&typeof t.reason=="string"&&typeof t.degradedAt=="number"&&typeof t.attempt=="number"}).slice(-20):[]}function W(n){return Array.isArray(n)?n.filter(e=>{if(!e||typeof e!="object")return false;let t=e;return typeof t.obligationId=="string"&&typeof t.contractId=="string"&&(t.status==="resolved"||t.status==="degraded")&&typeof t.completedAt=="number"&&typeof t.attempt=="number"&&(t.reason===void 0||typeof t.reason=="string")}).slice(-20):[]}function ke(n){if(!n||typeof n!="object")return null;let e=n,t=e.kind;if(t!=="add"&&t!=="correction"&&t!=="resolve"&&t!=="degrade"||typeof e.contractId!="string"||e.contractId.length>128||typeof e.at!="number")return null;let o={obligationId:typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:V(e.contractId),contractId:e.contractId,at:e.at};if(t==="add")return Y(e.contract)?{kind:t,...o,contract:e.contract}:null;if(t==="correction"){let i=typeof e.fingerprint=="string"?e.fingerprint:e.transcriptHash;return typeof i=="string"&&/^[a-f0-9]{64}$/.test(i)&&Array.isArray(e.violations)&&e.violations.every(s=>typeof s=="string"&&s.length<=240)?{kind:t,...o,fingerprint:i,violations:e.violations}:null}return t==="resolve"?{kind:t,...o}:typeof e.reason=="string"&&e.reason.length<=240?{kind:t,...o,reason:e.reason}:null}function G(n){return n==="add"?0:n==="correction"?1:2}function Y(n){if(!n||typeof n!="object")return false;let e=n,t=e.requiredSections,r=e.prohibitedClaims;return e.version==="1.0"&&typeof e.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(e.id)&&typeof e.runtimeProfilingOccurred=="boolean"&&typeof e.samplingEvidenceOccurred=="boolean"&&Array.isArray(t)&&t.length===3&&t[0]==="\u5DE5\u5177\u53D1\u73B0"&&t[1]==="\u6A21\u578B\u5047\u8BBE"&&t[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(r)&&r.length<=16&&r.every(o=>typeof o=="string"&&o.length<=128)&&typeof e.canonicalReport=="string"&&Buffer.byteLength(e.canonicalReport,"utf8")<=48*1024&&!!e.correctionPolicy&&e.correctionPolicy.maxAttempts===1&&e.correctionPolicy.repeatedViolation==="fail_open"}function T(n,e,t){try{let r=openGlobalDevFlowDatabase();try{r.insertEvent({kind:n,timestamp:Date.now(),duration:t,success:e.success!==!1,metadata:e});}finally{r.close();}}catch{}}var Ne=getLocalApiKey(),D=join(getDevFlowStateRoot(),"errors");async function k(n,e,t={}){let r=t.endpoint??process.env.DEVFLOW_SERVER_URL?.trim()??Le();if(!r)return {delivered:false,suppressed:false,fallbackReason:"runtime_not_ready"};let o=t.timeout??1500,i=t.durableMirror??true,s=t.maxRetries??(i?0:2),a=t.circuitBreaker??true,c=acquireRuntimeHttpCircuit(r,n);if(a&&!c.allowed)return {delivered:false,suppressed:true,fallbackReason:c.state.fallbackReason};let l;for(let u=0;u<=s;u+=1)try{return await qe(r,n,e,o),a&®isterRuntimeHttpSuccess(r,n).transitioned&&T("http_circuit_transition",{endpoint:r,path:new URL(n,r).pathname,previous:c.state.status,status:"closed",failures:0}),{delivered:!0,suppressed:!1}}catch(m){l=m instanceof Error?m:new Error(String(m)),u<s&&await He(Math.min(100*2**u,1e3));}if(!l)return {delivered:false,suppressed:false,fallbackReason:"unknown_http_failure"};if(!a)return X(n,l),{delivered:false,suppressed:false,fallbackReason:l.message};let d=registerRuntimeHttpFailure(r,n,t.fallbackReason??(i?"local_durable_mirror":"http_delivery_failed"));return d.transitioned&&(X(n,l),T("http_circuit_transition",{endpoint:r,path:new URL(n,r).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 Le(){let n=readRuntimeState();return n?.status==="ready"&&n.dashboardAvailable?n.url:void 0}function qe(n,e,t,r){return new Promise((o,i)=>{let s=JSON.stringify(t),a=new URL(e,n),c=false,l=u=>{c||(c=true,u?i(u):o());},d=request({hostname:a.hostname,port:a.port,path:a.pathname+a.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":Ne,"Content-Length":Buffer.byteLength(s)},timeout:r},u=>{u.on("error",l),u.on("end",()=>{let m=u.statusCode??0;l(m>=200&&m<300?void 0:new Error(`HTTP ${m}`));}),u.resume();});d.on("error",l),d.on("timeout",()=>d.destroy(new Error(`HTTP mirror timed out after ${r}ms`))),d.write(s),d.end();})}function X(n,e){try{existsSync(D)||mkdirSync(D,{recursive:!0});let t=join(D,"http-errors.log"),r=`${new Date().toISOString()} | ${n} | ${e.message}
|
|
2
|
+
`;rotateDiagnosticLogFile({path:t,maxBytes:50*1024*1024,maxFiles:5,incomingBytes:Buffer.byteLength(r)}),appendFileSync(t,r);}catch{}}function He(n){return new Promise(e=>setTimeout(e,n))}function te(n,e){let t=We(n);mkdirSync(t,{recursive:true,mode:448});let r=join(t,`${e.receiptId}.json`);if(existsSync(r))return e.receiptId;let o=`${r}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(e),{mode:384});try{renameSync(o,r);}catch(i){try{unlinkSync(o);}catch{}if(!existsSync(r))throw i}return e.receiptId}function We(n){return join(w(n),"session-finalize-pending")}var p=emitSemanticControlLog;function M(n){let{projectRoot:e,...t}=n;try{return new O(e).dispatchBoundary(t).snapshot??null}catch(r){return p({event:"hook.runtime.degraded",identity:{projectRoot:e,sessionId:n.sessionId,...n.turnId?{turnId:n.turnId}:{},...n.requestId?{requestId:n.requestId}:{},...n.executionId?{executionId:n.executionId}:{}},level:"error",timestamp:Date.now(),data:{stage:n.kind,reason:r instanceof Error?r.message:String(r),tool:n.producer}}),null}}var O=class{constructor(e){this.projectRoot=e;}dispatchBoundary(e){let t=Ze(e.kind,e.payload??{});if(!t)return {handled:false};let r=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let o=Xe(r,{projectRoot:this.projectRoot,sessionId:e.sessionId,...e.turnId?{turnId:e.turnId}:{},...e.requestId?{requestId:e.requestId}:{},...e.executionId?{executionId:e.executionId}:{}});return o?{handled:!0,snapshot:new TaskKernel(new TaskEventStore(r),new SemanticRuntimeEventProjector).dispatch({definition:o.definition,kind:t.kind,payload:t.payload,idempotencyKey:`host:${o.definition.definitionHash}:${e.dedupeKey}`,producer:e.producer}).snapshot}:{handled:!1}}finally{r.close();}}};function Xe(n,e){let t=e.executionId?n.getActiveContextReceipt(e.projectRoot,e.sessionId,e.executionId):null,r=e.turnId??t?.canonicalAction?.binding.turnId,o=e.requestId??t?.requestId;if(!r&&!o)return null;let i=n.listLatestTaskIntentArtifacts(e.projectRoot,e.sessionId).find(c=>r?c.turnId===r:c.requestId===o);if(!i)return null;let s=n.getTaskAggregateSnapshot(e.projectRoot,e.sessionId,i.turnId,i.version);if(!s)return null;let a=n.getTaskDefinitionV2(s.taskDefinitionHash);return !a||a.revision!==i.version?null:{definition:a,snapshot:s}}function Ze(n,e){switch(n){case "action.lease.issued":return {kind:"action_lease_issued",payload:e};case "action.succeeded":return {kind:"action_completed",payload:e};case "action.failed":return {kind:"action_failed",payload:e};case "verification.succeeded":return {kind:"verification_completed",payload:e};case "verification.failed":return {kind:"verification_failed",payload:e};case "memory.committed":return {kind:"memory_episode_persisted",payload:e};case "memory.skipped":return {kind:"memory_decision_completed",payload:e};case "memory.pending":return {kind:"memory_extraction_queued",payload:e};case "memory.failed":return {kind:"memory_extraction_failed",payload:e};case "durable_work.owned":return {kind:"durable_work_leased",payload:{...e,fencingToken:Number.isSafeInteger(e.fencingToken)?e.fencingToken:0}};case "durable_work.completed":return {kind:"durable_work_completed",payload:e};case "durable_work.dead_lettered":return {kind:"durable_work_dead_lettered",payload:e};default:return null}}var ot=512*1024,it=500;var st=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function ie(n){let e=n.runtimeStore??new I(n.projectRoot),t=e.listEvidenceObligations(n.sessionId);if(t.length===0)return at(n,e),null;let r=$(n.transcriptPath,t);if(!r.answer){let s=r.degradationReason??"transcript_answer_unavailable";for(let a of t)e.degradeEvidenceObligation(n.sessionId,a.obligationId,s);return null}let o=r.fingerprint;if(!o){for(let s of t)e.degradeEvidenceObligation(n.sessionId,s.obligationId,"transcript_identity_unavailable");return null}let i=[];for(let s of t){let a=se(r.answer,[s]);if(a.length===0){e.resolveEvidenceObligation(n.sessionId,s.obligationId),x(n,s,"satisfied",o);continue}if(!s.correctionFingerprint){e.markEvidenceCorrection(n.sessionId,s.obligationId,a,o),i.push({obligation:s,violations:a}),x(n,s,"correction_requested",o,a);continue}if(s.correctionFingerprint===o){i.push({obligation:s,violations:a});continue}e.degradeEvidenceObligation(n.sessionId,s.obligationId,"evidence_contract_unresolved"),x(n,s,"degraded",o,a);}return i.length===0?null:ct(i)}function at(n,e){let t=(e.get(n.sessionId)?.evidenceDegradations??[]).filter(i=>i.contract).slice(-8);if(t.length===0)return;let r=t.map(i=>({obligationId:i.obligationId,contractId:i.contractId,contract:i.contract,promptedAt:i.degradedAt,attempt:i.attempt,correctionRequested:true,violations:[]})),o=$(n.transcriptPath,r);if(!(!o.answer||!o.fingerprint))for(let i of r)se(o.answer,[i]).length>0||e.resolveDegradedEvidence(n.sessionId,i.obligationId)&&x(n,i,"satisfied",o.fingerprint);}function x(n,e,t,r,o=[]){t!=="correction_requested"&&M({projectRoot:n.projectRoot,sessionId:n.sessionId,kind:t==="satisfied"?"verification.succeeded":"verification.failed",payload:{receiptId:e.obligationId,reasonCode:t==="satisfied"?"performance_evidence_satisfied":"performance_evidence_unresolved"},dedupeKey:`${e.obligationId}:${t}:${e.attempt}`,producer:"devflow-evidence-contract"}),p({event:"verification.completed",identity:{projectRoot:n.projectRoot,sessionId:n.sessionId},level:t==="satisfied"?"info":t==="degraded"?"error":"warn",timestamp:Date.now(),data:{stage:"performance_evidence_transition",status:t,contractId:e.contractId,obligationId:e.obligationId,attempt:e.attempt,answerFingerprint:r,violations:o,supersedesDegradation:t==="satisfied"&&e.attempt>0}});}function ct(n){let e=[...new Set(n.flatMap(r=>r.violations))],t=[...new Map(n.map(r=>[r.obligation.contractId,r.obligation.contract.canonicalReport])).values()];return {decision:"block",reason:["DevFlow evidence contract violation. Correct the final performance answer once before stopping.",`Violations: ${e.join("; ")}`,"Use this canonical report (you may add clearly labeled hypotheses or runtime verification steps, but no unsupported measured claims):",t.join(`
|
|
3
3
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
`)].join(`
|
|
7
7
|
|
|
8
|
-
`)}}function se(n,e){let t=new Set,
|
|
9
|
-
`)+1)));let l=c.split(/\r?\n/).slice(-it),d=e.length>0?Math.min(...e.map(g=>g.promptedAt)):0,u=ht(l,d),h=[...u].reverse().find(g=>yt(g.text,e))??u.at(-1);return h?.text?{answer:h.text,fingerprint:h.fingerprint}:{degradationReason:"transcript_answer_unavailable"}}catch{return {degradationReason:"transcript_unreadable"}}finally{t!==void 0&&closeSync(t);}}function yt(n,e){let t=new Set(e.flatMap(
|
|
10
|
-
`):"";if(d.trim()){let u=d.trim(),m=typeof a.id=="string"&&a.id?`message:${a.id}`:typeof i.uuid=="string"&&i.uuid?`uuid:${i.uuid}`:`record:${String(i.timestamp??"")}:${o}:${createHash("sha256").update(r).digest("hex")}`,h=createHash("sha256").update(u).digest("hex"),g=createHash("sha256").update(`${m}\0${h}`).digest("hex");t.push({text:u,timestamp:c,fingerprint:g});}}catch{continue}}return t}function It(n){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n!="string")return 0;let e=Date.parse(n);return Number.isFinite(e)?e:0}function ce(n){let e=new Set,t=new Map,o;for(let r=0;r<n.length;r++){let i=n[r].trim().replace(/^#{1,6}\s*/,"").replace(/^\*\*(.*)\*\*$/,"$1").replace(/^(?:[一二三123][、..]\s*)/,"").replace(/[::]\s*$/,"").trim(),s=st.find(a=>i===a);s&&(o=s,e.add(s)),t.set(r,o);}return {found:e,byLine:t}}var _t={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 F(n){return wt(n)}function wt(n){let e=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let t=xt(e,n.artifact);if(Et(t.toState))return t;let o=e.getContextReceiptForRequest(n.artifact.projectRoot,n.artifact.sessionId,n.artifact.requestId),r=e.getMemoryTurn(n.artifact.turnId),i=n.artifact.intent==="memory"||r?.source==="explicit_intent";if(!o&&!i)return t;let s=o?St(n.artifact,o):"context_ready";t.toState==="intent_bound"&&(t=f(e,t,n,s,i?"task_context_not_required":s==="context_ready"?"canonical_context_receipt_ready":"canonical_context_receipt_degraded"));let a=o?Rt(n.artifact,o):"action_not_required";if((t.toState==="context_ready"||t.toState==="context_degraded")&&(a==="action_not_required"?t=f(e,t,n,"action_not_required","task_action_not_required"):t=f(e,t,n,"action_required","canonical_action_obligation_present")),t.toState==="action_required"){if(a==="action_required")return t;if(a==="action_failed")return f(e,t,n,"action_failed","canonical_action_attempt_failed");a==="action_degraded"?t=f(e,t,n,"action_degraded","canonical_action_unavailable_or_degraded"):a==="action_satisfied"&&(t=f(e,t,n,"action_satisfied","canonical_action_succeeded"));}if(t.toState==="action_failed")if(a==="action_satisfied")t=f(e,t,n,"action_satisfied","canonical_action_retry_succeeded");else if(a==="action_degraded")t=f(e,t,n,"action_degraded","canonical_action_retry_degraded");else return t;let c=s==="context_degraded"||a==="action_degraded";return ["action_not_required","action_satisfied","action_degraded"].includes(t.toState)&&(t=f(e,t,n,n.memoryStatus==="pending"?"memory_quarantined":"memory_decided",n.memoryStatus==="pending"?n.reason:`canonical_memory_${n.memoryStatus}`)),t.toState==="memory_decided"?f(e,t,n,c?"closed_with_degradation":"closed",n.reason):t.toState==="memory_quarantined"?f(e,t,n,n.retryOwned?"closed_with_retry_work":"closed_with_degradation",n.retryOwned?"durable_retry_owner_confirmed":"terminal_obligation_unowned"):t}finally{e.close();}}function St(n,e){return n.intent==="memory"||n.intent==="knowledge"||(e.selectedFiles?.length??0)>0?"context_ready":"context_degraded"}function Rt(n,e){let t=e.canonicalAction,r=(t?(e.actionAttempts??[]).filter(i=>i.tool===t.tool):[]).at(-1);return e.actionSatisfiedAt||r?.status==="succeeded"?"action_satisfied":r&&["failed","timeout","unavailable"].includes(r.status)?"action_failed":e.actionDegradation||t?.status==="degraded"||t?.status==="unsupported"?"action_degraded":t?.required||kt(n)?"action_required":"action_not_required"}function kt(n){return ["create","modify","debug","test","format"].includes(n.action)||["feature","refactor","performance"].includes(n.intent)}function xt(n,e){let t=n.getLatestTerminalTransition(e.projectRoot,e.sessionId,e.turnId);if(!t)throw new Error(`TERMINAL_INTENT_STATE_MISSING:${e.turnId}`);return t}function f(n,e,t,o,r){if(!_t[e.toState]?.includes(o))throw new Error(`TERMINAL_PATH_UNAVAILABLE:${e.toState}->${o}`);let i=e.sequence+1,s=`terminal:${createHash("sha256").update(`${t.artifact.artifactHash}\0${i}\0${o}`).digest("hex").slice(0,24)}`,a=n.appendTerminalTransition({projectRoot:t.artifact.projectRoot,projectId:t.artifact.projectId,hostId:t.artifact.hostId,sessionId:t.artifact.sessionId,turnId:t.artifact.turnId,requestId:t.artifact.requestId,executionId:t.artifact.executionId,sequence:i,fromState:e.toState,toState:o,receiptId:s,sourceReceiptId:t.memoryReceiptId??e.receiptId,reason:r,payload:{memoryStatus:t.memoryStatus,retryOwned:t.retryOwned??false,sourceIntentHash:t.artifact.artifactHash},createdAt:Date.now()});return p({event:"terminal.state.transitioned",identity:{projectRoot:t.artifact.projectRoot,projectId:t.artifact.projectId,hostId:t.artifact.hostId,sessionId:t.artifact.sessionId,turnId:t.artifact.turnId,requestId:t.artifact.requestId,...t.artifact.executionId?{executionId:t.artifact.executionId}:{}},level:o==="closed"?"info":o.includes("degradation")||o.includes("retry")||o==="action_failed"?"warn":"info",timestamp:Date.now(),data:{fromState:e.toState,nextState:o,receiptId:s,reason:r}}),a}function Et(n){return n==="closed"||n==="closed_with_degradation"||n==="closed_with_retry_work"}function de(n,e){let t=join(n,".devflow","delivery-line","state.db");if(!existsSync(t)||!e.trim())return 0;let o;try{o=new DatabaseSync(t,{timeout:250});let r=o.prepare("SELECT id, payload FROM delivery_cases WHERE id = ? OR json_extract(payload, '$.sessionId') = ?").all(e,e),i=0,s=!!o.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'delivery_events'").get();for(let a of r){let c="incomplete";try{let l=JSON.parse(a.payload);c=l.evidence?.some(d=>d.metadata?.trust==="external-untrusted")?"untrusted":l.stage==="delivered"?"clean":"incomplete";}catch{}if(i+=Number(o.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 l=`session.closed:${a.id}:${e}`;o.prepare("INSERT OR IGNORE INTO delivery_events (id,case_id,idempotency_key,actor,type,payload,created_at,processed_at) VALUES (?,?,?,?,?,?,?,NULL)").run(l,a.id,l,JSON.stringify({id:"devflow:session-end",kind:"system"}),"session.closed",JSON.stringify({sessionId:e,releasedLeases:i,outcome:c}),Date.now());}}return i}catch{return 0}finally{o?.close();}}function le(n){let e={committed:0,skipped:0,pending:0},t=[];for(let o of n)e[o.status]+=1,o.receiptId&&t.push(o.receiptId);return {memoryReceiptIds:[...new Set(t)],missingMemoryDecisionCount:e.pending,memoryTurnOutcomes:e}}function Mt(n){return (n instanceof Error?n.message:String(n)).trim().slice(0,240)||"memory_lifecycle_unavailable"}function jt(n,e=_(),t=true,o,r=true){let i;try{i=JSON.parse(n);}catch{return null}let s=i.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${e}\0${s}`).digest("hex").slice(0,24)}`,c={inputJson:n,sessionId:s,cleanupSharedState:t,executionId:o};try{de(e,s);}catch{}let l;try{l=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let d=l.requestSessionClosure({receiptId:a,projectRoot:e,sessionId:s,payload:c}),u=l.getWorkByIdempotencyKey(a),m={status:d.state==="closed"||d.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:u?.state??"pending",closureState:d.state,pendingWorkCount:d.pendingWorkCount,...u?.id?{workItemId:u.id}:{}};return p({event:"hook.session_end.completed",identity:{projectRoot:e,sessionId:s,executionId:o,terminalReceipt:a},level:m.status==="completed"?"info":"debug",timestamp:Date.now(),data:{stage:"enqueue",...m}}),m}catch(d){if(!r)throw d;return te(e,{receiptId:a,...c}),p({event:"hook.session_end.degraded",identity:{projectRoot:e,sessionId:s,executionId:o,terminalReceipt:a},level:"warn",timestamp:Date.now(),data:{stage:"enqueue",reason:Mt(d),fallback:"durable_spool"}}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{l?.close();}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=jt(e.trim()||process.argv[2]||"");t&&n(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}var E=1,Ht="memory-snapshot-v1.json",zt=512*1024,fe=256*1024,ge=2e3,Ut=500,Bt=10,Jt=240,Wt=300*1e3,Gt=720*60*60*1e3,Kt=2147483647;function Vt(n){return n.currentUid===void 0?{ownerSafe:true,modeSafe:true}:{ownerSafe:n.ownerUid===n.currentUid,modeSafe:(n.mode&18)===0}}function b(n){return resolve(n)}function S(n){return createHash("sha256").update(b(n)).digest("hex").slice(0,16)}function Yt(n,e={}){let t=S(n),o=e.stateRoot?join(e.stateRoot,t):getProjectStateDir(b(n));return join(o,Ht)}function Xt(n,e){let o=(n instanceof Error?n.message:"").replace(/[\r\n\t]+/gu," ").trim().slice(0,160);return o?`${e}:${o}`:e}function N(n,e){return Array.isArray(n)&&n.length<=e&&n.every(t=>typeof t=="string"&&t.length>0&&t.length<=512)}function Zt(n){if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return typeof e.id=="string"&&e.id.length>0&&e.id.length<=512&&typeof e.kind=="string"&&e.kind.length>0&&e.kind.length<=128&&(e.family===void 0||typeof e.family=="string"&&e.family.length>0&&e.family.length<=256)&&(e.entity===void 0||typeof e.entity=="string"&&e.entity.length>0&&e.entity.length<=256)&&N(e.memoryIds,100)&&(e.status==="withheld"||e.status==="resolved")&&(e.summary===void 0||typeof e.summary=="string"&&e.summary.length<=2e3)}function Qt(n){if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return typeof e.reason=="string"&&e.reason.length>0&&e.reason.length<=512&&(e.stale===void 0||typeof e.stale=="boolean")}function ye(n,e,t){if(!n||typeof n!="object"||Array.isArray(n))return null;let o=n,r=b(e),i=S(r),s=o.generation===void 0?0:o.generation;return o.version!==E||o.projectRoot!==r||o.projectHash!==i||typeof o.markdown!="string"||Buffer.byteLength(o.markdown,"utf8")>fe||!N(o.memoryIds,ge)||!Array.isArray(o.conflicts)||o.conflicts.length>Ut||!o.conflicts.every(Zt)||typeof o.generatedAt!="number"||!Number.isFinite(o.generatedAt)||o.generatedAt<0||o.generatedAt>t+Wt||!Number.isInteger(s)||s<0||s>Kt||!["ready","pending","degraded","disabled"].includes(String(o.status))||o.degradation!==void 0&&!Qt(o.degradation)?null:{...o,generation:s}}function en(n,e,t,o,r=0){let i=b(n);return {version:E,projectRoot:i,projectHash:S(i),markdown:"",memoryIds:[],conflicts:[],generatedAt:o,generation:r,status:e,degradation:{reason:t}}}function tn(n,e={}){let t=e.now??Date.now(),o=Yt(n,e),r;try{r=openSync(o,constants.O_RDONLY|constants.O_NOFOLLOW);let i=fstatSync(r);if(!i.isFile()||i.size<=0||i.size>zt)throw new Error("cache_size_invalid");let s=Vt({...typeof process.getuid=="function"?{currentUid:process.getuid()}:{},ownerUid:i.uid,mode:i.mode});if(!s.ownerSafe)throw new Error("cache_owner_invalid");if(!s.modeSafe)throw new Error("cache_permissions_unsafe");let a=JSON.parse(readFileSync(r,"utf8")),c=ye(a,n,t);if(!c)throw new Error("cache_schema_invalid");return c.status==="ready"&&t-c.generatedAt>Gt?{snapshot:{...c,status:"degraded",degradation:{reason:"cache_stale",stale:!0}},source:"cache",valid:!0,stale:!0}:{snapshot:c,source:"cache",valid:!0,stale:!1}}catch(i){let a=i.code==="ENOENT";return {snapshot:en(n,a?"pending":"degraded",a?"cache_missing":Xt(i,"cache_invalid"),t),source:"none",valid:false,stale:false}}finally{if(r!==void 0)try{closeSync(r);}catch{}}}function nn(n){if(!n)return true;try{return JSON.parse(readFileSync(n,"utf8")).sessionStart?.injectMemories??!0}catch{return true}}function on(n,e,t){if(!e.trim())return null;try{let o=JSON.parse(e);if(o.status!=="ok"&&o.status!=="degraded")return null;if(o.enabled===!1){let i=b(n);return {version:E,projectRoot:i,projectHash:S(i),markdown:"",memoryIds:[],conflicts:[],generatedAt:t,generation:0,status:"disabled"}}let r=ye(o.snapshot,n,t);if(r)return r;if(o.status==="ok"&&typeof o.markdown=="string"&&o.markdown.length>0&&Buffer.byteLength(o.markdown,"utf8")<=fe){let i=b(n);return {version:E,projectRoot:i,projectHash:S(i),markdown:o.markdown,memoryIds:N(o.memoryIds,ge)?o.memoryIds:[],conflicts:[],generatedAt:t,generation:0,status:"ready"}}}catch{}return null}function L(n,e){return [...(n??e).replace(/[\r\n\t|]+/gu," ").trim()||e].slice(0,Jt).join("")}function rn(n){if(n.length===0)return "";let e=n.slice(0,Bt),t=e.map(o=>{let r=L(o.family,"unknown"),i=L(o.entity,"unknown"),s=L(o.summary,"Explicit choice required.");return `- family=${r}; entity=${i}; status=${o.status}; summary=${s}`});return n.length>e.length&&t.push(`- ${n.length-e.length} additional conflict(s) omitted from SessionStart output.`),`## Withheld preference conflicts (${n.length})
|
|
8
|
+
`)}}function se(n,e){let t=new Set,r=new Set(e.flatMap(c=>c.contract.requiredSections)),o=ae(n.split(/\r?\n/)),i=ce(o.headingLines);for(let c of r)i.found.has(c)||t.add(`missing_section:${c}`);if(e.every(c=>c.contract.runtimeProfilingOccurred))return [...t];let a=e.every(c=>c.contract.samplingEvidenceOccurred);for(let c=0;c<o.claimLines.length;c++){let l=o.claimLines[c].trim();if(!l||lt(l))continue;let d=i.byLine.get(c);for(let u of gt(l))mt(u,d,a,t);}return [...t]}function ae(n){let e=false,t=[],r=[];for(let o of n){if(/^\s*```/.test(o)){e=!e,t.push(""),r.push(o.replace(/^\s*```+[^\s`]*/,"").replace(/```+\s*$/,"").trim());continue}t.push(e?"":o.replace(/`[^`]*`/g,"").trim()),r.push(o.replace(/`([^`]*)`/g,(i,s)=>dt(s)?"":s).trim());}return {headingLines:t,claimLines:r}}function dt(n){let e=n.trim().slice(0,256);return !e||/\s/.test(e)||n.trim().length>256?false:/^[A-Za-z_$][\w$.-]*$/.test(e)||/^(['"])[^'"`]*\1$/.test(e)}function lt(n){if(n.length>2048)return false;let e=n.replace(/^\s*(?:[-*+]|\d+[.)])\s+/,"").trim();return e?ut(e)||/^(?:\/\/|\/\*|\*\/|\*\s|#!)/.test(e)||/^(?:import|export|const|let|var|function|class|type|interface|enum|namespace|declare)\b/.test(e)||/^(?:async\s+)?(?:function\s+)?[A-Za-z_$][\w$]*\s*=\s*/.test(e)||/^[A-Za-z_$][\w$.[\]'"-]*\s*(?:=|\+=|-=|\*=|\/=|\?\?=|&&=|\|\|=)\s*/.test(e)||/^[A-Za-z_$'"-][\w$.'"-]*\s*:\s*[^:]+[,}]?$/.test(e)||/=>/.test(e)||/^(?:await\s+|return\s+|throw\s+|new\s+)?[A-Za-z_$][\w$.]*\s*\([^)]*\)\s*;?$/.test(e)||/^(['"])[\s\S]*\1[;,]?$/.test(e)?true:/[{}()[\]=<>]\s*;?$/.test(e)&&/(?:;|=>|\b(?:return|new|await)\b)/.test(e):false}function ut(n){if(n.length>1024)return false;let e="(?:--[A-Za-z0-9_-]+|(?:-webkit-|-moz-|-ms-)?(?:animation(?:-[a-z-]+)?|transition(?:-[a-z-]+)?|opacity|transform|will-change|contain|content-visibility|display|position|top|right|bottom|left|width|height|min-(?:width|height)|max-(?:width|height)|margin(?:-[a-z]+)?|padding(?:-[a-z]+)?|color|background(?:-[a-z-]+)?|border(?:-[a-z-]+)?|font(?:-[a-z-]+)?|line-height|z-index|overflow(?:-[xy])?))";return new RegExp(`^${e}\\s*:\\s*\\S[^;]{0,960};$`,"i").test(n)}function mt(n,e,t,r){let o=/\bP0\b/gi;for(let y of n.matchAll(o))oe(n,y.index??0,y[0],"p0")||r.add("unsupported_p0_severity");let i=/(?:中高|高)(?:风险|优先级)|严重(?:问题|风险)|\bhigh[- ](?:risk|severity|priority)\b/gi;for(let y of n.matchAll(i))oe(n,y.index??0,y[0],"high")||r.add("unsupported_high_severity");let s=/(?:性能)?瓶颈|卡顿|掉帧|CPU\s*(?:热点|尖峰)|\bbottleneck\b|\bjank\b|\bdropped frames?\b|\bCPU hotspot\b/gi;for(let y of n.matchAll(s))ft(n,y.index??0,y[0])||(/(?:瓶颈|bottleneck)/i.test(y[0])?r.add("unsupported_confirmed_bottleneck"):r.add("unsupported_runtime_effect"));let a=/\b\d{1,3}(?:\.\d+)?\s*%/.test(n),c=/(?:预计|预期|估计|提升|降低|减少|节省|改善|收益|加速|improve|reduce|faster|gain|benefit|speedup|expected|estimated)/i.test(n),l=/\b\d+(?:\.\d+)?\s*[x×]\b/i.test(n);(a||l)&&c&&r.add(a?"unsupported_benefit_percentage":"unsupported_performance_number");let d=/\b\d+(?:\.\d+)?(?:\s*[-–~]\s*\d+(?:\.\d+)?)?\s*(?:ms|fps|hz)\b/i.test(n)||/\d+(?:\.\d+)?(?:\s*[-–~]\s*\d+(?:\.\d+)?)?\s*(?:毫秒|次\s*\/\s*秒|帧)/.test(n),u=e==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&/(?:采集|记录|测量|收集|collect|measure|record)/i.test(n)&&!/(?:预计|预期|估计|约|大约|通常|平均|每(?:隔)?|达到|提升|降低|减少|节省|改善|improve|reduce|faster|expected|estimated|average|typically|every)/i.test(n);a&&!c&&!u&&r.add("unsupported_benefit_percentage"),d&&!u&&r.add("unsupported_performance_number");let m=/(?:requestAnimationFrame|\bRAF\b)/i.test(n),h=/(?:建议|应该|应当|使用|添加|采用|切换|包裹|优化|节流|\buse\b|\badopt\b|\brecommend\b|\bswitch\b|\bwrap\b|\bthrottl(?:e|ing)\b)/i.test(n),g=/(?:不要|不得|不能|不应|避免|不建议|不推荐).{0,16}(?:使用|采用|添加|切换|包裹|节流)?.{0,8}(?:requestAnimationFrame|\bRAF\b)|\b(?:do\s+not|don't|never|avoid)\s+(?:use|adopt|recommend|switch|wrap|throttle)?.{0,8}(?:requestAnimationFrame|RAF)\b/i.test(n);m&&h&&!g&&!t&&r.add("raf_without_sampling_evidence");}function oe(n,e,t,r){let o=n.slice(Math.max(0,e-64),e),i=n.slice(e+t.length,e+t.length+28),s=pt(o),a=/^(?:\s+)?(?:未发现|不存在|并不存在|未被发现)/.test(i)||/^(?:\s+)?(?:was\s+|is\s+)?not found\b/i.test(i);return s||a?true:r==="high"?/(?:未发现|没有发现|不存在|无证据(?:表明|证明)?)\s*(?:任何|明确的)?\s*P0\s*(?:或|和|及|、)\s*$/i.test(o)||/\b(?:no evidence (?:of|for)|no)\s+P0\s+(?:or|and)\s+$/i.test(o):false}function pt(n){if(/(?:未发现|没有发现|不存在|无证据(?:表明|证明)?|不是|并非|未被)\s*(?:任何|明确的)?\s*(?:(?:问题|发现|证据|项|内容)\s*)?(?:(?:属于|(?:被)?(?:评|判定|认定|标记|列|视|定|归(?:类)?)为)\s*)?$/i.test(n)||/\b(?:no evidence (?:of|for)|no|not|isn't|is\s+not)\s+(?:an?\s+)?(?:(?:issues?|findings?|evidence|items?)\s+)?(?:(?:classified|rated|marked|labelled|labeled)(?:\s+as)?\s+)?$/i.test(n))return true;let t=/(?:不得|不能|不应|不宜|不要)\s*(?:被\s*)?(?:(?:直接|轻易|简单|明确|正式|合理|据此|当前|目前)\s*){0,2}(?:(?:评|判定|认定|标记|列|视|定|归(?:类)?)为|属于)\s*$/i,r=/\b(?:cannot|can't|must not|should not|shouldn't|do not|don't)\s+(?:(?:reasonably|directly|formally|currently)\s+){0,2}(?:be\s+)?(?:classified|labeled|labelled|rated|marked)(?:\s+as)?\s+$/i;return t.test(n)||r.test(n)}function ft(n,e,t){let r=n.slice(Math.max(0,e-40),e),o=n.slice(e+t.length,e+t.length+32),i=/(?:是否|待验证|候选|可能|潜在|未观察到|没有观察到|未发现|不存在|无证据(?:表明)?|不能(?:据此)?确认|尚未(?:确认|证明)|验证(?:是否)?|测量(?:是否)?|采集|记录|收集).{0,16}$/i.test(r)||/\b(?:whether|measure|validate|candidate|potential|possible|may|might|no|no evidence(?: of| for)?|not observed|unobserved|collect|record).{0,18}$/i.test(r),s=/^(?:是否|有待验证|待验证|候选|可能|潜在|指标|需要(?:验证|测量)|需(?:验证|测量))/.test(o)||/^(?:\s+)?(?:candidate|potential|possible|metric|metrics|to (?:measure|validate)|needs? (?:measurement|validation)|is (?:a )?(?:candidate|potential))/i.test(o);return i||s}function gt(n){return n.split(/(?:[。!?;;,,]|\b(?:but|however|yet|nevertheless|nonetheless)\b|但是|但|然而|却|不过|可是)/i).map(e=>e.trim()).filter(Boolean)}function $(n,e){if(!n||n.length>4096)return {degradationReason:"transcript_path_missing"};let t;try{let r=lstatSync(n);if(!r.isFile()||r.isSymbolicLink())return {degradationReason:"transcript_path_unsafe"};t=openSync(n,constants.O_RDONLY|(constants.O_NOFOLLOW??0));let o=fstatSync(t);if(!o.isFile()||o.dev!==r.dev||o.ino!==r.ino)return {degradationReason:"transcript_path_changed"};let i=Math.min(o.size,ot),s=Buffer.alloc(i),a=0;for(;a<i;){let g=readSync(t,s,a,i-a,o.size-i+a);if(g===0)break;a+=g;}let c=s.subarray(0,a).toString("utf8");o.size>i&&(c=c.slice(Math.max(0,c.indexOf(`
|
|
9
|
+
`)+1)));let l=c.split(/\r?\n/).slice(-it),d=e.length>0?Math.min(...e.map(g=>g.promptedAt)):0,u=ht(l,d),h=[...u].reverse().find(g=>yt(g.text,e))??u.at(-1);return h?.text?{answer:h.text,fingerprint:h.fingerprint}:{degradationReason:"transcript_answer_unavailable"}}catch{return {degradationReason:"transcript_unreadable"}}finally{t!==void 0&&closeSync(t);}}function yt(n,e){let t=new Set(e.flatMap(o=>o.contract.requiredSections)),r=ce(ae(n.split(/\r?\n/u)).headingLines);return [...t].every(o=>r.found.has(o))}function P(n){return $(n,[]).answer}function ht(n,e){let t=[];for(let r=0;r<n.length;r++){let o=n[r];if(o.trim())try{let i=JSON.parse(o),s=i.message;if(!s||typeof s!="object"||s.role!=="assistant")continue;let a=s,c=It(i.timestamp);if(c>0&&c+5e3<e)continue;let l=s.content,d=typeof l=="string"?l:Array.isArray(l)?l.filter(u=>u&&typeof u=="object"&&u.type==="text").map(u=>u.text).filter(u=>typeof u=="string").join(`
|
|
10
|
+
`):"";if(d.trim()){let u=d.trim(),m=typeof a.id=="string"&&a.id?`message:${a.id}`:typeof i.uuid=="string"&&i.uuid?`uuid:${i.uuid}`:`record:${String(i.timestamp??"")}:${r}:${createHash("sha256").update(o).digest("hex")}`,h=createHash("sha256").update(u).digest("hex"),g=createHash("sha256").update(`${m}\0${h}`).digest("hex");t.push({text:u,timestamp:c,fingerprint:g});}}catch{continue}}return t}function It(n){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n!="string")return 0;let e=Date.parse(n);return Number.isFinite(e)?e:0}function ce(n){let e=new Set,t=new Map,r;for(let o=0;o<n.length;o++){let i=n[o].trim().replace(/^#{1,6}\s*/,"").replace(/^\*\*(.*)\*\*$/,"$1").replace(/^(?:[一二三123][、..]\s*)/,"").replace(/[::]\s*$/,"").trim(),s=st.find(a=>i===a);s&&(r=s,e.add(s)),t.set(o,r);}return {found:e,byLine:t}}var _t={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 F(n){return wt(n)}function wt(n){let e=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{let t=xt(e,n.artifact);if(Et(t.toState))return t;let r=e.getContextReceiptForRequest(n.artifact.projectRoot,n.artifact.sessionId,n.artifact.requestId),o=e.getMemoryTurn(n.artifact.turnId),i=n.artifact.intent==="memory"||o?.source==="explicit_intent";if(!r&&!i)return t;let s=r?St(n.artifact,r):"context_ready";t.toState==="intent_bound"&&(t=f(e,t,n,s,i?"task_context_not_required":s==="context_ready"?"canonical_context_receipt_ready":"canonical_context_receipt_degraded"));let a=r?Rt(n.artifact,r):"action_not_required";if((t.toState==="context_ready"||t.toState==="context_degraded")&&(a==="action_not_required"?t=f(e,t,n,"action_not_required","task_action_not_required"):t=f(e,t,n,"action_required","canonical_action_obligation_present")),t.toState==="action_required"){if(a==="action_required")return t;if(a==="action_failed")return f(e,t,n,"action_failed","canonical_action_attempt_failed");a==="action_degraded"?t=f(e,t,n,"action_degraded","canonical_action_unavailable_or_degraded"):a==="action_satisfied"&&(t=f(e,t,n,"action_satisfied","canonical_action_succeeded"));}if(t.toState==="action_failed")if(a==="action_satisfied")t=f(e,t,n,"action_satisfied","canonical_action_retry_succeeded");else if(a==="action_degraded")t=f(e,t,n,"action_degraded","canonical_action_retry_degraded");else return t;let c=s==="context_degraded"||a==="action_degraded";return ["action_not_required","action_satisfied","action_degraded"].includes(t.toState)&&(t=f(e,t,n,n.memoryStatus==="pending"?"memory_quarantined":"memory_decided",n.memoryStatus==="pending"?n.reason:`canonical_memory_${n.memoryStatus}`)),t.toState==="memory_decided"?f(e,t,n,c?"closed_with_degradation":"closed",n.reason):t.toState==="memory_quarantined"?f(e,t,n,n.retryOwned?"closed_with_retry_work":"closed_with_degradation",n.retryOwned?"durable_retry_owner_confirmed":"terminal_obligation_unowned"):t}finally{e.close();}}function St(n,e){return n.intent==="memory"||n.intent==="knowledge"||(e.selectedFiles?.length??0)>0?"context_ready":"context_degraded"}function Rt(n,e){let t=e.canonicalAction,o=(t?(e.actionAttempts??[]).filter(i=>i.tool===t.tool):[]).at(-1);return e.actionSatisfiedAt||o?.status==="succeeded"?"action_satisfied":o&&["failed","timeout","unavailable"].includes(o.status)?"action_failed":e.actionDegradation||t?.status==="degraded"||t?.status==="unsupported"?"action_degraded":t?.required||kt(n)?"action_required":"action_not_required"}function kt(n){return ["create","modify","debug","test","format"].includes(n.action)||["feature","refactor","performance"].includes(n.intent)}function xt(n,e){let t=n.getLatestTerminalTransition(e.projectRoot,e.sessionId,e.turnId);if(!t)throw new Error(`TERMINAL_INTENT_STATE_MISSING:${e.turnId}`);return t}function f(n,e,t,r,o){if(!_t[e.toState]?.includes(r))throw new Error(`TERMINAL_PATH_UNAVAILABLE:${e.toState}->${r}`);let i=e.sequence+1,s=`terminal:${createHash("sha256").update(`${t.artifact.artifactHash}\0${i}\0${r}`).digest("hex").slice(0,24)}`,a=n.appendTerminalTransition({projectRoot:t.artifact.projectRoot,projectId:t.artifact.projectId,hostId:t.artifact.hostId,sessionId:t.artifact.sessionId,turnId:t.artifact.turnId,requestId:t.artifact.requestId,executionId:t.artifact.executionId,sequence:i,fromState:e.toState,toState:r,receiptId:s,sourceReceiptId:t.memoryReceiptId??e.receiptId,reason:o,payload:{memoryStatus:t.memoryStatus,retryOwned:t.retryOwned??false,sourceIntentHash:t.artifact.artifactHash},createdAt:Date.now()});return p({event:"terminal.state.transitioned",identity:{projectRoot:t.artifact.projectRoot,projectId:t.artifact.projectId,hostId:t.artifact.hostId,sessionId:t.artifact.sessionId,turnId:t.artifact.turnId,requestId:t.artifact.requestId,...t.artifact.executionId?{executionId:t.artifact.executionId}:{}},level:r==="closed"?"info":r.includes("degradation")||r.includes("retry")||r==="action_failed"?"warn":"info",timestamp:Date.now(),data:{fromState:e.toState,nextState:r,receiptId:s,reason:o}}),a}function Et(n){return n==="closed"||n==="closed_with_degradation"||n==="closed_with_retry_work"}function de(n,e){let t=join(n,".devflow","delivery-line","state.db");if(!existsSync(t)||!e.trim())return 0;let r;try{r=new DatabaseSync(t,{timeout:250});let o=r.prepare("SELECT id, payload FROM delivery_cases WHERE id = ? OR json_extract(payload, '$.sessionId') = ?").all(e,e),i=0,s=!!r.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'delivery_events'").get();for(let a of o){let c="incomplete";try{let l=JSON.parse(a.payload);c=l.evidence?.some(d=>d.metadata?.trust==="external-untrusted")?"untrusted":l.stage==="delivered"?"clean":"incomplete";}catch{}if(i+=Number(r.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 l=`session.closed:${a.id}:${e}`;r.prepare("INSERT OR IGNORE INTO delivery_events (id,case_id,idempotency_key,actor,type,payload,created_at,processed_at) VALUES (?,?,?,?,?,?,?,NULL)").run(l,a.id,l,JSON.stringify({id:"devflow:session-end",kind:"system"}),"session.closed",JSON.stringify({sessionId:e,releasedLeases:i,outcome:c}),Date.now());}}return i}catch{return 0}finally{r?.close();}}function le(n){let e={committed:0,skipped:0,pending:0},t=[];for(let r of n)e[r.status]+=1,r.receiptId&&t.push(r.receiptId);return {memoryReceiptIds:[...new Set(t)],missingMemoryDecisionCount:e.pending,memoryTurnOutcomes:e}}function Mt(n){return (n instanceof Error?n.message:String(n)).trim().slice(0,240)||"memory_lifecycle_unavailable"}function jt(n,e=_(),t=true,r,o=true){let i;try{i=JSON.parse(n);}catch{return null}let s=i.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${e}\0${s}`).digest("hex").slice(0,24)}`,c={inputJson:n,sessionId:s,cleanupSharedState:t,executionId:r};try{de(e,s);}catch{}let l;try{l=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let d=l.requestSessionClosure({receiptId:a,projectRoot:e,sessionId:s,payload:c}),u=l.getWorkByIdempotencyKey(a),m={status:d.state==="closed"||d.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:u?.state??"pending",closureState:d.state,pendingWorkCount:d.pendingWorkCount,...u?.id?{workItemId:u.id}:{}};return p({event:"hook.session_end.completed",identity:{projectRoot:e,sessionId:s,executionId:r,terminalReceipt:a},level:m.status==="completed"?"info":"debug",timestamp:Date.now(),data:{stage:"enqueue",...m}}),m}catch(d){if(!o)throw d;return te(e,{receiptId:a,...c}),p({event:"hook.session_end.degraded",identity:{projectRoot:e,sessionId:s,executionId:r,terminalReceipt:a},level:"warn",timestamp:Date.now(),data:{stage:"enqueue",reason:Mt(d),fallback:"durable_spool"}}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{l?.close();}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=jt(e.trim()||process.argv[2]||"");t&&n(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}var E=1,Ht="memory-snapshot-v1.json",zt=512*1024,fe=256*1024,ge=2e3,Ut=500,Bt=10,Jt=240,Wt=300*1e3,Gt=720*60*60*1e3,Kt=2147483647;function Vt(n){return n.currentUid===void 0?{ownerSafe:true,modeSafe:true}:{ownerSafe:n.ownerUid===n.currentUid,modeSafe:(n.mode&18)===0}}function b(n){return resolve(n)}function S(n){return createHash("sha256").update(b(n)).digest("hex").slice(0,16)}function Yt(n,e={}){let t=S(n),r=e.stateRoot?join(e.stateRoot,t):getProjectStateDir(b(n));return join(r,Ht)}function Xt(n,e){let r=(n instanceof Error?n.message:"").replace(/[\r\n\t]+/gu," ").trim().slice(0,160);return r?`${e}:${r}`:e}function L(n,e){return Array.isArray(n)&&n.length<=e&&n.every(t=>typeof t=="string"&&t.length>0&&t.length<=512)}function Zt(n){if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return typeof e.id=="string"&&e.id.length>0&&e.id.length<=512&&typeof e.kind=="string"&&e.kind.length>0&&e.kind.length<=128&&(e.family===void 0||typeof e.family=="string"&&e.family.length>0&&e.family.length<=256)&&(e.entity===void 0||typeof e.entity=="string"&&e.entity.length>0&&e.entity.length<=256)&&L(e.memoryIds,100)&&(e.status==="withheld"||e.status==="resolved")&&(e.summary===void 0||typeof e.summary=="string"&&e.summary.length<=2e3)}function Qt(n){if(!n||typeof n!="object"||Array.isArray(n))return false;let e=n;return typeof e.reason=="string"&&e.reason.length>0&&e.reason.length<=512&&(e.stale===void 0||typeof e.stale=="boolean")}function ye(n,e,t){if(!n||typeof n!="object"||Array.isArray(n))return null;let r=n,o=b(e),i=S(o),s=r.generation===void 0?0:r.generation;return r.version!==E||r.projectRoot!==o||r.projectHash!==i||typeof r.markdown!="string"||Buffer.byteLength(r.markdown,"utf8")>fe||!L(r.memoryIds,ge)||!Array.isArray(r.conflicts)||r.conflicts.length>Ut||!r.conflicts.every(Zt)||typeof r.generatedAt!="number"||!Number.isFinite(r.generatedAt)||r.generatedAt<0||r.generatedAt>t+Wt||!Number.isInteger(s)||s<0||s>Kt||!["ready","pending","degraded","disabled"].includes(String(r.status))||r.degradation!==void 0&&!Qt(r.degradation)?null:{...r,generation:s}}function en(n,e,t,r,o=0){let i=b(n);return {version:E,projectRoot:i,projectHash:S(i),markdown:"",memoryIds:[],conflicts:[],generatedAt:r,generation:o,status:e,degradation:{reason:t}}}function tn(n,e={}){let t=e.now??Date.now(),r=Yt(n,e),o;try{o=openSync(r,constants.O_RDONLY|constants.O_NOFOLLOW);let i=fstatSync(o);if(!i.isFile()||i.size<=0||i.size>zt)throw new Error("cache_size_invalid");let s=Vt({...typeof process.getuid=="function"?{currentUid:process.getuid()}:{},ownerUid:i.uid,mode:i.mode});if(!s.ownerSafe)throw new Error("cache_owner_invalid");if(!s.modeSafe)throw new Error("cache_permissions_unsafe");let a=JSON.parse(readFileSync(o,"utf8")),c=ye(a,n,t);if(!c)throw new Error("cache_schema_invalid");return c.status==="ready"&&t-c.generatedAt>Gt?{snapshot:{...c,status:"degraded",degradation:{reason:"cache_stale",stale:!0}},source:"cache",valid:!0,stale:!0}:{snapshot:c,source:"cache",valid:!0,stale:!1}}catch(i){let a=i.code==="ENOENT";return {snapshot:en(n,a?"pending":"degraded",a?"cache_missing":Xt(i,"cache_invalid"),t),source:"none",valid:false,stale:false}}finally{if(o!==void 0)try{closeSync(o);}catch{}}}function nn(n){if(!n)return true;try{return JSON.parse(readFileSync(n,"utf8")).sessionStart?.injectMemories??!0}catch{return true}}function rn(n,e,t){if(!e.trim())return null;try{let r=JSON.parse(e);if(r.status!=="ok"&&r.status!=="degraded")return null;if(r.enabled===!1){let i=b(n);return {version:E,projectRoot:i,projectHash:S(i),markdown:"",memoryIds:[],conflicts:[],generatedAt:t,generation:0,status:"disabled"}}let o=ye(r.snapshot,n,t);if(o)return o;if(r.status==="ok"&&typeof r.markdown=="string"&&r.markdown.length>0&&Buffer.byteLength(r.markdown,"utf8")<=fe){let i=b(n);return {version:E,projectRoot:i,projectHash:S(i),markdown:r.markdown,memoryIds:L(r.memoryIds,ge)?r.memoryIds:[],conflicts:[],generatedAt:t,generation:0,status:"ready"}}}catch{}return null}function N(n,e){return [...(n??e).replace(/[\r\n\t|]+/gu," ").trim()||e].slice(0,Jt).join("")}function on(n){if(n.length===0)return "";let e=n.slice(0,Bt),t=e.map(r=>{let o=N(r.family,"unknown"),i=N(r.entity,"unknown"),s=N(r.summary,"Explicit choice required.");return `- family=${o}; entity=${i}; status=${r.status}; summary=${s}`});return n.length>e.length&&t.push(`- ${n.length-e.length} additional conflict(s) omitted from SessionStart output.`),`## Withheld preference conflicts (${n.length})
|
|
11
11
|
${t.join(`
|
|
12
|
-
`)}`}function sn(n){let e=n.now??Date.now();if(nn(n.configPath)===false)return "";let t=
|
|
13
|
-
DevFlow memory snapshot=pending; source=${
|
|
12
|
+
`)}`}function sn(n){let e=n.now??Date.now();if(nn(n.configPath)===false)return "";let t=rn(n.projectRoot,n.daemonResponse??"",e),r=t?{snapshot:t,source:"daemon"}:tn(n.projectRoot,{...n.cacheOptions,now:e}),{snapshot:o}=r;if(o.status==="disabled")return `## Project memory
|
|
13
|
+
DevFlow memory snapshot=pending; source=${r.source}; reason=previous_snapshot_disabled. Memory availability is not yet known; do not conclude that the project has no memories.`;let i=new Date(o.generatedAt).toISOString(),s=o.degradation?.reason?`; reason=${o.degradation.reason}`:"",a=`DevFlow memory snapshot=${o.status}; source=${r.source}; generatedAt=${i}${s}.`,c=on(o.conflicts);return o.markdown?[o.markdown,c,a].filter(Boolean).join(`
|
|
14
14
|
`):["## Project memory",c,`${a} Memory availability is not yet known; do not conclude that the project has no memories.`].filter(Boolean).join(`
|
|
15
|
-
`)}if(process.env.DEVFLOW_MEMORY_SNAPSHOT_CLI==="1"){let[,,n,e,t]=process.argv;n!=="session-start"||!e?process.exitCode=2:process.stdout.write(sn({projectRoot:e,configPath:t,daemonResponse:process.env.DEVFLOW_MEMORY_RESPONSE}));}function Ie(n){return `DevFlow memory decision required for ${n.turnId}. Before the final response, semantically decide whether this turn contains durable project knowledge. Call ${projectClaudeToolName("memory_commit_turn")} with evidence-bound candidates, or ${projectClaudeToolName("memory_skip_turn")} with a concrete reason. Do not claim memory success without a canonical receipt. For candidates, copy exact evidenceSpans from this user prompt, preserve package names, flags, versions, paths, and identifiers, and provide subject, predicate, value, polarity, and entities when known. To replace or retire an existing fact, provide operation=supersede or operation=retire plus referencedFactIds from the canonical memory receipt; aliases and entity names are not fact identity. Do not save assistant echoes, task narration, retries, or unverified guesses. Express a change from an old choice as the new durable value. If the decision tool remains unavailable, explicitly state that the memory was not saved.`}function ve(n){let e=ie({projectRoot:n.projectRoot,sessionId:n.sessionId,transcriptPath:n.transcriptPath,runtimeStore:n.runtimeStore}),t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});try{mn(n.runtimeStore,n.sessionId,t);let
|
|
15
|
+
`)}if(process.env.DEVFLOW_MEMORY_SNAPSHOT_CLI==="1"){let[,,n,e,t]=process.argv;n!=="session-start"||!e?process.exitCode=2:process.stdout.write(sn({projectRoot:e,configPath:t,daemonResponse:process.env.DEVFLOW_MEMORY_RESPONSE}));}function Ie(n){return `DevFlow memory decision required for ${n.turnId}. Before the final response, semantically decide whether this turn contains durable project knowledge. Call ${projectClaudeToolName("memory_commit_turn")} with evidence-bound candidates, or ${projectClaudeToolName("memory_skip_turn")} with a concrete reason. Do not claim memory success without a canonical receipt. For candidates, copy exact evidenceSpans from this user prompt, preserve package names, flags, versions, paths, and identifiers, and provide subject, predicate, value, polarity, and entities when known. To replace or retire an existing fact, provide operation=supersede or operation=retire plus referencedFactIds from the canonical memory receipt; aliases and entity names are not fact identity. Do not save assistant echoes, task narration, retries, or unverified guesses. Express a change from an old choice as the new durable value. If the decision tool remains unavailable, explicitly state that the memory was not saved.`}function ve(n){let e=ie({projectRoot:n.projectRoot,sessionId:n.sessionId,transcriptPath:n.transcriptPath,runtimeStore:n.runtimeStore}),t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});try{mn(n.runtimeStore,n.sessionId,t);let r=t.getPendingMemoryTurn(n.projectRoot,n.sessionId),o=r?t.markMemoryTurnStopPrompted(r.turnId):!1,i=[];e&&i.push(e.reason),r&&o&&i.push(Ie(r)),r&&!o&&ln(t,r.turnId)&&un(P(n.transcriptPath))&&i.push(`DevFlow explicit memory ${r.turnId} still has no canonical receipt. Remove the memory-success claim and tell the user that the memory was not saved, or complete the pending turn.`);let a=t.listSessionObligations(n.projectRoot,n.sessionId,["open"]).map(c=>({obligationId:c.obligationId,kind:c.kind,action:c.kind==="memory_decision"?`Call ${projectClaudeToolName("memory_decide_turn")} using the canonical turn ID.`:c.kind==="evidence_contract"?c.payload.subtype==="policy_verification"?`Complete the required project verification: ${String(c.payload.command??c.payload.verificationKind??"unknown command")}.`:"Return a final answer that satisfies the canonical evidence contract.":"Allow SessionEnd durable finalization to complete.",canonicalInput:c.kind==="memory_decision"&&c.turnId?{turnId:c.turnId}:void 0}));return i.length>0?{decision:"block_once",unresolved:a,additionalContext:["DevFlow has unresolved terminal obligations. Complete all actions below before stopping.",...i].join(`
|
|
16
16
|
|
|
17
|
-
`)}:a.length>0?{decision:"degrade",unresolved:a,additionalContext:"DevFlow terminal obligations remain unresolved after their one-shot correction budget."}:{decision:"allow",unresolved:[]}}finally{t.close();}}function ln(n,e){return !!n.getWorkByIdempotencyKey(`memory-turn:commit_explicit:${e}`)}function un(n){if(!n)return false;let e=n.normalize("NFKC").replace(/\s+/gu," ");return /(?:未|没有|无法|失败|暂未|尚未).{0,24}(?:记住|记下|记录|保存|持久化|回执)|(?:memory|receipt).{0,24}(?:failed|missing|pending|degraded|not saved)|status=(?:pending|degraded|rejected|failed)/iu.test(e)?false:/(?:已|已经|成功).{0,20}(?:记住|记下|记录|保存|持久化)|跨会话生效|(?:memory|preference).{0,20}(?:saved|remembered|persisted)|status=(?:accepted|committed)/iu.test(e)}function mn(n,e,t){let
|
|
17
|
+
`)}:a.length>0?{decision:"degrade",unresolved:a,additionalContext:"DevFlow terminal obligations remain unresolved after their one-shot correction budget."}:{decision:"allow",unresolved:[]}}finally{t.close();}}function ln(n,e){return !!n.getWorkByIdempotencyKey(`memory-turn:commit_explicit:${e}`)}function un(n){if(!n)return false;let e=n.normalize("NFKC").replace(/\s+/gu," ");return /(?:未|没有|无法|失败|暂未|尚未).{0,24}(?:记住|记下|记录|保存|持久化|回执)|(?:memory|receipt).{0,24}(?:failed|missing|pending|degraded|not saved)|status=(?:pending|degraded|rejected|failed)/iu.test(e)?false:/(?:已|已经|成功).{0,20}(?:记住|记下|记录|保存|持久化)|跨会话生效|(?:memory|preference).{0,20}(?:saved|remembered|persisted)|status=(?:accepted|committed)/iu.test(e)}function mn(n,e,t){let r=n.get(e);if(r){for(let o of r.evidenceObligations)t.upsertSessionObligation({obligationId:`evidence:${o.obligationId}`,projectRoot:r.projectRoot,sessionId:e,executionId:r.executionId,kind:"evidence_contract",state:"open",payload:{contract:o.contract,runtimeObligationId:o.obligationId},createdAt:o.promptedAt,updatedAt:r.lastActivityAt});for(let o of r.evidenceOutcomes){let i=`evidence:${o.obligationId}`,s=t.getSessionObligation(r.projectRoot,e,i);if(!s||s.state!=="open"&&!(s.state==="degraded"&&o.status==="resolved"))continue;let a=o.status==="resolved"?`evidence-receipt:${createHash("sha256").update(`${o.obligationId}\0${o.completedAt}\0${o.attempt}`).digest("hex").slice(0,24)}`:void 0;t.resolveSessionObligation({projectRoot:r.projectRoot,sessionId:e,obligationId:i,state:o.status==="resolved"?"satisfied":"degraded",receiptId:a,reason:o.reason,resolvedAt:o.completedAt});}}}async function fn(n,e=_()){let t;try{t=JSON.parse(n);}catch{return null}let r=t.session_id?.trim();if(!r)return null;let o=new I(e),i=ve({projectRoot:e,sessionId:r,transcriptPath:t.transcript_path,stopHookActive:t.stop_hook_active===true,runtimeStore:o});if(i.decision==="block_once")return p({event:"hook.stop.degraded",identity:{projectRoot:e,sessionId:r},level:"warn",timestamp:Date.now(),data:{decision:"block_once",unresolved:i.unresolved.map(a=>a.obligationId)}}),{decision:"block",reason:i.additionalContext};let s=o.completeExecution(r);if(s?.executionId){let a=openGlobalDevFlowDatabase();try{let c=a.listSessionMemoryTurnsForReconciliation(e,r),l=new Map(a.listLatestTaskIntentArtifacts(e,r).map(d=>[d.turnId,d]));for(let d of c){let u=l.get(d.turnId);!u||d.status==="pending"||F({artifact:u,memoryStatus:d.status,memoryReceiptId:d.receiptId,reason:"stop_obligations_satisfied"});}a.reconcileSkillExecution(s.executionId,"completed",Date.now(),{...le(c),evidenceDegradations:s.evidenceDegradations,evidenceContractOutcomes:s.evidenceOutcomes,unresolvedObligations:i.unresolved,terminalState:i.decision}),a.deleteContextReceipt(e,r,s.executionId);}finally{a.close();}}return k(`/api/telemetry/sessions/${encodeURIComponent(r)}/tick`,{timestamp:Date.now()},{fallbackReason:"stop_tick_already_local"}),p({event:"hook.stop.completed",identity:{projectRoot:e,sessionId:r,executionId:s?.executionId},level:"info",timestamp:Date.now(),data:{decision:i.decision,unresolvedCount:i.unresolved.length}}),null}if(process.argv[1]?.endsWith("stop")||process.argv[1]?.endsWith("stop.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=await fn(e.trim()||process.argv[2]||"");t&&n(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),4e3).unref();}export{fn as handleStop};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifestVersion": "devflow-runtime.v1",
|
|
3
|
-
"packageVersion": "0.
|
|
4
|
-
"sourceCommit": "
|
|
3
|
+
"packageVersion": "0.19.1",
|
|
4
|
+
"sourceCommit": "b61099e2d21991cf212012dfbe965393fbf4da00",
|
|
5
5
|
"bundleHashes": {
|
|
6
|
-
"hooks": "
|
|
6
|
+
"hooks": "40df4bca4427aee4f71c5ca021b96ba5d22951b1677162cd4d1e15625b343563",
|
|
7
7
|
"mcp": "ae638ba33e7807efad1554deadd8517002e7e6a263a4f4745ff7cb2081671997",
|
|
8
|
-
"cli": "
|
|
8
|
+
"cli": "6107445bfaec2e9a72d6cbf165f7dbdd1077388d8d0d6d5f883571e90d791871"
|
|
9
9
|
},
|
|
10
|
-
"registryHash": "
|
|
10
|
+
"registryHash": "89109dd3624492b5c46a2aecc7d708f0d1d89a6ae3655ee3ace1c6686f23bb2f",
|
|
11
11
|
"stateDbPath": "<projectRoot>/.devflow/delivery-line/state.db",
|
|
12
|
-
"builtAt":
|
|
13
|
-
"manifestHash": "
|
|
12
|
+
"builtAt": 1793610259242,
|
|
13
|
+
"manifestHash": "ba0ebac2659579541c443979b9e0f4da1fcae613b7b8502632c5a56e3e9c9c29"
|
|
14
14
|
}
|
package/hooks/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# DevFlow Hooks 注册表
|
|
2
|
+
|
|
3
|
+
`hooks.json` 中每个条目的用途说明。Claude Code 的 hooks schema 只接受 `matcher` 与 `hooks` 键,
|
|
4
|
+
`id` / `description` 元数据存放于此,不写入 `hooks.json`(否则 CLI 启动时会产生 unknown keys 警告)。
|
|
5
|
+
|
|
6
|
+
| id | 事件 | 脚本 | 说明 |
|
|
7
|
+
| --- | --- | --- | --- |
|
|
8
|
+
| `session:start:banner` | SessionStart | `session-start` | Compact DevFlow session banner: capability pointer, memory snapshot, gateway status |
|
|
9
|
+
| `pre:devflow-gate` | PreToolUse | `pre-tool-use` | Delivery write gate + execution/context-receipt tracking for Skill and MCP calls. Read-only discovery tools (Read/Grep/Glob/Agent/WebSearch) are deliberately NOT matched — they are advisory only. |
|
|
10
|
+
| `post:telemetry` | PostToolUse | `post-tool-use` | Telemetry completion + memory turn staging (non-blocking observation) |
|
|
11
|
+
| `post:failure-learning` | PostToolUseFailure | `post-tool-use-failure` | Failure classification + learning extraction from failed tool calls |
|
|
12
|
+
| `prompt:intent` | UserPromptSubmit | `user-prompt-submit` | Task intent capture + turn correlation |
|
|
13
|
+
| `stop:finalize` | Stop | `stop` | Memory turn finalize + graceful daemon shutdown |
|
|
14
|
+
| `compact:persist` | PreCompact | `pre-compact` | Persist durable state before context compaction |
|
|
15
|
+
| `session:end:cleanup` | SessionEnd | `session-end` | Lifecycle cleanup: release delivery leases, spool finalize, state cleanup |
|
package/hooks/constitution.md
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
你正在使用 DevFlow MCP Gateway。
|
|
1
|
+
# DevFlow 能力声明
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
你已接入 DevFlow —— 项目智能层:上下文包、符号与依赖检索、项目记忆、知识库和标准工作流。运行 /devflow 查看全部已安装能力,按项目技术栈选择对应领域技能。
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
Hook 会自动拦截不符合规范的原生工具调用,并按提示引导你使用正确的 MCP 工具。
|
|
5
|
+
使用 /devflow:* 技能时的推荐路径:先调用 SKILL.md 列出的 MCP 工具获取上下文,再基于返回结果分析;需要补充细节时用 Read 读取关联文件。MCP 不可用时重试一次,然后可直接用原生工具检索,并如实说明已降级。
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
1. 调用 Skill 加载命令
|
|
11
|
-
2. 立即调用 MCP 工具
|
|
12
|
-
3. 基于 MCP 结果回答
|
|
13
|
-
4. 如需补充信息,使用 Read 工具读取 MCP 未包含的关联文件
|
|
7
|
+
真实性约定(无论何时使用 DevFlow 都适用):
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- 用 Agent(Explore) 替代 MCP 工具
|
|
19
|
-
- 尝试绕过 Hook 拦截
|
|
20
|
-
</EXTREMELY_IMPORTANT>
|
|
9
|
+
- 记忆保存以 DevFlow canonical receipt 为准;队列接受或宿主本地写入不等于保存成功。
|
|
10
|
+
- 静态发现不是运行时测量——不虚构瓶颈、严重度或量化的收益数字。
|
|
11
|
+
- 工作流成功需要 canonical host-action 与验证证据;降级、取消、失败、未知状态不得记为成功。
|
package/hooks/hooks.json
CHANGED
|
@@ -6,18 +6,20 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start\""
|
|
9
|
+
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/session-start\"",
|
|
10
|
+
"timeout": 15
|
|
10
11
|
}
|
|
11
12
|
]
|
|
12
13
|
}
|
|
13
14
|
],
|
|
14
15
|
"PreToolUse": [
|
|
15
16
|
{
|
|
16
|
-
"matcher": "
|
|
17
|
+
"matcher": "Write|Edit|NotebookEdit|Bash|Skill|mcp__.*",
|
|
17
18
|
"hooks": [
|
|
18
19
|
{
|
|
19
20
|
"type": "command",
|
|
20
|
-
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-tool-use\""
|
|
21
|
+
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-tool-use\"",
|
|
22
|
+
"timeout": 10
|
|
21
23
|
}
|
|
22
24
|
]
|
|
23
25
|
}
|
|
@@ -28,7 +30,8 @@
|
|
|
28
30
|
"hooks": [
|
|
29
31
|
{
|
|
30
32
|
"type": "command",
|
|
31
|
-
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use\""
|
|
33
|
+
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use\"",
|
|
34
|
+
"timeout": 10
|
|
32
35
|
}
|
|
33
36
|
]
|
|
34
37
|
}
|
|
@@ -39,7 +42,8 @@
|
|
|
39
42
|
"hooks": [
|
|
40
43
|
{
|
|
41
44
|
"type": "command",
|
|
42
|
-
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use-failure\""
|
|
45
|
+
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/post-tool-use-failure\"",
|
|
46
|
+
"timeout": 10
|
|
43
47
|
}
|
|
44
48
|
]
|
|
45
49
|
}
|
|
@@ -62,7 +66,8 @@
|
|
|
62
66
|
"hooks": [
|
|
63
67
|
{
|
|
64
68
|
"type": "command",
|
|
65
|
-
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/stop\""
|
|
69
|
+
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/stop\"",
|
|
70
|
+
"timeout": 15
|
|
66
71
|
}
|
|
67
72
|
]
|
|
68
73
|
}
|
package/hooks/post-tool-use
CHANGED
|
@@ -5,6 +5,13 @@ set -euo pipefail
|
|
|
5
5
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
6
|
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$SCRIPT_DIR/..}"
|
|
7
7
|
source "$SCRIPT_DIR/runtime-node"
|
|
8
|
+
|
|
9
|
+
# Global kill switch: exit with no opinion before spawning any runtime.
|
|
10
|
+
if devflow_is_disabled; then
|
|
11
|
+
cat >/dev/null 2>&1 || true
|
|
12
|
+
exit 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
8
15
|
DEVFLOW_NODE="$(devflow_resolve_node "$PLUGIN_ROOT")"
|
|
9
16
|
CLIENT_JS="$PLUGIN_ROOT/dist/hooks/hook-client.js"
|
|
10
17
|
FALLBACK_JS="$PLUGIN_ROOT/dist/hooks/post-tool-use.js"
|
|
@@ -4,6 +4,13 @@ set -euo pipefail
|
|
|
4
4
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
5
|
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$SCRIPT_DIR/..}"
|
|
6
6
|
source "$SCRIPT_DIR/runtime-node"
|
|
7
|
+
|
|
8
|
+
# Global kill switch: exit with no opinion before spawning any runtime.
|
|
9
|
+
if devflow_is_disabled; then
|
|
10
|
+
cat >/dev/null 2>&1 || true
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
7
14
|
DEVFLOW_NODE="$(devflow_resolve_node "$PLUGIN_ROOT")"
|
|
8
15
|
CLIENT_JS="$PLUGIN_ROOT/dist/hooks/hook-client.js"
|
|
9
16
|
FALLBACK_JS="$PLUGIN_ROOT/dist/hooks/post-tool-use-failure.js"
|
package/hooks/pre-compact
CHANGED
|
@@ -4,6 +4,13 @@ set -euo pipefail
|
|
|
4
4
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
5
|
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$SCRIPT_DIR/..}"
|
|
6
6
|
source "$SCRIPT_DIR/runtime-node"
|
|
7
|
+
|
|
8
|
+
# Global kill switch: exit with no opinion before spawning any runtime.
|
|
9
|
+
if devflow_is_disabled; then
|
|
10
|
+
cat >/dev/null 2>&1 || true
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
7
14
|
DEVFLOW_NODE="$(devflow_resolve_node "$PLUGIN_ROOT")"
|
|
8
15
|
CLIENT_JS="$PLUGIN_ROOT/dist/hooks/hook-client.js"
|
|
9
16
|
FALLBACK_JS="$PLUGIN_ROOT/dist/hooks/pre-compact.js"
|
package/hooks/pre-tool-use
CHANGED
|
@@ -1,27 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
|
-
# DevFlow PreToolUse Hook — talks to hook-daemon via hook-client
|
|
4
|
+
# DevFlow PreToolUse Hook — talks to hook-daemon via hook-client.
|
|
5
|
+
# DevFlow must fail open: if the hook runtime is unavailable the host keeps
|
|
6
|
+
# native behavior; empty output means "no opinion" (allow).
|
|
5
7
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
8
|
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$SCRIPT_DIR/..}"
|
|
7
9
|
source "$SCRIPT_DIR/runtime-node"
|
|
10
|
+
|
|
11
|
+
# Global kill switch: exit with no opinion before spawning any runtime.
|
|
12
|
+
if devflow_is_disabled; then
|
|
13
|
+
cat >/dev/null 2>&1 || true
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
8
17
|
DEVFLOW_NODE="$(devflow_resolve_node "$PLUGIN_ROOT")"
|
|
9
18
|
CLIENT_JS="$PLUGIN_ROOT/dist/hooks/hook-client.js"
|
|
10
19
|
FALLBACK_JS="$PLUGIN_ROOT/dist/hooks/pre-tool-use.js"
|
|
11
20
|
|
|
12
21
|
if [ -f "$CLIENT_JS" ] && devflow_has_local_runtime "$PLUGIN_ROOT"; then
|
|
13
22
|
"$DEVFLOW_NODE" "$CLIENT_JS" pre-tool-use || {
|
|
14
|
-
echo '[devflow] hook-client failed, trying fallback' >&2
|
|
15
23
|
if [ -f "$FALLBACK_JS" ]; then
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"DevFlow hook unavailable; writes are blocked until Delivery authority can be verified."}}'
|
|
24
|
+
echo '[devflow] hook-client failed, trying fallback' >&2
|
|
25
|
+
DEVFLOW_HOOK_DEGRADED=1 "$DEVFLOW_NODE" "$FALLBACK_JS" || exit 0
|
|
19
26
|
fi
|
|
27
|
+
exit 0
|
|
20
28
|
}
|
|
21
29
|
elif [ -f "$CLIENT_JS" ]; then
|
|
22
|
-
devflow_npm_hook "$PLUGIN_ROOT" hook-client pre-tool-use ||
|
|
30
|
+
devflow_npm_hook "$PLUGIN_ROOT" hook-client pre-tool-use || exit 0
|
|
23
31
|
elif [ -f "$FALLBACK_JS" ]; then
|
|
24
|
-
DEVFLOW_HOOK_DEGRADED=1 "$DEVFLOW_NODE" "$FALLBACK_JS" ||
|
|
25
|
-
else
|
|
26
|
-
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"DevFlow hook unavailable; writes are blocked until Delivery authority can be verified."}}'
|
|
32
|
+
DEVFLOW_HOOK_DEGRADED=1 "$DEVFLOW_NODE" "$FALLBACK_JS" || exit 0
|
|
27
33
|
fi
|
|
34
|
+
|
|
35
|
+
exit 0
|
package/hooks/runtime-node
CHANGED
|
@@ -50,3 +50,14 @@ devflow_npm_hook() {
|
|
|
50
50
|
# workspace bin found in the caller's current directory.
|
|
51
51
|
npx --yes --package "@devflow-tools/devflow@${version}" --call "devflow $*"
|
|
52
52
|
}
|
|
53
|
+
|
|
54
|
+
# Global kill switch: active when DEVFLOW_DISABLED=1 or a `disable` marker
|
|
55
|
+
# file exists in the DevFlow state root (DEVFLOW_STATE_DIR or ~/.devflow).
|
|
56
|
+
# All env resolution lives here so hook scripts stay free of env literals.
|
|
57
|
+
devflow_is_disabled() {
|
|
58
|
+
if [ "${DEVFLOW_DISABLED:-0}" = "1" ]; then
|
|
59
|
+
return 0
|
|
60
|
+
fi
|
|
61
|
+
local state_root="${DEVFLOW_STATE_DIR:-${HOME:-}/.devflow}"
|
|
62
|
+
[ -f "${state_root}/disable" ]
|
|
63
|
+
}
|
package/hooks/session-end
CHANGED
|
@@ -4,6 +4,13 @@ set -euo pipefail
|
|
|
4
4
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
5
|
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$SCRIPT_DIR/..}"
|
|
6
6
|
source "$SCRIPT_DIR/runtime-node"
|
|
7
|
+
|
|
8
|
+
# Global kill switch: exit with no opinion before spawning any runtime.
|
|
9
|
+
if devflow_is_disabled; then
|
|
10
|
+
cat >/dev/null 2>&1 || true
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
7
14
|
DEVFLOW_NODE="$(devflow_resolve_node "$PLUGIN_ROOT")"
|
|
8
15
|
CLIENT_JS="$PLUGIN_ROOT/dist/hooks/hook-client.js"
|
|
9
16
|
FALLBACK_JS="$PLUGIN_ROOT/dist/hooks/session-end.js"
|