toolnet-memory 0.3.11 → 0.3.13
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/.env.example +0 -4
- package/README.md +428 -202
- package/bin/toolnet-memory +15 -42
- package/bundle/agy-hook.js +47 -47
- package/bundle/agy.js +31 -31
- package/bundle/api.js +15 -52
- package/bundle/auto-integrate.js +34 -33
- package/bundle/claude-hook.js +9 -9
- package/bundle/codex.js +28 -28
- package/bundle/config.js +17 -12
- package/bundle/context-runtime.js +9 -9
- package/bundle/context.js +12 -12
- package/bundle/continuity-certify.js +13 -50
- package/bundle/copilot-hook.js +13 -13
- package/bundle/cursor-hook.js +13 -13
- package/bundle/doctor.js +4 -6
- package/bundle/full-index.js +21 -22
- package/bundle/graph-index.js +3 -3
- package/bundle/graph-ui.js +3 -3
- package/bundle/grok-hook.js +13 -13
- package/bundle/help-cli.js +4 -4
- package/bundle/impact.js +3 -3
- package/bundle/incremental.js +3 -3
- package/bundle/init.js +37 -36
- package/bundle/kilo.js +2 -0
- package/bundle/kiro-hook.js +14 -14
- package/bundle/learner.js +4 -4
- package/bundle/mcp.js +18 -56
- package/bundle/memory-agent.js +7 -47
- package/bundle/opencode.js +27 -27
- package/bundle/project-manual.js +2 -2
- package/bundle/recovery-certify.js +13 -53
- package/bundle/runtime.js +11 -11
- package/bundle/semantic.js +5 -6
- package/bundle/snapshot.js +3 -3
- package/bundle/status-cli.js +4 -4
- package/bundle/toolnet-cli.js +2 -0
- package/bundle/work-continuity.js +5 -5
- package/package.json +1 -3
- package/bundle/model-cli.js +0 -2
- package/bundle/provider.js +0 -6
- package/bundle/setup.js +0 -1159
|
@@ -1,50 +1,13 @@
|
|
|
1
|
-
import{mkdirSync as
|
|
2
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function
|
|
3
|
-
`)}function
|
|
4
|
-
`)}function
|
|
5
|
-
|
|
6
|
-
`)}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Rules:
|
|
15
|
-
|
|
16
|
-
1. Answer only from the supplied ToolNet project memory.
|
|
17
|
-
2. Never invent completed work, files, blockers, decisions, or test results.
|
|
18
|
-
3. Prefer the latest session/work state over old information.
|
|
19
|
-
4. Be concise.
|
|
20
|
-
5. Do not dump raw JSON or full memory files.
|
|
21
|
-
6. Tell the coding agent exactly:
|
|
22
|
-
- what the previous agent was doing,
|
|
23
|
-
- what is already completed,
|
|
24
|
-
- what remains unfinished,
|
|
25
|
-
- what file was last touched,
|
|
26
|
-
- what should be done next,
|
|
27
|
-
when those facts are available.
|
|
28
|
-
7. If information is missing, say it is not recorded.
|
|
29
|
-
8. Do not explain ToolNet internals unless asked.
|
|
30
|
-
9. Do not repeat irrelevant history.
|
|
31
|
-
10. Respond in the same language as the question.
|
|
32
|
-
|
|
33
|
-
Think of yourself as the project's memory coworker talking directly to another AI.
|
|
34
|
-
`.trim()},{role:"user",content:`
|
|
35
|
-
Question from coding agent:
|
|
36
|
-
|
|
37
|
-
${e}
|
|
38
|
-
|
|
39
|
-
ToolNet selected memory:
|
|
40
|
-
|
|
41
|
-
${o}
|
|
42
|
-
|
|
43
|
-
Answer the coding agent directly.
|
|
44
|
-
`.trim()}]}),p=a.text.trim();return p?{answer:p,provider:a.provider,model:a.model,usedAi:!0}:{answer:r.answer,usedAi:!1}}catch{return{answer:r.answer,usedAi:!1}}}import{existsSync as gt,mkdirSync as yt,readFileSync as ht,renameSync as kt,rmSync as bt,writeFileSync as vt}from"node:fs";import{join as ue}from"node:path";var At=720*60*1e3;function de(n){return ue(n.rootPath,".toolnet","context","memory-agent-conversation.json")}function E(n){return n.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function Mt(n){let e=E(n);return[/\btiếp tục\b/u,/\btiếp tục task\b/u,/\blúc nãy\b/u,/\btrước đó\b/u,/\btask trước\b/u,/\bprevious (?:task|session|work)\b/u,/\bcontinue\b/u,/\bresume\b/u,/\bcurrent task\b/u,/\bđang làm gì\b/u].some(t=>t.test(e))}function xt(n){if(Mt(n))return!1;let e=E(n),t=e.split(/\s+/u).filter(Boolean);return[/^(?:tại sao|vì sao|sao vậy)\b/u,/^(?:why|why so|why that)\b/u,/^(?:còn|thế|vậy|rồi sao|sau đó)\b/u,/^(?:what about|and what|then what)\b/u,/^(?:cái đó|việc đó|nó|phần đó)\b/u].some(r=>r.test(e))?!0:t.length<=5&&/\b(?:nó|đó|vậy|thế|that|it|this)\b/u.test(e)}function wt(n,e,t){let r=de(n);if(!gt(r))return null;try{let o=JSON.parse(ht(r,"utf8"));if(o.schema!=="toolnet.memory-conversation.v1"||o.version!==1||o.projectId!==n.id||!Array.isArray(o.focus))return null;let i=Date.parse(o.updatedAt);return!Number.isFinite(i)||e-i>t?null:o}catch{return null}}function St(n,e=8){let t=new Set,r=[];for(let o of n){let i=o.value.replace(/\s+/gu," ").trim();if(!i)continue;let a=[o.kind,E(i)].join(":");if(!t.has(a)&&(t.add(a),r.push({...o,value:i}),r.length>=e))break}return r}function Et(n,e){let t=de(n),r=ue(n.rootPath,".toolnet","context");yt(r,{recursive:!0,mode:448});let o=`${t}.${process.pid}.tmp`;try{vt(o,JSON.stringify(e,null,2)+`
|
|
45
|
-
`,{encoding:"utf8",mode:384}),kt(o,t)}finally{bt(o,{force:!0})}}function Ct(n){return n.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
|
|
46
|
-
`)}function _t(n,e){return n.priorFocus.find(t=>t.kind===e)?.value}function H(n){if(!n.usedPriorFocus||n.currentIntent!=="summary"||n.priorFocus.length===0)return null;let e=E(n.originalQuestion),t=/^(?:tại sao|vì sao|sao vậy|why|why so|why that)\b/u.test(e),r=/^(?:rồi sao|sau đó|tiếp thì sao|thế tiếp theo|then what|what next)\b/u.test(e),o=t?["decision","blocker","next_action","task","file"]:r?["next_action","todo","task","blocker","file","decision"]:["task","next_action","file","decision","blocker"],i={task:"Task li\xEAn quan",next_action:"Vi\u1EC7c ti\u1EBFp theo",file:"File li\xEAn quan",decision:"Quy\u1EBFt \u0111\u1ECBnh li\xEAn quan",blocker:"Blocker",todo:"TODO"},a=[];for(let p of o){let l=_t(n,p);if(l&&(a.push(`${i[p]??p}: ${l}.`),t&&a.length>=2||!t&&a.length>=3))break}return a.length===0?null:{answer:a.join(" "),intent:"summary",source:"conversation-focus"}}function It(n){let e=E(n);return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(e)}function me(n,e,t={}){let r=t.now??Date.now(),o=t.maxAgeMs??At,i=wt(n,r,o),a=!!(i&&i.focus.length>0&&xt(e)&&!It(e)),p=a&&i?[e.trim(),"","Previous ToolNet Memory conversation focus:",Ct(i),"","Use the compact focus only to resolve the current follow-up question.","Do not reconstruct or request raw session transcripts."].join(`
|
|
47
|
-
`):e.trim(),l=C(e),d=y(n,p,{maxFacts:8,maxChars:1800}).facts.map(b=>({kind:b.kind,value:b.value,source:b.source})),g=St(a&&i?[...d,...i.focus]:d);return Et(n,{schema:"toolnet.memory-conversation.v1",version:1,projectId:n.id,updatedAt:new Date(r).toISOString(),lastIntent:l,focus:g}),{question:p,originalQuestion:e,usedPriorFocus:a,previousIntent:i?.lastIntent,currentIntent:l,priorFocus:i?.focus??[],focusCount:g.length}}var Dr={question:pe.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:pe.enum(["ai","local"]).optional().describe("ai uses ToolNet Memory Agent with configured LLM fallback chain. local returns deterministic local memory only.")};async function fe(n,e){let t=me(n.project,e.question);if(e.mode==="local"){let o=H(t);if(o)return{answer:o.answer,mode:"local",usedAi:!1,source:o.source,intent:o.intent};let i=M(n.project,t.originalQuestion);return{answer:i.answer,mode:"local",usedAi:!1,source:i.source,intent:i.intent}}let r=await le(n.project,t.question);if(!r.usedAi){let o=H(t);if(o)return{answer:o.answer,mode:"ai",usedAi:!1,provider:r.provider,model:r.model}}return{answer:r.answer,mode:"ai",usedAi:r.usedAi,provider:r.provider,model:r.model}}var ge="RAW_TRANSCRIPT_MUST_NEVER_ENTER_CONTINUITY_CONTEXT_X1";function ye(n,e){he(n,JSON.stringify(e,null,2)+`
|
|
48
|
-
`,"utf8")}function Rt(n,e,t,r,o,i,a){return{continuity:{schema:"toolnet.handoff.v2",version:2,project:{id:n,name:e},source:{agent:t,nativeSessionId:`${t}-x1-source`,sessionKey:`${t}:${t}-x1-source`,sequence:42,reason:"checkpoint"},capturedAt:"2026-08-13T05:30:00.000Z",current:{phase:{id:"x1",title:"Cross-Agent Continuity E2E",status:"in_progress"},task:{id:"x1-cross-agent",title:r,status:"in_progress"},file:o},completed:{phases:["A1 OpenCode Adapter","A2 Agy Adapter","A3 Claude Code Adapter"],tasks:["Build canonical handoff schema","Build intelligent memory retrieval"]},remaining:{phases:["X1 Cross-Agent Continuity E2E"],tasks:[r],todos:[i]},nextAction:a,blockers:[],decisions:["Canonical handoff must override stale session state","Never replay raw transcripts during continuity recovery"],files:{current:o,recent:[o]},tests:{status:"passing",recent:["A1-A3 adapter tests passed"]},attention:[],progress:{phasesTotal:3,phasesCompleted:2,tasksTotal:4,tasksCompleted:3,blocked:0},stateDigest:"a".repeat(64)}}}async function L(n,e){return fe({project:n},{question:e,mode:"local"})}async function Ft(n,e){let t=Tt(k(Ot(),`toolnet-x1-${n}-${e}-`));try{let r=`x1-${n}-${e}`,o=`x1-${n}-to-${e}`,i={id:r,name:o,rootPath:t,createdAt:"2026-08-13T05:30:00.000Z",updatedAt:"2026-08-13T05:30:00.000Z",graphVersion:1,memoryVersion:1},a=k(t,".toolnet","work"),p=k(t,".toolnet","context"),l=k(t,".toolnet","sessions",n,"raw-session-x1");G(a,{recursive:!0}),G(p,{recursive:!0}),G(l,{recursive:!0});let f=`X1 ${n} to ${e} canonical continuity`,d=`src/x1/${n}-to-${e}.ts`,g=`Implement ${e} continuation step`,b=`Continue ${f} in ${d}`;ye(k(a,"handoff-latest.json"),Rt(r,o,n,f,d,g,b)),ye(k(p,"session-origin.json"),{version:1,projectId:r,agent:"stale-agent",nativeSessionId:"stale-session",updatedAt:"2026-01-01T00:00:00.000Z",currentTask:"STALE TASK MUST NOT WIN",currentPhase:"STALE PHASE",lastTouchedFile:"src/stale/old.ts",latestNextAction:"STALE NEXT ACTION"}),he(k(l,"events.jsonl"),JSON.stringify({text:ge})+`
|
|
49
|
-
`,"utf8");let be=y(i,"T\xF4i ph\u1EA3i l\xE0m g\xEC ti\u1EBFp?",{maxFacts:12,maxChars:3200}),D=await L(i,"Task hi\u1EC7n t\u1EA1i \u0111ang l\xE0m l\xE0 g\xEC?"),K=await L(i,"File hi\u1EC7n t\u1EA1i l\xE0 file n\xE0o?"),$=await L(i,"TODO c\xF2n l\u1EA1i l\xE0 g\xEC?"),U=await L(i,"T\xF4i ph\u1EA3i l\xE0m g\xEC ti\u1EBFp?"),ve=[D.answer,K.answer,$.answer,U.answer].join(`
|
|
50
|
-
`),j=[D,K,$,U],Y={canonicalHandoffPreferred:be.facts[0]?.source==="handoff",taskRecovered:D.answer.includes(f),fileRecovered:K.answer.includes(d),todoRecovered:$.answer.includes(g),nextActionRecovered:U.answer.includes(b),localModeOnly:j.every(A=>A.mode==="local"),noAiRequired:j.every(A=>A.usedAi===!1),rawTranscriptIsolated:!ve.includes(ge),compact:j.every(A=>A.answer.length<1600)};return{from:n,to:e,passed:Object.values(Y).every(Boolean),checks:Y}}finally{Pt(t,{recursive:!0,force:!0})}}async function ke(){let n=[["agy","codex"],["codex","opencode"],["opencode","claude"],["claude","kiro"],["kiro","cursor"],["cursor","copilot"],["copilot","grok"],["grok","agy"]],e=[];for(let[r,o]of n)e.push(await Ft(r,o));let t=e.filter(r=>r.passed).length;return{passed:t===e.length,total:e.length,passedCount:t,cases:e}}var m={reset:"\x1B[0m",green:"\x1B[32m",red:"\x1B[31m",cyan:"\x1B[36m",gray:"\x1B[90m",white:"\x1B[97m"};function Nt(n){return n?`${m.green}\u2713${m.reset}`:`${m.red}\u2717${m.reset}`}function Lt(n){let e=`${n.from.padEnd(8)} \u2192 ${n.to.padEnd(8)}`;if(console.log(`\u2502 ${Nt(n.passed)} ${e}`),!n.passed)for(let[t,r]of Object.entries(n.checks))r||console.log(`\u2502 ${m.red}\u2717${m.reset} ${t}`)}async function Dt(){console.log(""),console.log(`${m.cyan}\u25C7${m.reset} ${m.white}ToolNet Cross-Agent Continuity Certification${m.reset}`),console.log(`${m.gray}\u2502${m.reset}`);let n=await ke();for(let e of n.cases)Lt(e);if(console.log(`${m.gray}\u2502${m.reset}`),n.passed){console.log(`${m.green}\u25C6 PASS${m.reset} ${n.passedCount}/${n.total} cross-agent transitions`),console.log(`${m.green}\u2713${m.reset} canonical handoff`),console.log(`${m.green}\u2713${m.reset} memory_agent_ask`),console.log(`${m.green}\u2713${m.reset} task / file / TODO / next action`),console.log(`${m.green}\u2713${m.reset} raw transcripts isolated`),console.log(`${m.green}\u2713${m.reset} AI not required for direct continuity`);return}console.log(`${m.red}\u25C6 FAIL${m.reset} ${n.passedCount}/${n.total} cross-agent transitions`),process.exitCode=1}Dt().catch(n=>{console.error(n instanceof Error?n.message:String(n)),process.exitCode=1});
|
|
1
|
+
import{mkdirSync as j,mkdtempSync as St,rmSync as Ct,writeFileSync as re}from"node:fs";import{tmpdir as Mt}from"node:os";import{join as k}from"node:path";import{z as N}from"zod";import{existsSync as _e,readFileSync as Re}from"node:fs";import{join as $e}from"node:path";import{existsSync as ue,mkdirSync as _t,readFileSync as le,renameSync as Rt,writeFileSync as $t}from"node:fs";import{dirname as Nt,join as de}from"node:path";function fe(t){return de(t.rootPath,".toolnet","work","current.json")}function $(t){let e=fe(t);if(!ue(e))return null;try{let n=JSON.parse(le(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}import{existsSync as me,mkdirSync as Dt,readFileSync as pe,renameSync as Lt,writeFileSync as Kt}from"node:fs";import{dirname as qt,join as ge}from"node:path";function ke(t){return ge(t.rootPath,".toolnet","context","session-origin.json")}function P(t){let e=ke(t);if(!me(e))return null;try{let n=JSON.parse(pe(e,"utf8"));return n.version!==1||n.projectId!==t.id?null:n}catch{return null}}function ye(t){return t.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function M(t){let e=ye(t),n=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),r=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return n&&r?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}import{existsSync as Ae,mkdirSync as Pn,readFileSync as Te}from"node:fs";import{join as L}from"node:path";var be=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],w=class{scan(e){let n=[];for(let r of be){let o=new RegExp(r.regex.source,r.regex.flags);for(let s of e.matchAll(o))n.push({type:r.type,value:s[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var A=class{scanner=new w;sanitize(e){let n=e,r=this.scanner.scan(e),o=new Set;for(let s of r)o.add(s.type),n=n.split(s.value).join(`[REDACTED:${s.type}]`);return{text:n,redacted:r.length,secretTypes:[...o]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,o]of Object.entries(e)){let s=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(o)}return n}return e}};import{existsSync as ve,readFileSync as xe}from"node:fs";import{homedir as Se}from"node:os";import{join as Ce}from"node:path";function Me(t){let e=t.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
|
|
2
|
+
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function we(){let t=process.env.TOOLNET_GLOBAL_ENV??Ce(Se(),".config","toolnet-memory",".env");if(!ve(t))return;let e=xe(t,"utf8");for(let n of e.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let s=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=Me(r.slice(o+1)))}}we();var Sn=new A;function Fe(t){return L(t.rootPath,".toolnet","memory","checkpoints")}function Ee(t){return L(Fe(t),"latest.json")}function Ie(t){let e=Ee(t);if(!Ae(e))return null;try{let n=JSON.parse(Te(e,"utf8"));return n.schema!=="toolnet.memory.checkpoint.v1"||n.project.id!==t.id?null:n}catch{return null}}function K(t){return Ie(t)}var Pe={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,request:95,activity:90,phase:75,file:65,next_action:55,blocker:45},next_action:{next_action:100,todo:80,task:65,blocker:60,file:40},last_file:{file:100,task:65,next_action:40},blocker:{blocker:100,task:60,next_action:50,file:35},decision:{decision:100,rule:85,architecture:80,task:45,file:30},completed:{completed:100,progress:70,task:30},status:{progress:100,task:85,phase:75,blocker:65,next_action:60},summary:{task:100,request:98,activity:96,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,rule:54,architecture:53,fix:52,progress:50,test:45,goal:35}},Ne={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function Oe(t){return t.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function i(t,e){let n=e.value.replace(/\s+/g," ").trim();n&&t.push({...e,value:n,score:0})}function je(t){let e=$e(t.rootPath,".toolnet","work","handoff-latest.json");if(!_e(e))return null;try{let r=JSON.parse(Re(e,"utf8")).continuity;return r?.schema!=="toolnet.handoff.v2"||r.project.id!==t.id?null:r}catch{return null}}function De(t){let e=K(t);if(!e)return[];let n=[];e.request&&i(n,{kind:"request",value:e.request,source:"checkpoint"}),e.activity&&i(n,{kind:"activity",value:e.activity,source:"checkpoint"}),e.current.phase&&i(n,{kind:"phase",value:e.current.phase.title,source:"checkpoint"}),e.current.task&&i(n,{kind:"task",value:e.current.task.title,source:"checkpoint"});let r=e.files.active.at(-1);r&&i(n,{kind:"file",value:r,source:"checkpoint"});for(let o of e.nextActions)i(n,{kind:"next_action",value:o,source:"checkpoint"});for(let o of e.blockers)i(n,{kind:"blocker",value:o,source:"checkpoint"});for(let o of e.completed.tasks)i(n,{kind:"completed",value:o,source:"checkpoint"});for(let o of e.remaining.tasks)i(n,{kind:"todo",value:o,source:"checkpoint"});for(let o of e.durableFacts)i(n,{kind:o.kind,value:o.content,source:"checkpoint"});return n}function Le(t){let e=je(t);if(!e)return[];let n=[];i(n,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.request&&i(n,{kind:"request",value:e.request,source:"handoff"}),e.activity&&i(n,{kind:"activity",value:e.activity,source:"handoff"}),e.goal&&i(n,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&i(n,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&i(n,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&i(n,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&i(n,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let r of e.blockers)i(n,{kind:"blocker",value:r,source:"handoff"});for(let r of e.decisions)i(n,{kind:"decision",value:r,source:"handoff"});for(let r of e.completed.tasks)i(n,{kind:"completed",value:r,source:"handoff"});for(let r of e.remaining.todos)i(n,{kind:"todo",value:r,source:"handoff"});return i(n,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),i(n,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),n}function Ke(t){let e=P(t);if(!e)return[];let n=[];return i(n,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&i(n,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&i(n,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&i(n,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&i(n,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&i(n,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&i(n,{kind:"decision",value:e.latestDecision,source:"session-origin"}),n}function He(t){let e=$(t);if(!e)return[];let n=[];e.currentRequest&&i(n,{kind:"request",value:e.currentRequest,source:"work-state"}),e.currentActivity&&i(n,{kind:"activity",value:e.currentActivity,source:"work-state"}),e.goal&&i(n,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&i(n,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&i(n,{kind:"task",value:e.currentTask.title,source:"work-state"});let r=e.activeFiles?.at(-1)??e.filesTouched.at(-1);r&&i(n,{kind:"file",value:r,source:"work-state"});for(let o of e.nextActions.slice(0,5))i(n,{kind:"next_action",value:o,source:"work-state"});for(let o of e.blockers.slice(-5))i(n,{kind:"blocker",value:o,source:"work-state"});for(let o of e.decisions.slice(-5))i(n,{kind:"decision",value:o,source:"work-state"});for(let o of e.tasks.filter(s=>s.status==="completed").slice(-8))i(n,{kind:"completed",value:o.title,source:"work-state"});for(let o of e.tasks.filter(s=>s.status!=="completed"&&s.status!=="cancelled").slice(0,8))i(n,{kind:"todo",value:o.title,source:"work-state"});for(let o of e.tests.slice(-5))i(n,{kind:"test",value:o,source:"work-state"});return i(n,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),n}function qe(t,e){let n=Pe[t];return e.map((r,o)=>({...r,score:(n[r.kind]??10)+Ne[r.source]+Math.max(0,5-o*.01)}))}function ze(t){let e=new Map;for(let n of t){let r=`${n.kind}:${Oe(n.value)}`,o=e.get(r);(!o||n.score>o.score)&&e.set(r,n)}return[...e.values()]}function h(t,e,n={}){let r=M(e),o=[...De(t),...Le(t),...Ke(t),...He(t)],s=ze(qe(r,o)).sort((d,p)=>p.score-d.score),c=Math.max(1,n.maxFacts??12),l=Math.max(300,n.maxChars??3200),f=[],a=0;for(let d of s){if(f.length>=c)break;let p=d.kind.length+d.value.length+d.source.length+16;f.length>0&&a+p>l||(f.push(d),a+=p)}return{intent:r,facts:f,context:{project:{id:t.id,name:t.name},intent:r,selectedFacts:f.map(d=>({kind:d.kind,value:d.value,source:d.source}))},stats:{candidates:o.length,selected:f.length,chars:a}}}var H={previous_agent:"Agent tr\u01B0\u1EDBc",request:"Y\xEAu c\u1EA7u hi\u1EC7n t\u1EA1i",activity:"\u0110ang l\xE0m",goal:"M\u1EE5c ti\xEAu",phase:"Phase",task:"Task hi\u1EC7n t\u1EA1i",file:"File hi\u1EC7n t\u1EA1i",todo:"TODO",next_action:"Ti\u1EBFp theo",blocker:"Blocker",decision:"Quy\u1EBFt \u0111\u1ECBnh",rule:"Quy t\u1EAFc",architecture:"Ki\u1EBFn tr\xFAc",fix:"\u0110\xE3 s\u1EEDa",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},q=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],We={previous_agent:["previous_agent"],current_task:["request","activity","task","file","next_action"],next_action:["next_action","task","file","todo"],last_file:["file","task","next_action"],blocker:["blocker"],decision:["decision"],completed:["completed"],status:["progress","task","next_action","blocker"],summary:q};function Be(t){let e=t.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)}function Qe(t){let e=t.filter(r=>r.source==="handoff");if(e.length===0)return t;let n=t.filter(r=>r.source==="checkpoint"&&["rule","architecture","fix"].includes(r.kind));return[...e,...n]}function Ue(t){let e=new Set,n=[];for(let r of t){let o=`${r.kind}:${r.value.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}`;e.has(o)||(e.add(o),n.push(r))}return n}function z(t){switch(t){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function Ve(t,e){let n=[];for(let r of e){let o=t.filter(s=>s.kind===r).slice(0,z(r));for(let s of o)n.push(`${H[r]}: ${s.value}`)}return n.join(`
|
|
3
|
+
`)}function Ye(t,e){let n=We[e]??q,r=[];for(let o of n){let s=t.filter(c=>c.kind===o).slice(0,z(o));for(let c of s)r.push(`${H[o]}: ${c.value}`)}return r.join(`
|
|
4
|
+
`)}function W(t,e){let n=h(t,e,{maxFacts:32,maxChars:6400}),r=Ue(Qe(n.facts)),o=Be(e)?Ve(r,["todo","task","next_action","file"]):Ye(r,String(n.intent));return o?{intent:String(n.intent),answer:o,source:r[0]?.source??"none"}:{intent:String(n.intent),answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}import{existsSync as Je,mkdirSync as Ge,readFileSync as Xe,renameSync as Ze,rmSync as et,writeFileSync as tt}from"node:fs";import{join as B}from"node:path";var nt=720*60*1e3;function Q(t){return B(t.rootPath,".toolnet","context","memory-agent-conversation.json")}function C(t){return t.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function rt(t){let e=C(t);return[/\btiếp tục\b/u,/\btiếp tục task\b/u,/\blúc nãy\b/u,/\btrước đó\b/u,/\btask trước\b/u,/\bprevious (?:task|session|work)\b/u,/\bcontinue\b/u,/\bresume\b/u,/\bcurrent task\b/u,/\bđang làm gì\b/u].some(n=>n.test(e))}function ot(t){if(rt(t))return!1;let e=C(t),n=e.split(/\s+/u).filter(Boolean);return[/^(?:tại sao|vì sao|sao vậy)\b/u,/^(?:why|why so|why that)\b/u,/^(?:còn|thế|vậy|rồi sao|sau đó)\b/u,/^(?:what about|and what|then what)\b/u,/^(?:cái đó|việc đó|nó|phần đó)\b/u].some(r=>r.test(e))?!0:n.length<=5&&/\b(?:nó|đó|vậy|thế|that|it|this)\b/u.test(e)}function st(t,e,n){let r=Q(t);if(!Je(r))return null;try{let o=JSON.parse(Xe(r,"utf8"));if(o.schema!=="toolnet.memory-conversation.v1"||o.version!==1||o.projectId!==t.id||!Array.isArray(o.focus))return null;let s=Date.parse(o.updatedAt);return!Number.isFinite(s)||e-s>n?null:o}catch{return null}}function it(t,e=8){let n=new Set,r=[];for(let o of t){let s=o.value.replace(/\s+/gu," ").trim();if(!s)continue;let c=[o.kind,C(s)].join(":");if(!n.has(c)&&(n.add(c),r.push({...o,value:s}),r.length>=e))break}return r}function ct(t,e){let n=Q(t),r=B(t.rootPath,".toolnet","context");Ge(r,{recursive:!0,mode:448});let o=`${n}.${process.pid}.tmp`;try{tt(o,JSON.stringify(e,null,2)+`
|
|
5
|
+
`,{encoding:"utf8",mode:384}),Ze(o,n)}finally{et(o,{force:!0})}}function at(t){return t.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
|
|
6
|
+
`)}function ut(t,e){return t.priorFocus.find(n=>n.kind===e)?.value}function U(t){if(!t.usedPriorFocus||t.currentIntent!=="summary"||t.priorFocus.length===0)return null;let e=C(t.originalQuestion),n=/^(?:tại sao|vì sao|sao vậy|why|why so|why that)\b/u.test(e),r=/^(?:rồi sao|sau đó|tiếp thì sao|thế tiếp theo|then what|what next)\b/u.test(e),o=n?["decision","blocker","next_action","task","file"]:r?["next_action","todo","task","blocker","file","decision"]:["task","next_action","file","decision","blocker"],s={task:"Task li\xEAn quan",next_action:"Vi\u1EC7c ti\u1EBFp theo",file:"File li\xEAn quan",decision:"Quy\u1EBFt \u0111\u1ECBnh li\xEAn quan",blocker:"Blocker",todo:"TODO"},c=[];for(let l of o){let f=ut(t,l);if(f&&(c.push(`${s[l]??l}: ${f}.`),n&&c.length>=2||!n&&c.length>=3))break}return c.length===0?null:{answer:c.join(" "),intent:"summary",source:"conversation-focus"}}function lt(t){let e=C(t);return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(e)}function V(t,e,n={}){let r=n.now??Date.now(),o=n.maxAgeMs??nt,s=st(t,r,o),c=!!(s&&s.focus.length>0&&ot(e)&&!lt(e)),l=c&&s?[e.trim(),"","Previous ToolNet Memory conversation focus:",at(s),"","Use the compact focus only to resolve the current follow-up question.","Do not reconstruct or request raw session transcripts."].join(`
|
|
7
|
+
`):e.trim(),f=M(e),d=h(t,l,{maxFacts:8,maxChars:1800}).facts.map(y=>({kind:y.kind,value:y.value,source:y.source})),p=it(c&&s?[...d,...s.focus]:d);return ct(t,{schema:"toolnet.memory-conversation.v1",version:1,projectId:t.id,updatedAt:new Date(r).toISOString(),lastIntent:f,focus:p}),{question:l,originalQuestion:e,usedPriorFocus:c,previousIntent:s?.lastIntent,currentIntent:f,priorFocus:s?.focus??[],focusCount:p.length}}import{existsSync as dt,readFileSync as ft}from"node:fs";import{join as mt}from"node:path";function g(t){return!!t?.trim()}function Y(t){let e=[],n=[],r=100;g(t.goal)||g(t.request)||(e.push("goal_or_request"),r-=20),g(t.activity)||g(t.current.task?.title)||g(t.current.phase?.title)||(e.push("current_work"),r-=25),g(t.nextAction)||g(t.remaining.todos[0])||(e.push("next_action"),r-=25),t.tests.status!=="unknown"||t.tests.recent.length>0||(t.tests.checks?.length??0)>0||(t.evidence?.commands.length??0)>0||(t.evidence?.references.length??0)>0||(e.push("evidence"),r-=20),g(t.files.current)||t.files.recent.length>0||(t.files.active?.length??0)>0||(t.files.modified?.length??0)>0||(t.files.created?.length??0)>0||(e.push("files"),r-=10),t.tests.status==="failing"&&n.push("tests_failing"),t.blockers.length>0&&n.push("active_blockers"),r=Math.max(0,Math.min(100,r));let a=e.includes("current_work")||e.includes("next_action"),d;return r>=80&&!a?d="high":r>=50?d="medium":d="low",{confidence:d,score:r,missingContext:e,warnings:n}}var J={compact:{completed:3,evidence:3,files:5,blockers:2,maxChars:1800},normal:{completed:10,evidence:10,files:15,blockers:5,maxChars:4200},benchmark:{completed:30,evidence:30,files:40,blockers:10,maxChars:1e4}};function b(t){let e=new Set,n=[];for(let r of t){let o=r?.replace(/\s+/gu," ").trim();if(!o)continue;let s=o.normalize("NFKC").toLowerCase();e.has(s)||(e.add(s),n.push(o))}return n}function v(t){return t.length>0?t.map(e=>`- ${e}`).join(`
|
|
8
|
+
`):"- none"}function pt(t,e){return t.length<=e?t:[t.slice(0,e).trimEnd(),"","[Structured handoff truncated]"].join(`
|
|
9
|
+
`)}function G(t,e){if(e)return e;let n=t.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/\bbenchmark\b/u.test(n)||/\bdeep handoff\b/u.test(n)||/\bfull handoff\b/u.test(n)||/\btakeover\b/u.test(n)||/\btake over\b/u.test(n)||/tiếp quản/u.test(n)||/bằng chứng đầy đủ/u.test(n)||/evidence.*(?:file|test|command)/u.test(n)?"benchmark":/\bcompact\b/u.test(n)||/\bbrief\b/u.test(n)||/ngắn gọn/u.test(n)||/tóm tắt ngắn/u.test(n)?"compact":"normal"}function gt(t,e="normal"){let n=J[e],r=b([`Source agent: ${t.source.agent}`,`Captured: ${t.capturedAt}`,t.goal?`Goal: ${t.goal}`:void 0,t.request?`Request: ${t.request}`:void 0,t.activity?`Activity: ${t.activity}`:void 0,t.current.phase?`Phase: ${t.current.phase.title} [${t.current.phase.status}]`:void 0,t.current.task?`Task: ${t.current.task.title} [${t.current.task.status}]`:void 0,t.current.file?`Current file: ${t.current.file}`:void 0,`Progress: ${JSON.stringify(t.progress)}`]),o=b([...t.completed.phases.map(a=>`Phase: ${a}`),...t.completed.tasks.map(a=>`Task: ${a}`)]).slice(0,n.completed),s=b([`Tests status: ${t.tests.status}`,...t.tests.recent.map(a=>`Test: ${a}`),...(t.tests.checks??[]).map(a=>`Check [${a.status}] ${a.kind}: ${a.command}`),...(t.evidence?.commands??[]).map(a=>`Command: ${a}`),...(t.evidence?.references??[]).map(a=>`Reference: ${a}`),...t.decisions.map(a=>`Decision: ${a}`),...t.attention.map(a=>`Attention: ${a}`)]).slice(0,n.evidence),c=b([t.files.current,...(t.files.active??[]).map(a=>`Active: ${a}`),...(t.files.modified??[]).map(a=>`Modified: ${a}`),...(t.files.created??[]).map(a=>`Created: ${a}`),...(t.files.deleted??[]).map(a=>`Deleted: ${a}`),...t.files.recent.map(a=>`Recent: ${a}`)]).slice(0,n.files),l=b(t.blockers).slice(0,n.blockers),f=b([t.nextAction,t.nextAction?void 0:t.remaining.todos[0]]).slice(0,1);return{currentState:r,completed:o,evidence:s,filesTouched:c,blockers:l,nextAction:f}}function kt(t,e,n){return[`HANDOFF_DETAIL: ${e}`,`CONTINUITY_CONFIDENCE: ${n.confidence}`,`QUALITY_SCORE: ${n.score}`,`MISSING_CONTEXT: ${n.missingContext.length>0?n.missingContext.join(", "):"none"}`,`QUALITY_WARNINGS: ${n.warnings.length>0?n.warnings.join(", "):"none"}`,"","CURRENT_STATE",v(t.currentState),"","COMPLETED",v(t.completed),"","EVIDENCE",v(t.evidence),"","FILES_TOUCHED",v(t.filesTouched),"","BLOCKERS",v(t.blockers),"","NEXT_ACTION",v(t.nextAction)].join(`
|
|
10
|
+
`)}function X(t,e="normal"){let n=mt(t.rootPath,".toolnet","work","handoff-latest.json");if(!dt(n))return null;try{let o=JSON.parse(ft(n,"utf8")).continuity;if(!o||o.schema!=="toolnet.handoff.v2"||o.version!==2)return null;let s=gt(o,e),c=Y(o),l=pt(kt(s,e,c),J[e].maxChars);return{detail:e,data:s,quality:c,text:l}}catch{return null}}function yt(t){return t.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}var ht=[/\bhandoff\b/u,/\bcontinuity\b/u,/\bcontinue\b/u,/\bresume\b/u,/\btakeover\b/u,/\btake over\b/u,/tiếp tục/u,/tiếp quản/u,/bàn giao/u,/dừng ở đâu/u,/đang làm gì/u],bt=[/\bcurrent state\b/u,/\bcurrent task\b/u,/\bevidence\b/u,/\breport locations?\b/u,/\bfiles?\b/u,/\burls?\b/u,/\bassets?\b/u,/\btests?\b/u,/\bcommands?\b/u,/\bblockers?\b/u,/\bnext actions?\b/u,/trạng thái hiện tại/u,/task hiện tại/u,/bằng chứng/u,/vị trí báo cáo/u,/file/u,/url/u,/blocker/u,/việc tiếp theo/u,/bước tiếp theo/u],vt=[/\bsummarize\b/u,/\bsummary\b/u,/\bfull state\b/u,/\bfull context\b/u,/tóm tắt/u,/đầy đủ/u,/toàn bộ trạng thái/u];function xt(t){let e=0;for(let n of bt)n.test(t)&&(e+=1);return e}function Z(t,e){let n=yt(t);if(/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(n)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(n)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(n))return!1;if(e==="summary"||e==="status")return!0;if(!n)return!1;let o=ht.some(l=>l.test(n)),s=vt.some(l=>l.test(n)),c=xt(n);return!!(o&&c>=1||s&&c>=2||c>=4)}var lr={question:N.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:N.enum(["local"]).optional().describe("Returns deterministic local memory only. No external AI is used."),detail:N.enum(["compact","normal","benchmark"]).optional().describe("Handoff detail level. compact=minimal, normal=standard, benchmark=deep evidence/files/tests for agent takeover.")};function ee(t,e,n,r,o){if(!Z(e,n))return{answer:r};let s=G(e,o),c=X(t.project,s);return c?{answer:c.text,handoff:c.data,detail:c.detail,confidence:c.quality.confidence,missingContext:c.quality.missingContext,quality:c.quality}:{answer:r}}async function O(t,e){let n=V(t.project,e.question),r=U(n);if(r)return{...ee(t,n.originalQuestion,String(r.intent),r.answer,e.detail),mode:"local",usedAi:!1,source:r.source,intent:r.intent};let o=W(t.project,n.originalQuestion),s=ee(t,n.originalQuestion,String(o.intent),o.answer,e.detail);return"handoff"in s?{...s,mode:"local",usedAi:!1,source:o.source,intent:o.intent,routing:"deterministic-handoff"}:{...s,mode:"local",usedAi:!1,source:o.source,intent:o.intent}}var te="RAW_TRANSCRIPT_MUST_NEVER_ENTER_CONTINUITY_CONTEXT_X1";function ne(t,e){re(t,JSON.stringify(e,null,2)+`
|
|
11
|
+
`,"utf8")}function wt(t,e,n,r,o,s,c,l){return{continuity:{schema:"toolnet.handoff.v2",version:2,project:{id:t,name:e},source:{agent:n,nativeSessionId:`${n}-x1-source`,sessionKey:`${n}:${n}-x1-source`,sequence:42,reason:"checkpoint"},capturedAt:"2026-08-13T05:30:00.000Z",goal:`Continue ${e} safely across agents`,request:`Recover ${o} with exact evidence and next action`,activity:`Preparing ${r} takeover from ${n}`,current:{phase:{id:"x1",title:"Cross-Agent Continuity E2E",status:"in_progress"},task:{id:"x1-cross-agent",title:o,status:"in_progress"},file:s},completed:{phases:["A1 OpenCode Adapter","A2 Agy Adapter","A3 Claude Code Adapter"],tasks:["Build canonical handoff schema","Build intelligent memory retrieval"]},remaining:{phases:["X1 Cross-Agent Continuity E2E"],tasks:[o],todos:[c]},nextAction:l,blockers:[],decisions:["Canonical handoff must override stale session state","Never replay raw transcripts during continuity recovery"],files:{current:s,recent:[s]},tests:{status:"passing",recent:["A1-A3 adapter tests passed"],checks:[{kind:"test",status:"passed",command:`node scripts/${n}-to-${r}-verify.mjs`}]},evidence:{commands:[`node scripts/${n}-to-${r}-verify.mjs`],references:[`https://example.test/${n}/${r}/continuity-report`]},attention:[],progress:{phasesTotal:3,phasesCompleted:2,tasksTotal:4,tasksCompleted:3,blocked:0},stateDigest:"a".repeat(64)}}}async function T(t,e){return O({project:t},{question:e,mode:"local"})}async function At(t,e){let n=St(k(Mt(),`toolnet-x1-${t}-${e}-`));try{let r=`x1-${t}-${e}`,o=`x1-${t}-to-${e}`,s={id:r,name:o,rootPath:n,createdAt:"2026-08-13T05:30:00.000Z",updatedAt:"2026-08-13T05:30:00.000Z",graphVersion:1,memoryVersion:1},c=k(n,".toolnet","work"),l=k(n,".toolnet","context"),f=k(n,".toolnet","sessions",t,"raw-session-x1");j(c,{recursive:!0}),j(l,{recursive:!0}),j(f,{recursive:!0});let a=`X1 ${t} to ${e} canonical continuity`,d=`src/x1/${t}-to-${e}.ts`,p=`Implement ${e} continuation step`,y=`Continue ${a} in ${d}`;ne(k(c,"handoff-latest.json"),wt(r,o,t,e,a,d,p,y)),ne(k(l,"session-origin.json"),{version:1,projectId:r,agent:"stale-agent",nativeSessionId:"stale-session",updatedAt:"2026-01-01T00:00:00.000Z",currentTask:"STALE TASK MUST NOT WIN",currentPhase:"STALE PHASE",lastTouchedFile:"src/stale/old.ts",latestNextAction:"STALE NEXT ACTION"}),re(k(f,"events.jsonl"),JSON.stringify({text:te})+`
|
|
12
|
+
`,"utf8");let se=h(s,"T\xF4i ph\u1EA3i l\xE0m g\xEC ti\u1EBFp?",{maxFacts:12,maxChars:3200}),F=await T(s,"Task hi\u1EC7n t\u1EA1i \u0111ang l\xE0m l\xE0 g\xEC?"),E=await T(s,"File hi\u1EC7n t\u1EA1i l\xE0 file n\xE0o?"),I=await T(s,"TODO c\xF2n l\u1EA1i l\xE0 g\xEC?"),_=await T(s,"T\xF4i ph\u1EA3i l\xE0m g\xEC ti\u1EBFp?"),m=await O({project:s},{mode:"local",detail:"benchmark",question:"Summarize current state, completed work, evidence, files, tests, blockers and exact next action for benchmark agent takeover."}),x=m,ie=`node scripts/${t}-to-${e}-verify.mjs`,ce=`https://example.test/${t}/${e}/continuity-report`,ae=[F.answer,E.answer,I.answer,_.answer,m.answer].join(`
|
|
13
|
+
`),R=[F,E,I,_],D={canonicalHandoffPreferred:se.facts[0]?.source==="handoff",taskRecovered:F.answer.includes(a),fileRecovered:E.answer.includes(d),todoRecovered:I.answer.includes(p),nextActionRecovered:_.answer.includes(y),localModeOnly:R.every(S=>S.mode==="local"),noAiRequired:R.every(S=>S.usedAi===!1),rawTranscriptIsolated:!ae.includes(te),compact:R.every(S=>S.answer.length<1600),structuredTakeoverRecovered:m.answer.includes("CURRENT_STATE")&&m.answer.includes("COMPLETED")&&m.answer.includes("EVIDENCE")&&m.answer.includes("FILES_TOUCHED")&&m.answer.includes("BLOCKERS")&&m.answer.includes("NEXT_ACTION"),benchmarkDetailRecovered:x.detail==="benchmark"&&m.answer.includes("HANDOFF_DETAIL: benchmark"),highConfidence:x.confidence==="high"&&Array.isArray(x.missingContext)&&x.missingContext.length===0,evidenceRecovered:m.answer.includes(ie)&&m.answer.includes(ce),deterministicTakeover:m.usedAi===!1&&x.routing==="deterministic-handoff"};return{from:t,to:e,passed:Object.values(D).every(Boolean),checks:D}}finally{Ct(n,{recursive:!0,force:!0})}}async function oe(){let t=[["agy","codex"],["codex","opencode"],["opencode","claude"],["claude","kiro"],["kiro","cursor"],["cursor","copilot"],["copilot","grok"],["grok","agy"]],e=[];for(let[r,o]of t)e.push(await At(r,o));let n=e.filter(r=>r.passed).length;return{passed:n===e.length,total:e.length,passedCount:n,cases:e}}var u={reset:"\x1B[0m",green:"\x1B[32m",red:"\x1B[31m",cyan:"\x1B[36m",gray:"\x1B[90m",white:"\x1B[97m"};function Tt(t){return t?`${u.green}\u2713${u.reset}`:`${u.red}\u2717${u.reset}`}function Ft(t){let e=`${t.from.padEnd(8)} \u2192 ${t.to.padEnd(8)}`;if(console.log(`\u2502 ${Tt(t.passed)} ${e}`),!t.passed)for(let[n,r]of Object.entries(t.checks))r||console.log(`\u2502 ${u.red}\u2717${u.reset} ${n}`)}async function Et(){console.log(""),console.log(`${u.cyan}\u25C7${u.reset} ${u.white}ToolNet Cross-Agent Continuity Certification${u.reset}`),console.log(`${u.gray}\u2502${u.reset}`);let t=await oe();for(let e of t.cases)Ft(e);if(console.log(`${u.gray}\u2502${u.reset}`),t.passed){console.log(`${u.green}\u25C6 PASS${u.reset} ${t.passedCount}/${t.total} cross-agent transitions`),console.log(`${u.green}\u2713${u.reset} canonical handoff`),console.log(`${u.green}\u2713${u.reset} memory_agent_ask`),console.log(`${u.green}\u2713${u.reset} task / file / TODO / next action`),console.log(`${u.green}\u2713${u.reset} raw transcripts isolated`),console.log(`${u.green}\u2713${u.reset} AI not required for direct continuity`);return}console.log(`${u.red}\u25C6 FAIL${u.reset} ${t.passedCount}/${t.total} cross-agent transitions`),process.exitCode=1}Et().catch(t=>{console.error(t instanceof Error?t.message:String(t)),process.exitCode=1});
|