@kitelev/exocortex-cli 16.96.8 → 16.96.9

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.
Files changed (2) hide show
  1. package/dist/index.js +3 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // @kitelev/exocortex-cli v16.96.8
2
+ // @kitelev/exocortex-cli v16.96.9
3
3
  // CLI tool for Exocortex knowledge management system - SPARQL queries, task management, and more
4
4
  // License: MIT
5
5
 
@@ -460,7 +460,7 @@ To resolve:
460
460
  path = ${e}
461
461
  url = ${t}
462
462
  `;return{content:n+i+s,added:!0}}a(Tz,"appendGitmodulesEntry");function Az(n,e){let t=n.split(/\r?\n/),r=[],i=!1,s=new RegExp(`^\\[submodule\\s+"${jE(e)}"\\]\\s*$`);for(let l of t){if(i){if(/^\[.+\]\s*$/.test(l)){i=!1,r.push(l);continue}continue}if(s.test(l)){i=!0;continue}r.push(l)}let o=[],c=!1;for(let l of r){let u=l.trim().length===0;u&&c||(o.push(l),c=u)}return o.join(`
463
- `)}a(Az,"stripGitmodulesEntry")});var ld=w($E=>{"use strict";Object.defineProperty($E,"__esModule",{value:!0});$E.gitBlobSha=Iz;async function Iz(n,e){let t=new TextEncoder,r=typeof n=="string"?t.encode(n):n,i=t.encode(`blob ${r.byteLength}\0`),s=new Uint8Array(i.byteLength+r.byteLength);return s.set(i,0),s.set(r,i.byteLength),e(s)}a(Iz,"gitBlobSha")});var UE=w(ay=>{"use strict";Object.defineProperty(ay,"__esModule",{value:!0});ay.extractAssetUid=L3;ay.detectChanges=Rz;var xz=ld();function L3(n){let e=/^---\r?\n([\s\S]*?)\r?\n---(?=\r?\n|$)/.exec(n);if(!e)return;let t=/^exo__Asset_uid:[ \t]*["']?([^\s"']+)["']?[ \t]*$/m.exec(e[1]);return t?t[1]:void 0}a(L3,"extractAssetUid");async function Rz(n){let{localFiles:e,watermark:t,actualBaseTreeSha:r,sha1:i}=n;if(t===null)return{kind:"full-conflict",reason:"first-sync"};if(r===null)return{kind:"full-conflict",reason:"base-mismatch",detail:`watermark commit ${t.lastSyncedSha} not resolvable on remote`};if(r!==t.rootTreeSha)return{kind:"full-conflict",reason:"base-mismatch",detail:`stored root tree ${t.rootTreeSha} != actual ${r} at ${t.lastSyncedSha}`};let s=[],o=new Map;for(let[T,I]of e){let A=await(0,xz.gitBlobSha)(I,i);o.set(T,A),s.push({path:T,blobSha:A,uid:typeof I=="string"?L3(I):void 0})}let c=[],l=[],u=[],f=[],d=new Map;for(let T of s){if(T.uid===void 0)continue;let I=d.get(T.uid)??[];I.push(T.path),d.set(T.uid,I)}let h=new Map;for(let T of t.files){if(T.uid===void 0)continue;let I=h.get(T.uid)??[];I.push(T.path),h.set(T.uid,I)}let p=new Set;for(let[T,I]of d)I.length>1&&p.add(T);for(let[T,I]of h)I.length>1&&p.add(T);for(let T of[...p].sort()){let I=d.get(T)??[],A=I.length>1?`on disk (${I.join(", ")})`:`in the sync base (${(h.get(T)??[]).join(", ")})`;f.push(`duplicate uid ${T} ${A} \u2014 uid identity suppressed for the group; every path matched by path identity (#3477)`)}let y=new Map,g=[];for(let T of t.files)T.uid!==void 0&&!p.has(T.uid)?y.set(T.uid,T):g.push(T);let v=[],_=new Set;for(let T of s){let I=T.uid!==void 0&&!p.has(T.uid)?y.get(T.uid):void 0;T.uid!==void 0&&I!==void 0?(_.add(T.uid),(I.blobSha!==T.blobSha||I.path!==T.path)&&l.push({path:T.path,uid:T.uid,blobSha:T.blobSha,...I.path!==T.path?{basePath:I.path}:{}})):v.push(T)}let S=new Map;for(let T of g)S.set(T.path,T);for(let[T,I]of y)_.has(T)||S.set(I.path,I);for(let T of v){let I=S.get(T.path);I!==void 0?(S.delete(T.path),I.blobSha!==T.blobSha&&l.push({path:T.path,uid:T.uid,blobSha:T.blobSha})):c.push({path:T.path,uid:T.uid,blobSha:T.blobSha})}for(let T of S.values())u.push({path:T.path,uid:T.uid,blobSha:T.blobSha});return{kind:"changes",added:c,modified:l,deleted:u,warnings:f,diskBlobShas:o,duplicateUids:p}}a(Rz,"detectChanges")});var fd=w(wc=>{"use strict";Object.defineProperty(wc,"__esModule",{value:!0});wc.getHeadSha=Cz;wc.getCommitInfo=Oz;wc.getTree=Dz;wc.getBlobText=Fz;wc.getBlobBytes=Lz;var N3=il(),Pz="https://api.github.com";function ud(n){return(n??Pz).replace(/\/$/,"")}a(ud,"api");function Sc(n){return n!==null&&typeof n=="object"?n:void 0}a(Sc,"asRecord");function Ds(n,e){let r=Sc(n)?.[e];return typeof r=="string"?r:void 0}a(Ds,"readString");async function Cz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/refs/heads/${encodeURIComponent(r)}`}),o=Ds(Sc(s?.json)?.object,"sha");if(typeof o!="string"||o.length===0)throw new Error(`ExoSync: missing object.sha for ref heads/${r}`);return o}a(Cz,"getHeadSha");async function Oz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/commits/${encodeURIComponent(r)}`}),o=Sc(s?.json),c=Ds(o,"sha"),l=Ds(o?.tree,"sha");if(!c||!l)throw new Error(`ExoSync: malformed commit response for ${r}`);let u=o?.parents,f=Array.isArray(u)?u.map(d=>Ds(d,"sha")).filter(d=>typeof d=="string"):[];return{sha:c,treeSha:l,parents:f}}a(Oz,"getCommitInfo");async function Dz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/trees/${encodeURIComponent(r)}?recursive=1`}),o=Sc(s?.json);if(o?.truncated===!0)throw new Error(`ExoSync: tree ${r} is truncated by GitHub (repo too large for recursive listing) \u2014 refusing to diff`);let c=o?.tree;if(!Array.isArray(c))throw new Error(`ExoSync: malformed tree response for ${r}`);let l=[];for(let u of c){let f=Sc(u);if(f?.type!=="blob")continue;let d=Ds(f,"path"),h=Ds(f,"sha"),p=typeof f.size=="number"?f.size:void 0;d&&h&&l.push({path:d,blobSha:h,...p!==void 0?{size:p}:{}})}return l}a(Dz,"getTree");async function Fz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/blobs/${encodeURIComponent(r)}`}),o=Sc(s?.json),c=Ds(o,"content");if(typeof c!="string")throw new Error(`ExoSync: malformed blob response for ${r}`);return Ds(o,"encoding")==="utf-8"?c:(0,N3.base64ToUtf8)(c)}a(Fz,"getBlobText");async function Lz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/blobs/${encodeURIComponent(r)}`}),o=Sc(s?.json),c=Ds(o,"content");if(typeof c!="string")throw new Error(`ExoSync: malformed blob response for ${r}`);return Ds(o,"encoding")==="utf-8"?new TextEncoder().encode(c):(0,N3.base64ToBytes)(c)}a(Lz,"getBlobBytes")});var cy=w(BE=>{"use strict";Object.defineProperty(BE,"__esModule",{value:!0});BE.isAuthError=Nz;function Nz(n){let e=n instanceof Error?n.message:String(n);return/HTTP 401/.test(e)?!0:/HTTP 403/.test(e)&&!/rate limit/i.test(e)&&!/abuse detection/i.test(e)}a(Nz,"isAuthError")});var uy=w(ly=>{"use strict";Object.defineProperty(ly,"__esModule",{value:!0});ly.scanForSecrets=kz;ly.redactSecrets=Mz;var k3=[{kind:"github-token",re:/gh[pousr]_[A-Za-z0-9_]{36,}/},{kind:"github-fine-grained-token",re:/github_pat_[A-Za-z0-9_]{22,}_[A-Za-z0-9_]{59,}/},{kind:"private-key",re:/-----BEGIN [A-Z ]*PRIVATE KEY-----/}];function kz(n){let e=[];for(let[t,r]of n)for(let{kind:i,re:s}of k3)s.test(r)&&e.push({path:t,kind:i});return e}a(kz,"scanForSecrets");function Mz(n){let e=n;for(let{kind:t,re:r}of k3)e=e.replace(new RegExp(r.source,"g"),`[REDACTED:${t}]`);return e}a(Mz,"redactSecrets")});var dy=w(fy=>{"use strict";Object.defineProperty(fy,"__esModule",{value:!0});fy.isRateLimitError=M3;fy.withRateLimitBackoff=$z;function M3(n){let e=n instanceof Error?n.message:String(n);return/HTTP 429/.test(e)?!0:/HTTP 403/.test(e)&&(/rate limit/i.test(e)||/abuse detection/i.test(e))}a(M3,"isRateLimitError");var jz=a(n=>new Promise(e=>setTimeout(e,n)),"defaultSleep");function $z(n,e={}){let t=e.maxRetries??3,r=e.baseDelayMs??1e3,i=e.sleep??jz,s=e.random??Math.random;return async o=>{let c=0;for(;;)try{return await n(o)}catch(l){if(!M3(l)||c>=t)throw l;let u=r*2**c*(1+s());c++,await i(u)}}}a($z,"withRateLimitBackoff")});var hy=w(Io=>{"use strict";Object.defineProperty(Io,"__esModule",{value:!0});Io.DEFAULT_MAX_FILE_BYTES=Io.InMemoryQuarantineStore=void 0;Io.contentEquals=Uz;Io.isSyncablePath=Bz;Io.isFileSpaceSyncablePath=Vz;function Uz(n,e){if(n===void 0||e===void 0||typeof n=="string"&&typeof e=="string")return n===e;if(typeof n=="string"||typeof e=="string"||n.byteLength!==e.byteLength)return!1;for(let t=0;t<n.byteLength;t++)if(n[t]!==e[t])return!1;return!0}a(Uz,"contentEquals");var VE=class{static{a(this,"InMemoryQuarantineStore")}constructor(){this.entries=[]}async quarantine(e){this.entries.push(e)}};Io.InMemoryQuarantineStore=VE;function Bz(n){return n.endsWith(".md")&&!n.includes(".local.")&&!n.includes(".conflict.")}a(Bz,"isSyncablePath");function Vz(n){return!n.includes(".local.")&&!n.includes(".conflict.")}a(Vz,"isFileSpaceSyncablePath");Io.DEFAULT_MAX_FILE_BYTES=30*1024*1024});var WE=w(Fs=>{"use strict";Object.defineProperty(Fs,"__esModule",{value:!0});Fs.SyncEngine=Fs.DEFAULT_MAX_PUSH_RETRIES=void 0;Fs.isNonFastForwardError=V3;Fs.orderChildrenFirst=Yz;var Gz=sy(),Ft=fd(),vc=UE(),qz=il(),dd=ld(),Wz=cy(),zz=uy(),Hz=dy(),da=hy();Fs.DEFAULT_MAX_PUSH_RETRIES=3;function Kz(n){try{return new TextDecoder("utf-8",{fatal:!0}).decode(n)}catch{return null}}a(Kz,"decodeUtf8Strict");function Qz(n){return typeof n=="string"?n:{base64:(0,qz.bytesToBase64)(n)}}a(Qz,"toCommitContent");async function j3(n,e){if(n.readBinary===void 0)throw new Error("LocalFilesPort.readBinary is required for file-mode sync (Phase C)");return n.readBinary(e)}a(j3,"readBinaryStrict");async function Xz(n,e,t){if(n.writeBinary===void 0)throw new Error("LocalFilesPort.writeBinary is required for file-mode sync (Phase C)");return n.writeBinary(e,t)}a(Xz,"writeBinaryStrict");function $3(n){return n.length===0||n.startsWith("/")||n.includes("\\")?!1:n.split("/").every(e=>e.length>0&&e!=="."&&e!=="..")}a($3,"isSafeRepoRelativePath");function V3(n){let e=n instanceof Error?n.message:String(n);return/HTTP 422/.test(e)&&/git\/refs/.test(e)||/ref update mismatch/.test(e)||/HTTP 422/.test(e)&&/git\/trees/.test(e)&&/BadObjectState/.test(e)}a(V3,"isNonFastForwardError");function Yz(n){let e=a(t=>t.split("/").filter(r=>r.length>0).length,"depth");return[...n].sort((t,r)=>e(r.localPath)-e(t.localPath))}a(Yz,"orderChildrenFirst");function U3(n,e){let t=new Map(n.map(o=>[o.path,o])),r=new Set,i=[];for(let o of e){r.add(o.path);let c=t.get(o.path);(c===void 0||c.blobSha!==o.blobSha)&&i.push(o)}let s=n.filter(o=>!r.has(o.path));return{changed:i,deleted:s}}a(U3,"diffTrees");function cu(n){return n instanceof Error?n.message:String(n)}a(cu,"errMsg");function Jz(n,e,t){if(t.size===0)return n;let r=new Map(e.files.map(o=>[o.path,o])),i=new Set(n.map(o=>o.path)),s=[];for(let o of n){if(!t.has(o.path)){s.push(o);continue}let c=r.get(o.path);c!==void 0&&s.push(c)}for(let o of t){if(i.has(o))continue;let c=r.get(o);c!==void 0&&s.push(c)}return s}a(Jz,"applyWatermarkPins");var GE={mergedFiles:new Map,mergedWrites:[],quarantineEntries:[],resolvedQuarantineEntries:[],mergedCount:0,mergedPaths:[],warnings:[]};function B3(n){return new Map(n.map(e=>[e.path,e.blobSha]))}a(B3,"treeByPath");function py(n){return[...n.quarantineEntries.map(e=>e.path),...n.resolvedQuarantineEntries.map(e=>e.path)]}a(py,"quarantinedPathsOf");var qE=class{static{a(this,"SyncEngine")}constructor(e){this.opInProgress=!1,this.deps=e,this.transport=(0,Hz.withRateLimitBackoff)(e.transport,e.backoff)}busyResult(e){return{repoKey:e.repoKey,status:"busy",pulledCount:0,pushedCount:0,mergedCount:0,quarantinedCount:0,warnings:[],deferredDeletes:[],detail:"another sync operation is in progress (D11 guard) \u2014 retry after it finishes"}}modeOps(e){let t=e.spaceKind==="file",r=t?da.isFileSpaceSyncablePath:da.isSyncablePath,i=this.deps.maxFileBytes??da.DEFAULT_MAX_FILE_BYTES;return{fileMode:t,syncable:r,treeFilter:a(s=>r(s.path)&&(!t||s.size===void 0||s.size<=i),"treeFilter")}}async buildFileModeFirstSyncBase(e,t,r,i){let s=await(0,Ft.getHeadSha)(this.transport,e.owner,e.repo,e.branch,this.deps.baseURL),o=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,s,this.deps.baseURL),c=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,o.treeSha,this.deps.baseURL)).filter(r.treeFilter),l=[];for(let u of c){let f=t.get(u.path);f!==void 0&&await(0,dd.gitBlobSha)(f,this.deps.sha1)===u.blobSha&&l.push({path:u.path,blobSha:u.blobSha})}return i.push(`first-sync (file mode): synthetic base from ${l.length} already-identical file(s) at head ${s} \u2014 divergence resolves through the remote-wins layer (D22)`),{lastSyncedSha:s,rootTreeSha:o.treeSha,files:l,spaceKind:"file"}}async syncAll(e,t="sync",r){if(this.opInProgress)return e.map(i=>this.busyResult(i));this.opInProgress=!0;try{let i=[];for(let s of e)i.push(await this.syncLocked(s,t,r));return i}finally{this.opInProgress=!1}}async sync(e,t="sync",r){if(this.opInProgress)return this.busyResult(e);this.opInProgress=!0;try{return await this.syncLocked(e,t,r)}finally{this.opInProgress=!1}}emitProgress(e,t,r){if(e!==void 0)try{e({repoKey:t,phase:r})}catch{}}async syncLocked(e,t="sync",r){let i=[],s=[],o=[],c=a((l,u={})=>({repoKey:e.repoKey,status:l,pulledCount:0,pushedCount:0,mergedCount:0,quarantinedCount:0,warnings:i,deferredDeletes:s,...u}),"result");try{let l=await this.deps.materializationCheck.check(e);if(!l.fullyMaterialized)return i.push(`skipped: repo not fully materialized${l.reason?` (${l.reason})`:""} \u2014 deletes NOT inferred (D19)`),c("skipped-not-materialized");let u=this.modeOps(e),f=this.deps.localFilesFor(e);if(u.fileMode&&(f.readBinary===void 0||f.writeBinary===void 0))return c("error",{detail:"file-mode repo requires a LocalFilesPort with readBinary/writeBinary \u2014 refusing to sync through the text-only port (binary would corrupt)"});if(u.fileMode&&this.deps.quarantine===void 0)return c("error",{detail:"file-mode repo requires a quarantine sink (D18 remote-wins preserves losing local bytes there) \u2014 configure the quarantine repo before syncing FileSpaces"});let d=this.deps.maxFileBytes??da.DEFAULT_MAX_FILE_BYTES,h=new Map,p=new Set;for(let N of(await f.list()).filter(u.syncable))if(u.fileMode){let j=await j3(f,N);if(j.byteLength>d){p.add(N),i.push(`skipped oversized file ${N} (${j.byteLength} bytes > ${d} cap) \u2014 excluded from sync symmetrically (Phase C size cap)`);continue}h.set(N,j)}else h.set(N,await f.read(N));let y=await this.deps.watermarkStore.get(e.repoKey);if(y?.spaceKind==="file"&&!u.fileMode)return c("error",{detail:"watermark was written by a FILE-mode sync but the spec now resolves to asset mode \u2014 refusing (fix the conflicting Space declarations, or clear the watermark to restart)"});y!==null&&u.fileMode&&y.spaceKind!=="file"&&(i.push("watermark was written by an ASSET-mode sync \u2014 rebuilding the base through the file-mode first-sync layer (kind flip)"),y=null);let g=!1;if(y===null){if(!u.fileMode)return await this.bootstrapWatermark(e,h,i,c);g=!0,y=await this.buildFileModeFirstSyncBase(e,h,u,i)}let v=y;u.fileMode&&p.size>0&&(y={...y,files:y.files.filter(N=>!p.has(N.path))}),this.emitProgress(r,e.repoKey,"detecting");let _=await(0,vc.detectChanges)({localFiles:h,watermark:y,actualBaseTreeSha:await this.resolveBaseTreeSha(e,y),sha1:this.deps.sha1});if(_.kind==="full-conflict")return c("full-conflict",{detail:`${_.reason}${_.detail?`: ${_.detail}`:""} \u2014 divergence must go through merge/quarantine (A2/A3), not overwrite`});i.push(..._.warnings);let S=this.pinLocalChanges(_,h,i,s,t);o=[...S.pushDeletionsAll.keys()];let T=await this.runPushLoop(e,y,S,h,i,u,g,p,t,r);if(o=[],T.kind!=="done"&&S.pushDeletionsAll.size>0&&s.push(...S.pushDeletionsAll.keys()),T.kind==="conflict")return c("conflict",{detail:T.detail});if(T.kind==="secret-detected")return c("error",{detail:T.detail});if(T.kind==="retry-exhausted"){i.push(...T.merge.warnings);let N=await this.buildTerminalQuarantineEntries(e,y,T.pushFiles,T.merge.quarantineEntries,h),j=[...T.merge.quarantineEntries,...T.merge.resolvedQuarantineEntries,...N];return await this.flushQuarantine(j,i),c("retry-exhausted",{detail:T.detail,quarantinedCount:j.length,...j.length>0?{quarantinedPaths:j.map(se=>se.path)}:{}})}let{examinedHead:I,pushedSha:A,applyWrites:R,applyDeletes:q,pushFiles:Y}=T,C=T.merge;i.push(...C.warnings),i.push(...T.deferredWarnings),s.push(...T.withheldDeletions);let O=T.deferredPaths.size>0?{deferredPaths:[...T.deferredPaths]}:{},k=T.pushedDeletions.length>0?{pushedDeletes:T.pushedDeletions}:{},H=await this.flushQuarantine([...C.quarantineEntries,...C.resolvedQuarantineEntries],i),G=new Set;if(!H&&C.resolvedQuarantineEntries.length>0){for(let N of C.resolvedQuarantineEntries)G.add(N.path);i.push(`quarantine flush failed \u2014 remote-wins apply withheld for ${G.size} path(s); local files untouched, conflict re-derives next sync (D18 durability gate)`)}if(A===void 0&&I===y.lastSyncedSha&&R.length===0&&q.length===0&&C.mergedWrites.length===0&&C.quarantineEntries.length===0&&C.resolvedQuarantineEntries.length===0&&(y.pinnedPaths?.length??0)===0&&T.alreadyInHead.length===0&&T.deferredPaths.size===0&&!g)return c("synced");let B=A??I,Z=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,B,this.deps.baseURL);if(A!==void 0&&Z.parents[0]!==I)return await this.checkRaceWindow(e,y,I,Z.parents[0],Y,new Set(T.pushedDeletions),i,u),i.push(`race-window: watermark NOT advanced (pushed commit's parent ${Z.parents[0]} != examined head ${I}) \u2014 next sync reconciles the concurrent change`),c("synced",{pushedSha:A,pushedCount:Y.size,mergedCount:C.mergedCount,quarantinedCount:C.quarantineEntries.length+C.resolvedQuarantineEntries.length,...C.mergedPaths.length>0?{mergedPaths:C.mergedPaths}:{},...py(C).length>0?{quarantinedPaths:py(C)}:{},...O,...k});let{pulledCount:_e,pinnedPaths:ie}=await this.applyRemoteChanges(f,h,[...R,...C.mergedWrites].filter(N=>!G.has(N.path)),q.filter(N=>!G.has(N.path)),i);for(let N of C.quarantineEntries)ie.add(N.path);for(let N of T.deferredPaths)ie.add(N);for(let N of G)ie.add(N);if(u.fileMode){for(let N of p)ie.add(N);for(let N of T.remoteOversized)ie.add(N)}return await this.advanceWatermark(e,B,Z.treeSha,h,[...R,...C.mergedWrites,...T.deferredRemoteChanges],v,ie,_.diskBlobShas,u,p),await this.resolveClearedPins(e,v,ie,i,new Set(C.resolvedQuarantineEntries.map(N=>N.path))),c("synced",{pushedSha:A,pulledCount:_e,pushedCount:Y.size,mergedCount:C.mergedCount,quarantinedCount:C.quarantineEntries.length+C.resolvedQuarantineEntries.length,...C.mergedPaths.length>0?{mergedPaths:C.mergedPaths}:{},...py(C).length>0?{quarantinedPaths:py(C)}:{},...O,...k})}catch(l){let u=this.deps.redact??(f=>f);return o.length>0&&s.push(...o),(0,Wz.isAuthError)(l)?c("auth-required",{detail:u(`authentication failed: ${cu(l)} \u2014 the PAT is expired, revoked or under-scoped; update it in the per-device secure storage (R8). Never treated as success.`)}):(i.push(`sync failed: ${u(cu(l))}`),c("error",{detail:u(cu(l))}))}}async flushQuarantine(e,t){if(e.length===0)return!0;let r=this.deps.redact??(s=>s);for(let s of e)t.push(r(`quarantined ${s.path}: ${s.reason}`));let i=this.deps.quarantine;if(i===void 0)return!1;try{if(i.quarantineAll!==void 0)await i.quarantineAll(e);else for(let s of e)await i.quarantine(s);return!0}catch(s){let o=this.deps.redact??(c=>c);return t.push(`quarantine sink failed: ${o(cu(s))} \u2014 files untouched on disk; the conflict re-derives next sync (D17 degradation)`),!1}}async buildTerminalQuarantineEntries(e,t,r,i,s){let o=new Set(i.map(u=>u.path)),c=new Map;try{let u=await(0,Ft.getHeadSha)(this.transport,e.owner,e.repo,e.branch,this.deps.baseURL),f=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,(await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,u,this.deps.baseURL)).treeSha,this.deps.baseURL)).filter(d=>r.has(d.path));for(let d of f)c.set(d.path,await(0,Ft.getBlobText)(this.transport,e.owner,e.repo,d.blobSha,this.deps.baseURL))}catch{}let l=[];for(let[u,f]of r){if(o.has(u))continue;let d=s.get(u),h=d??f,p=d!==void 0&&!(0,da.contentEquals)(d,f),y=typeof h=="string"?(0,vc.extractAssetUid)(h):void 0,g=c.get(u);l.push({repoKey:e.repoKey,path:u,...y!==void 0?{uid:y}:{},reason:`non-fast-forward push failed after ${this.deps.maxPushRetries??Fs.DEFAULT_MAX_PUSH_RETRIES} retries (D16) \u2014 a concurrent writer keeps moving ${e.branch}; base recoverable from git history at ${t.lastSyncedSha}${p?"; the contended push payload was a merged proposal (never applied to disk) \u2014 the merge re-derives next sync":""}`,...typeof h=="string"?{localContent:h}:{localContentBytes:h},...g!==void 0?{remoteContent:g}:{}})}return l}async resolveClearedPins(e,t,r,i,s=new Set){let o=this.deps.quarantine;if(o===void 0||o.markResolved===void 0)return;let c=(t.pinnedPaths??[]).filter(l=>!r.has(l)&&!s.has(l));for(let l of c)try{await o.markResolved?.(e.repoKey,l)}catch(u){let f=this.deps.redact??(d=>d);i.push(`quarantine markResolved failed for ${l}: ${f(cu(u))} \u2014 unresolved-count may overcount until the resolver UI reconciles (CQ4)`)}}async resolveBaseTreeSha(e,t){try{return(await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,t.lastSyncedSha,this.deps.baseURL)).treeSha}catch{return null}}pinLocalChanges(e,t,r,i,s){let o=e.modified.filter(h=>h.basePath!==void 0),c=[...e.added,...e.modified.filter(h=>h.basePath===void 0)],l=new Map;if(s==="pull"){for(let h of o)h.basePath!==void 0&&i.push(h.basePath),r.push(`pull-only: rename (uid ${h.uid??"?"}) ${h.basePath} \u2192 ${h.path} not pushed \u2014 propagates on the next push/Sync (#3473)`);for(let h of e.deleted)i.push(h.path),r.push(`pull-only: delete of ${h.path} not pushed \u2014 propagates on the next push/Sync (#3473)`)}else{for(let h of o)h.basePath!==void 0&&l.set(h.basePath,h.path);for(let h of e.deleted)l.set(h.path,h.path)}let u=[...c,...o,...e.deleted.map(h=>({...h}))],f=new Set(e.deleted.map(h=>h.path)),d=new Map;for(let h of[...c,...s==="pull"?[]:o]){let p=t.get(h.path);p!==void 0&&d.set(h.path,p)}return{localChanges:u,localDeletedPaths:f,pushFilesAll:d,pushDeletionsAll:l,dupUids:e.duplicateUids}}async runPushLoop(e,t,r,i,s,o,c=!1,l=new Set,u="sync",f){let{localChanges:d,localDeletedPaths:h,pushFilesAll:p,pushDeletionsAll:y,dupUids:g}=r,v=this.deps.maxPushRetries??Fs.DEFAULT_MAX_PUSH_RETRIES,_=0,S="",T,I=[],A=[],R=new Map,q=new Set,Y=[],C=GE,O=[],k=new Set,H=[],G=[],B=new Set;for(;;){S=await(0,Ft.getHeadSha)(this.transport,e.owner,e.repo,e.branch,this.deps.baseURL),I=[],A=[],C=GE,O=[],k=new Set,H=[],G=[];let Z,_e=new Set,ie=(t.pinnedPaths?.length??0)>0;if(S!==t.lastSyncedSha||ie||c){this.emitProgress(f,e.repoKey,"pulling-remote");let se=await this.collectRemoteChanges(e,t,S,o,l,s,B);Z=se.headTreeByPath;let be=this.matchLocalVsRemote(d,h,i,se.changes,_e,g,se.headTreeByPath);if(be.conflicts.length>0){if(u==="sync"&&this.emitProgress(f,e.repoKey,"merging"),u!=="sync"){for(let W of be.conflicts){k.add(W.local.path),W.local.basePath!==void 0&&k.add(W.local.basePath);for(let Ee of W.remotes)k.add(Ee.path),Ee.kind==="change"&&H.push(Ee)}G.push(`${u}-only: ${be.conflicts.length} conflict(s) deferred to a full Sync (${be.conflicts.map(W=>W.desc).join("; ")}) \u2014 paths pinned, nothing merged`)}else if(o.fileMode)C=this.resolveFileModeConflicts(e,be.conflicts,i,be.applyWrites,be.applyDeletes);else{if(this.deps.mergeLayer===void 0)return{kind:"conflict",detail:`overlapping change on ${be.conflicts[0].desc} \u2014 merge layer (A2/A3) required; nothing pushed, nothing written`};C=await this.resolveMergeConflicts(e,t,be.conflicts,i)}if(u==="sync")for(let W of be.conflicts)for(let Ee of W.remotes)Ee.path!==W.local.path&&(k.add(Ee.path),Ee.kind==="change"&&H.push(Ee),G.push(`conflict group ${W.desc}: remote change at ${Ee.path} NOT applied \u2014 pinned to re-derive on the next sync (#3477)`))}if(I=be.applyWrites,A=be.applyDeletes,u==="push"&&(I.length>0||A.length>0)){for(let W of I)k.add(W.path),H.push(W);for(let W of A)k.add(W.path);G.push(`push-only: ${I.length+A.length} remote change(s) NOT applied \u2014 pinned to re-derive on the next pull/Sync`),I=[],A=[]}}R=u==="pull"?new Map:new Map([...[...p].filter(([se])=>!_e.has(se)),...C.mergedFiles]),q=new Set,Y=[];for(let[se,be]of y){if(_e.has(be)){Y.push(se);continue}R.has(se)||q.add(se)}if((R.size>0||q.size>0)&&Z===void 0&&(Z=B3(await(0,Ft.getTree)(this.transport,e.owner,e.repo,t.rootTreeSha,this.deps.baseURL))),R.size>0&&Z!==void 0){for(let[se,be]of R){let W=Z.get(se);W!==void 0&&W===await(0,dd.gitBlobSha)(be,this.deps.sha1)&&(R.delete(se),O.push(se))}O.length>0&&s.push(`phantom push skipped: ${O.length} file(s) already identical in remote HEAD (${O.join(", ")}) \u2014 excluded from the commit (#3475)`)}if(q.size>0&&Z!==void 0){for(let se of[...q])Z.has(se)||q.delete(se);R.size===0&&q.size>=Z.size&&(Y.push(...q),G.push(`deletion of ALL ${q.size} remaining file(s) deferred \u2014 GitHub cannot create an empty tree; the deletes re-derive and propagate once the repo has at least one surviving file`),q.clear())}if(R.size===0&&q.size===0)break;let N=new Map;for(let[se,be]of R)if(typeof be=="string")N.set(se,be);else{let W=Kz(be);W!==null&&N.set(se,W)}let j=(0,zz.scanForSecrets)(N);if(j.length>0)return{kind:"secret-detected",detail:`secret-scan: refusing to push \u2014 ${j.map(se=>`${se.path} (${se.kind})`).join(", ")} (R5); remove the secret and re-sync`};try{T=await(0,Gz.restCreateCommit)(this.transport,{owner:e.owner,repo:e.repo,branch:e.branch,files:new Map([...R].map(([se,be])=>[se,Qz(be)])),deletions:[...q],message:this.deps.commitMessage?.(e,R.size,q.size)??`chore(exosync): sync ${R.size} file(s)${q.size>0?`, ${q.size} deletion(s)`:""}`,baseURL:this.deps.baseURL,redact:this.deps.redact});break}catch(se){if(!V3(se))throw se;if(_++,_>v)return{kind:"retry-exhausted",detail:`non-fast-forward push failed after ${v} retries (D16 cap) \u2014 contended files routed to quarantine (D17)`,pushFiles:R,merge:C};s.push(`non-fast-forward push (attempt ${_}/${v}) \u2014 re-pulling and retrying (D16)`)}}return{kind:"done",examinedHead:S,pushedSha:T,applyWrites:I,applyDeletes:A,pushFiles:R,pushedDeletions:T!==void 0?[...q]:[],withheldDeletions:Y,merge:C,remoteOversized:B,alreadyInHead:O,deferredPaths:k,deferredRemoteChanges:H,deferredWarnings:G}}async resolveMergeConflicts(e,t,r,i){let s=this.deps.mergeLayer;if(s===void 0)return GE;let o=new Map(t.files.map(g=>[g.path,g])),c=new Map,l=[],u=[],f=[],d=[],h=0,p=a(g=>typeof g=="string"?g:void 0,"asText"),y=a((g,v,_)=>{let S=p(i.get(g.local.path)),T=p(g.remotes[0]?.content);return{repoKey:e.repoKey,path:g.local.path,...g.local.uid!==void 0?{uid:g.local.uid}:{},reason:v,..._!==void 0?{baseContent:_}:{},...S!==void 0?{localContent:S}:{},...T!==void 0?{remoteContent:T}:{}}},"entry");for(let g of r){let v=o.get(g.local.basePath??g.local.path)??o.get(g.remotes[0]?.path??""),_;if(v!==void 0&&(_=await(0,Ft.getBlobText)(this.transport,e.owner,e.repo,v.blobSha,this.deps.baseURL)),g.remotes.length>1){u.push(y(g,`ambiguous conflict: local change overlaps ${g.remotes.length} remote changes (${g.remotes.map(R=>R.path).join(", ")})`,_));continue}let S=g.remotes[0],T=p(i.get(g.local.path)),I=await s.resolve({path:g.local.path,...g.local.uid!==void 0?{uid:g.local.uid}:{},..._!==void 0?{base:_}:{},...T!==void 0?{local:T}:{},...S.kind==="change"&&typeof S.content=="string"?{remote:S.content}:{}});if(I.action==="quarantine"){u.push(y(g,I.reason,_));continue}h++,d.push(g.local.path);for(let R of I.warnings??[])f.push(`merge(${g.local.path}): ${R}`);let A=S.kind==="change"?S.content:void 0;if(I.content!==A&&c.set(g.local.path,I.content),I.content!==i.get(g.local.path)){let R=(0,vc.extractAssetUid)(I.content)??g.local.uid;l.push({path:g.local.path,kind:"change",content:I.content,blobSha:await(0,dd.gitBlobSha)(I.content,this.deps.sha1),...R!==void 0?{uid:R}:{}})}}return{mergedFiles:c,mergedWrites:l,quarantineEntries:u,resolvedQuarantineEntries:[],mergedCount:h,mergedPaths:d,warnings:f}}resolveFileModeConflicts(e,t,r,i,s){let o=[],c=[];for(let l of t){l.remotes.length>1&&c.push(`file-mode conflict on ${l.local.path} unexpectedly overlaps ${l.remotes.length} remote changes \u2014 resolving against the first`);let u=l.remotes[0],f=r.get(l.local.path);u.kind==="change"?i.push(u):s.push(u),!(l.localIsDelete||f===void 0)&&o.push({repoKey:e.repoKey,path:l.local.path,reason:`file-mode remote-wins (D18): remote ${u.kind==="change"?`version ${u.blobSha}`:"delete"} wins; this is the losing LOCAL version, preserved byte-exact`,...typeof f=="string"?{localContent:f}:{localContentBytes:f}})}return{mergedFiles:new Map,mergedWrites:[],quarantineEntries:[],resolvedQuarantineEntries:o,mergedCount:0,mergedPaths:[],warnings:c}}async applyRemoteChanges(e,t,r,i,s){let o=0,c=new Set,l=a(async(f,d)=>{try{return d?await j3(e,f):await e.read(f)}catch{return}},"tryRead"),u=a(async(f,d)=>{typeof d=="string"?await e.write(f,d):await Xz(e,f,d)},"writeContent");for(let f of r){if(f.content===void 0)continue;if(!$3(f.path)){s.push(`unsafe remote path skipped on pull-apply: ${f.path}`),c.add(f.path);continue}let d=t.get(f.path),h=await l(f.path,typeof(d??f.content)!="string");if(!(0,da.contentEquals)(h,d)){s.push(`pull-apply skipped: ${f.path} changed on disk mid-sync (TOCTOU) \u2014 remote change re-derives next sync`),c.add(f.path);continue}await u(f.path,f.content),o++}for(let f of i){if(!$3(f.path)){s.push(`unsafe remote path skipped on pull-delete: ${f.path}`),c.add(f.path);continue}let d=t.get(f.path);if(d!==void 0){let h=await l(f.path,typeof d!="string");if(h!==void 0&&!(0,da.contentEquals)(h,d)){s.push(`pull-delete skipped: ${f.path} changed on disk mid-sync (TOCTOU) \u2014 delete-vs-modify re-derives next sync`),c.add(f.path);continue}await e.delete(f.path),o++}}return{pulledCount:o,pinnedPaths:c}}async advanceWatermark(e,t,r,i,s,o,c,l,u,f=new Set){let d=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,r,this.deps.baseURL)).filter(p=>u.treeFilter(p)&&!f.has(p.path)),h=Jz(await this.buildWatermarkFiles(e,d,i,s,o,l,u),o,c);await this.deps.watermarkStore.set(e.repoKey,{lastSyncedSha:t,rootTreeSha:r,files:h,...c.size>0?{pinnedPaths:[...c]}:{},...u.fileMode?{spaceKind:"file"}:{}})}async bootstrapWatermark(e,t,r,i){let s=await(0,Ft.getHeadSha)(this.transport,e.owner,e.repo,e.branch,this.deps.baseURL),o=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,s,this.deps.baseURL),c=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,o.treeSha,this.deps.baseURL)).filter(u=>(0,da.isSyncablePath)(u.path));if(c.length!==t.size)return i("full-conflict",{detail:`first-sync: no watermark and local tree (${t.size} files) differs from remote head (${c.length} files) \u2014 A2/A3 scope`});for(let u of c){let f=t.get(u.path);if(f===void 0||await(0,dd.gitBlobSha)(f,this.deps.sha1)!==u.blobSha)return i("full-conflict",{detail:`first-sync: no watermark and local content diverges from remote head at ${u.path} \u2014 A2/A3 scope`})}let l=c.map(u=>{let f=t.get(u.path),d=typeof f=="string"?(0,vc.extractAssetUid)(f):void 0;return{path:u.path,blobSha:u.blobSha,...d?{uid:d}:{}}});return await this.deps.watermarkStore.set(e.repoKey,{lastSyncedSha:s,rootTreeSha:o.treeSha,files:l}),r.push(`watermark bootstrapped from head ${s} (local tree identical to remote)`),i("synced")}async collectRemoteChanges(e,t,r,i,s=new Set,o=[],c=new Set){let l=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,r,this.deps.baseURL),u=await(0,Ft.getTree)(this.transport,e.owner,e.repo,l.treeSha,this.deps.baseURL);if(i.fileMode)for(let g of u)i.syncable(g.path)&&!i.treeFilter(g)&&!c.has(g.path)&&(c.add(g.path),o.push(`skipped oversized REMOTE file ${g.path} (${g.size??"?"} bytes over cap) \u2014 excluded from sync symmetrically (Phase C size cap)`));let f=u.filter(g=>i.treeFilter(g)&&!s.has(g.path)),d=t.files.filter(g=>!c.has(g.path)&&!s.has(g.path)),{changed:h,deleted:p}=U3(d,f),y=[];for(let g of h){if(i.fileMode){let _=await(0,Ft.getBlobBytes)(this.transport,e.owner,e.repo,g.blobSha,this.deps.baseURL);y.push({path:g.path,kind:"change",blobSha:g.blobSha,content:_});continue}let v=await(0,Ft.getBlobText)(this.transport,e.owner,e.repo,g.blobSha,this.deps.baseURL);y.push({path:g.path,kind:"change",blobSha:g.blobSha,content:v,uid:(0,vc.extractAssetUid)(v)})}for(let g of p)y.push({path:g.path,kind:"delete",uid:g.uid});return{changes:y,headTreeByPath:B3(u)}}matchLocalVsRemote(e,t,r,i,s,o=new Set,c){let l=new Set,u=[],f=new Map;for(let g of i)g.kind==="change"&&g.uid!==void 0&&f.set(g.uid,(f.get(g.uid)??0)+1);let d=new Set(o);for(let[g,v]of f)v>1&&d.add(g);let h=new Map,p=new Map;for(let g of i){if(g.uid!==void 0&&!d.has(g.uid)){let v=h.get(g.uid)??[];v.push(g),h.set(g.uid,v)}p.set(g.path,g)}for(let g of e){let v=new Set;if(g.uid!==void 0&&!d.has(g.uid))for(let I of h.get(g.uid)??[])I.kind==="change"&&I.path!==g.path&&(c?.has(g.path)===!0||g.basePath!==void 0&&c?.has(g.basePath)===!0)||v.add(I);let _=p.get(g.path);if(_!==void 0&&v.add(_),g.basePath!==void 0){let I=p.get(g.basePath);I!==void 0&&v.add(I)}let S=[],T=!1;for(let I of v){if(T=t.has(g.path)&&!r.has(g.path),T&&I.kind==="delete"){l.add(I);continue}if(!T&&I.kind==="change"&&I.path===g.path&&I.blobSha===g.blobSha){l.add(I),s.add(g.path);continue}if(I.kind==="delete"&&g.basePath!==void 0&&I.path===g.basePath){let A=p.get(g.path);if(A!==void 0&&A.kind==="change"&&A.blobSha===g.blobSha){l.add(I);continue}}S.push(I),l.add(I)}S.length>0&&(u.push({local:g,localIsDelete:T,remotes:S,desc:`${g.uid!==void 0&&!d.has(g.uid)?g.uid:g.path} (local ${T?"delete":"change"} vs remote ${S[0].kind} at ${S[0].path})`}),s.add(g.path))}let y=i.filter(g=>!l.has(g));return{conflicts:u,applyWrites:y.filter(g=>g.kind==="change"),applyDeletes:y.filter(g=>g.kind==="delete")}}async checkRaceWindow(e,t,r,i,s,o,c,l){try{let u=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,i,this.deps.baseURL),f=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,u.treeSha,this.deps.baseURL)).filter(l.treeFilter),d=r===t.lastSyncedSha?t.files:(await(0,Ft.getTree)(this.transport,e.owner,e.repo,(await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,r,this.deps.baseURL)).treeSha,this.deps.baseURL)).filter(l.treeFilter),{changed:h,deleted:p}=U3(d,f);for(let y of h)s.has(y.path)&&c.push(`race-window: concurrent commit ${i} changed ${y.path} between conflict check (head ${r}) and push \u2014 local version won; previous version recoverable from git history`),o.has(y.path)&&c.push(`race-window: concurrent commit ${i} changed ${y.path} which this push DELETED \u2014 the delete won; the concurrent version is recoverable from git history`);for(let y of p)s.has(y.path)&&c.push(`race-window: concurrent commit ${i} deleted ${y.path}; push re-created it`)}catch(u){let f=this.deps.redact??(d=>d);c.push(`race-window check failed: ${f(cu(u))}`)}}async buildWatermarkFiles(e,t,r,i,s,o,c){if(c.fileMode)return t.map(f=>({path:f.path,blobSha:f.blobSha}));let l=new Map;for(let f of i)f.kind==="change"&&f.blobSha!==void 0&&l.set(f.blobSha,f.uid);for(let[f,d]of r){let h=o?.get(f)??await(0,dd.gitBlobSha)(d,this.deps.sha1);l.set(h,typeof d=="string"?(0,vc.extractAssetUid)(d):void 0)}for(let f of s.files)l.has(f.blobSha)||l.set(f.blobSha,f.uid);let u=[];for(let f of t){let d;if(l.has(f.blobSha))d=l.get(f.blobSha);else{let h=await(0,Ft.getBlobText)(this.transport,e.owner,e.repo,f.blobSha,this.deps.baseURL);d=(0,vc.extractAssetUid)(h)}u.push({path:f.path,blobSha:f.blobSha,...d?{uid:d}:{}})}return u}};Fs.SyncEngine=qE});var KE=w(HE=>{"use strict";Object.defineProperty(HE,"__esModule",{value:!0});HE.diff3=Zz;function G3(n,e){let t=n.length,r=e.length,i=Array.from({length:t+1},()=>new Int32Array(r+1));for(let l=t-1;l>=0;l--)for(let u=r-1;u>=0;u--)i[l][u]=n[l]===e[u]?i[l+1][u+1]+1:Math.max(i[l+1][u],i[l][u+1]);let s=new Map,o=0,c=0;for(;o<t&&c<r;)n[o]===e[c]?(s.set(o,c),o++,c++):i[o+1][c]>=i[o][c+1]?o++:c++;return s}a(G3,"lcsMatch");function zE(n,e){if(n.length!==e.length)return!1;for(let t=0;t<n.length;t++)if(n[t]!==e[t])return!1;return!0}a(zE,"sliceEq");function Zz(n,e,t){let r=G3(n,e),i=G3(n,t),s=[],o=0,c=0,l=0;for(;;){let u=o;for(;u<n.length&&!(r.has(u)&&i.has(u));)u++;let f=u<n.length?r.get(u):e.length,d=u<n.length?i.get(u):t.length,h=n.slice(o,u),p=e.slice(c,f),y=t.slice(l,d),g=!zE(p,h),v=!zE(y,h);if(!g&&!v)s.push(...h);else if(!g)s.push(...y);else if(!v)s.push(...p);else if(zE(p,y))s.push(...p);else return{ok:!1,conflict:{base:h,local:p,remote:y}};if(u>=n.length)break;s.push(n[u]),o=u+1,c=f+1,l=d+1}return{ok:!0,merged:s}}a(Zz,"diff3")});var W3=w(md=>{"use strict";Object.defineProperty(md,"__esModule",{value:!0});md.StructuredMerger=void 0;md.splitSections=my;var q3=KE(),eH=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/,hd="exo__Instance_class";function pd(n){if(n===null||typeof n!="object")return!0;if(Array.isArray(n))return n.every(pd);let e=Object.getPrototypeOf(n);return e!==Object.prototype&&e!==null?!1:Object.values(n).every(pd)}a(pd,"isPlainValue");function ha(n,e){if(n===e)return!0;if(n===null||e===null||n===void 0||e===void 0||typeof n!="object"||typeof e!="object"||Array.isArray(n)!==Array.isArray(e))return!1;if(Array.isArray(n)&&Array.isArray(e))return n.length!==e.length?!1:n.every((s,o)=>ha(s,e[o]));let t=n,r=e,i=Object.keys(t);return i.length!==Object.keys(r).length?!1:i.every(s=>ha(t[s],r[s]))}a(ha,"deepEqual");function Ec(n){return typeof n=="string"?`s:${n}`:`j:${JSON.stringify(n)}`}a(Ec,"setKey");function ui(n){return n==null?[]:Array.isArray(n)?n:[n]}a(ui,"toElements");function tH(n,e,t){let r=new Set(ui(n).map(Ec)),i=ui(e),s=ui(t),o=new Set(i.map(Ec)),c=new Set(s.map(Ec)),l=a(d=>o.has(d)&&c.has(d)||o.has(d)&&!r.has(d)||c.has(d)&&!r.has(d),"keep"),u=[],f=new Set;for(let d of[...i,...s]){let h=Ec(d);f.has(h)||!l(h)||(f.add(h),u.push(d))}return u}a(tH,"mergeSet");function rH(n,e,t){let r=[],i=[],s=new Set;for(let c of[...Object.keys(n),...Object.keys(e),...Object.keys(t)])s.has(c)||(s.add(c),i.push(c));let o={};for(let c of i){let l=n[c],u=e[c],f=t[c];if(!pd(l)||!pd(u)||!pd(f))return{ok:!1,reason:`frontmatter key "${c}" contains a non-plain value (Date?) \u2014 the codec must round-trip scalars as strings (CORE_SCHEMA contract)`};if(Array.isArray(l)||Array.isArray(u)||Array.isArray(f)){if(!(c in e)&&!(c in t))continue;let d=tH(l,u,f),h=new Set(ui(l).map(Ec)),p=ui(u).some(g=>!h.has(Ec(g))),y=ui(f).some(g=>!h.has(Ec(g)));p&&y&&!ha(ui(u),ui(f))&&r.push(`both sides added values to multi-valued key "${c}" \u2014 union kept (D20)`),d.length>0&&(o[c]=d);continue}if(ha(u,f)){u!==void 0&&(o[c]=u);continue}if(ha(u,l)){f!==void 0&&(o[c]=f);continue}if(ha(f,l)){u!==void 0&&(o[c]=u);continue}return{ok:!1,reason:`frontmatter key "${c}" changed differently on both sides`}}return{ok:!0,value:o,warnings:r}}a(rH,"mergeFrontmatter");var nH=/^(```|~~~)/,iH=/^#{1,6}\s/;function my(n){let e=n.split(`
463
+ `)}a(Az,"stripGitmodulesEntry")});var ld=w($E=>{"use strict";Object.defineProperty($E,"__esModule",{value:!0});$E.gitBlobSha=Iz;async function Iz(n,e){let t=new TextEncoder,r=typeof n=="string"?t.encode(n):n,i=t.encode(`blob ${r.byteLength}\0`),s=new Uint8Array(i.byteLength+r.byteLength);return s.set(i,0),s.set(r,i.byteLength),e(s)}a(Iz,"gitBlobSha")});var UE=w(ay=>{"use strict";Object.defineProperty(ay,"__esModule",{value:!0});ay.extractAssetUid=L3;ay.detectChanges=Rz;var xz=ld();function L3(n){let e=/^---\r?\n([\s\S]*?)\r?\n---(?=\r?\n|$)/.exec(n);if(!e)return;let t=/^exo__Asset_uid:[ \t]*["']?([^\s"']+)["']?[ \t]*$/m.exec(e[1]);return t?t[1]:void 0}a(L3,"extractAssetUid");async function Rz(n){let{localFiles:e,watermark:t,actualBaseTreeSha:r,sha1:i}=n;if(t===null)return{kind:"full-conflict",reason:"first-sync"};if(r===null)return{kind:"full-conflict",reason:"base-mismatch",detail:`watermark commit ${t.lastSyncedSha} not resolvable on remote`};if(r!==t.rootTreeSha)return{kind:"full-conflict",reason:"base-mismatch",detail:`stored root tree ${t.rootTreeSha} != actual ${r} at ${t.lastSyncedSha}`};let s=[],o=new Map;for(let[T,I]of e){let A=await(0,xz.gitBlobSha)(I,i);o.set(T,A),s.push({path:T,blobSha:A,uid:typeof I=="string"?L3(I):void 0})}let c=[],l=[],u=[],f=[],d=new Map;for(let T of s){if(T.uid===void 0)continue;let I=d.get(T.uid)??[];I.push(T.path),d.set(T.uid,I)}let h=new Map;for(let T of t.files){if(T.uid===void 0)continue;let I=h.get(T.uid)??[];I.push(T.path),h.set(T.uid,I)}let p=new Set;for(let[T,I]of d)I.length>1&&p.add(T);for(let[T,I]of h)I.length>1&&p.add(T);for(let T of[...p].sort()){let I=d.get(T)??[],A=I.length>1?`on disk (${I.join(", ")})`:`in the sync base (${(h.get(T)??[]).join(", ")})`;f.push(`duplicate uid ${T} ${A} \u2014 uid identity suppressed for the group; every path matched by path identity (#3477)`)}let y=new Map,g=[];for(let T of t.files)T.uid!==void 0&&!p.has(T.uid)?y.set(T.uid,T):g.push(T);let v=[],_=new Set;for(let T of s){let I=T.uid!==void 0&&!p.has(T.uid)?y.get(T.uid):void 0;T.uid!==void 0&&I!==void 0?(_.add(T.uid),(I.blobSha!==T.blobSha||I.path!==T.path)&&l.push({path:T.path,uid:T.uid,blobSha:T.blobSha,...I.path!==T.path?{basePath:I.path}:{}})):v.push(T)}let S=new Map;for(let T of g)S.set(T.path,T);for(let[T,I]of y)_.has(T)||S.set(I.path,I);for(let T of v){let I=S.get(T.path);I!==void 0?(S.delete(T.path),I.blobSha!==T.blobSha&&l.push({path:T.path,uid:T.uid,blobSha:T.blobSha})):c.push({path:T.path,uid:T.uid,blobSha:T.blobSha})}for(let T of S.values())u.push({path:T.path,uid:T.uid,blobSha:T.blobSha});return{kind:"changes",added:c,modified:l,deleted:u,warnings:f,diskBlobShas:o,duplicateUids:p}}a(Rz,"detectChanges")});var fd=w(wc=>{"use strict";Object.defineProperty(wc,"__esModule",{value:!0});wc.getHeadSha=Cz;wc.getCommitInfo=Oz;wc.getTree=Dz;wc.getBlobText=Fz;wc.getBlobBytes=Lz;var N3=il(),Pz="https://api.github.com";function ud(n){return(n??Pz).replace(/\/$/,"")}a(ud,"api");function Sc(n){return n!==null&&typeof n=="object"?n:void 0}a(Sc,"asRecord");function Ds(n,e){let r=Sc(n)?.[e];return typeof r=="string"?r:void 0}a(Ds,"readString");async function Cz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/refs/heads/${encodeURIComponent(r)}`}),o=Ds(Sc(s?.json)?.object,"sha");if(typeof o!="string"||o.length===0)throw new Error(`ExoSync: missing object.sha for ref heads/${r}`);return o}a(Cz,"getHeadSha");async function Oz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/commits/${encodeURIComponent(r)}`}),o=Sc(s?.json),c=Ds(o,"sha"),l=Ds(o?.tree,"sha");if(!c||!l)throw new Error(`ExoSync: malformed commit response for ${r}`);let u=o?.parents,f=Array.isArray(u)?u.map(d=>Ds(d,"sha")).filter(d=>typeof d=="string"):[];return{sha:c,treeSha:l,parents:f}}a(Oz,"getCommitInfo");async function Dz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/trees/${encodeURIComponent(r)}?recursive=1`}),o=Sc(s?.json);if(o?.truncated===!0)throw new Error(`ExoSync: tree ${r} is truncated by GitHub (repo too large for recursive listing) \u2014 refusing to diff`);let c=o?.tree;if(!Array.isArray(c))throw new Error(`ExoSync: malformed tree response for ${r}`);let l=[];for(let u of c){let f=Sc(u);if(f?.type!=="blob")continue;let d=Ds(f,"path"),h=Ds(f,"sha"),p=typeof f.size=="number"?f.size:void 0;d&&h&&l.push({path:d,blobSha:h,...p!==void 0?{size:p}:{}})}return l}a(Dz,"getTree");async function Fz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/blobs/${encodeURIComponent(r)}`}),o=Sc(s?.json),c=Ds(o,"content");if(typeof c!="string")throw new Error(`ExoSync: malformed blob response for ${r}`);return Ds(o,"encoding")==="utf-8"?c:(0,N3.base64ToUtf8)(c)}a(Fz,"getBlobText");async function Lz(n,e,t,r,i){let s=await n({method:"GET",url:`${ud(i)}/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}/git/blobs/${encodeURIComponent(r)}`}),o=Sc(s?.json),c=Ds(o,"content");if(typeof c!="string")throw new Error(`ExoSync: malformed blob response for ${r}`);return Ds(o,"encoding")==="utf-8"?new TextEncoder().encode(c):(0,N3.base64ToBytes)(c)}a(Lz,"getBlobBytes")});var cy=w(BE=>{"use strict";Object.defineProperty(BE,"__esModule",{value:!0});BE.isAuthError=Nz;function Nz(n){let e=n instanceof Error?n.message:String(n);return/HTTP 401/.test(e)?!0:/HTTP 403/.test(e)&&!/rate limit/i.test(e)&&!/abuse detection/i.test(e)}a(Nz,"isAuthError")});var uy=w(ly=>{"use strict";Object.defineProperty(ly,"__esModule",{value:!0});ly.scanForSecrets=kz;ly.redactSecrets=Mz;var k3=[{kind:"github-token",re:/gh[pousr]_[A-Za-z0-9_]{36,}/},{kind:"github-fine-grained-token",re:/github_pat_[A-Za-z0-9_]{22,}_[A-Za-z0-9_]{59,}/},{kind:"private-key",re:/-----BEGIN [A-Z ]*PRIVATE KEY-----/}];function kz(n){let e=[];for(let[t,r]of n)for(let{kind:i,re:s}of k3)s.test(r)&&e.push({path:t,kind:i});return e}a(kz,"scanForSecrets");function Mz(n){let e=n;for(let{kind:t,re:r}of k3)e=e.replace(new RegExp(r.source,"g"),`[REDACTED:${t}]`);return e}a(Mz,"redactSecrets")});var dy=w(fy=>{"use strict";Object.defineProperty(fy,"__esModule",{value:!0});fy.isRateLimitError=M3;fy.withRateLimitBackoff=$z;function M3(n){let e=n instanceof Error?n.message:String(n);return/HTTP 429/.test(e)?!0:/HTTP 403/.test(e)&&(/rate limit/i.test(e)||/abuse detection/i.test(e))}a(M3,"isRateLimitError");var jz=a(n=>new Promise(e=>setTimeout(e,n)),"defaultSleep");function $z(n,e={}){let t=e.maxRetries??3,r=e.baseDelayMs??1e3,i=e.sleep??jz,s=e.random??Math.random;return async o=>{let c=0;for(;;)try{return await n(o)}catch(l){if(!M3(l)||c>=t)throw l;let u=r*2**c*(1+s());c++,await i(u)}}}a($z,"withRateLimitBackoff")});var hy=w(Io=>{"use strict";Object.defineProperty(Io,"__esModule",{value:!0});Io.DEFAULT_MAX_FILE_BYTES=Io.InMemoryQuarantineStore=void 0;Io.contentEquals=Uz;Io.isSyncablePath=Bz;Io.isFileSpaceSyncablePath=Vz;function Uz(n,e){if(n===void 0||e===void 0||typeof n=="string"&&typeof e=="string")return n===e;if(typeof n=="string"||typeof e=="string"||n.byteLength!==e.byteLength)return!1;for(let t=0;t<n.byteLength;t++)if(n[t]!==e[t])return!1;return!0}a(Uz,"contentEquals");var VE=class{static{a(this,"InMemoryQuarantineStore")}constructor(){this.entries=[]}async quarantine(e){this.entries.push(e)}};Io.InMemoryQuarantineStore=VE;function Bz(n){return n.endsWith(".md")&&!n.includes(".local.")&&!n.includes(".conflict.")}a(Bz,"isSyncablePath");function Vz(n){return!n.includes(".local.")&&!n.includes(".conflict.")}a(Vz,"isFileSpaceSyncablePath");Io.DEFAULT_MAX_FILE_BYTES=30*1024*1024});var WE=w(Fs=>{"use strict";Object.defineProperty(Fs,"__esModule",{value:!0});Fs.SyncEngine=Fs.DEFAULT_MAX_PUSH_RETRIES=void 0;Fs.isNonFastForwardError=V3;Fs.orderChildrenFirst=Yz;var Gz=sy(),Ft=fd(),vc=UE(),qz=il(),dd=ld(),Wz=cy(),zz=uy(),Hz=dy(),da=hy();Fs.DEFAULT_MAX_PUSH_RETRIES=3;function Kz(n){try{return new TextDecoder("utf-8",{fatal:!0}).decode(n)}catch{return null}}a(Kz,"decodeUtf8Strict");function Qz(n){return typeof n=="string"?n:{base64:(0,qz.bytesToBase64)(n)}}a(Qz,"toCommitContent");async function j3(n,e){if(n.readBinary===void 0)throw new Error("LocalFilesPort.readBinary is required for file-mode sync (Phase C)");return n.readBinary(e)}a(j3,"readBinaryStrict");async function Xz(n,e,t){if(n.writeBinary===void 0)throw new Error("LocalFilesPort.writeBinary is required for file-mode sync (Phase C)");return n.writeBinary(e,t)}a(Xz,"writeBinaryStrict");function $3(n){return n.length===0||n.startsWith("/")||n.includes("\\")?!1:n.split("/").every(e=>e.length>0&&e!=="."&&e!=="..")}a($3,"isSafeRepoRelativePath");function V3(n){let e=n instanceof Error?n.message:String(n);return/HTTP 422/.test(e)&&/git\/refs/.test(e)||/ref update mismatch/.test(e)||/HTTP 422/.test(e)&&/git\/trees/.test(e)&&/BadObjectState/.test(e)}a(V3,"isNonFastForwardError");function Yz(n){let e=a(t=>t.split("/").filter(r=>r.length>0).length,"depth");return[...n].sort((t,r)=>e(r.localPath)-e(t.localPath))}a(Yz,"orderChildrenFirst");function U3(n,e){let t=new Map(n.map(o=>[o.path,o])),r=new Set,i=[];for(let o of e){r.add(o.path);let c=t.get(o.path);(c===void 0||c.blobSha!==o.blobSha)&&i.push(o)}let s=n.filter(o=>!r.has(o.path));return{changed:i,deleted:s}}a(U3,"diffTrees");function cu(n){return n instanceof Error?n.message:String(n)}a(cu,"errMsg");function Jz(n,e,t){if(t.size===0)return n;let r=new Map(e.files.map(o=>[o.path,o])),i=new Set(n.map(o=>o.path)),s=[];for(let o of n){if(!t.has(o.path)){s.push(o);continue}let c=r.get(o.path);c!==void 0&&s.push(c)}for(let o of t){if(i.has(o))continue;let c=r.get(o);c!==void 0&&s.push(c)}return s}a(Jz,"applyWatermarkPins");var GE={mergedFiles:new Map,mergedWrites:[],quarantineEntries:[],resolvedQuarantineEntries:[],mergedCount:0,mergedPaths:[],warnings:[]};function B3(n){return new Map(n.map(e=>[e.path,e.blobSha]))}a(B3,"treeByPath");function py(n){return[...n.quarantineEntries.map(e=>e.path),...n.resolvedQuarantineEntries.map(e=>e.path)]}a(py,"quarantinedPathsOf");var qE=class{static{a(this,"SyncEngine")}constructor(e){this.opInProgress=!1,this.deps=e,this.transport=(0,Hz.withRateLimitBackoff)(e.transport,e.backoff)}busyResult(e){return{repoKey:e.repoKey,status:"busy",pulledCount:0,pushedCount:0,mergedCount:0,quarantinedCount:0,warnings:[],deferredDeletes:[],detail:"another sync operation is in progress (D11 guard) \u2014 retry after it finishes"}}modeOps(e){let t=e.spaceKind==="file",r=t?da.isFileSpaceSyncablePath:da.isSyncablePath,i=this.deps.maxFileBytes??da.DEFAULT_MAX_FILE_BYTES;return{fileMode:t,syncable:r,treeFilter:a(s=>r(s.path)&&(!t||s.size===void 0||s.size<=i),"treeFilter")}}async buildFileModeFirstSyncBase(e,t,r,i){let s=await(0,Ft.getHeadSha)(this.transport,e.owner,e.repo,e.branch,this.deps.baseURL),o=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,s,this.deps.baseURL),c=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,o.treeSha,this.deps.baseURL)).filter(r.treeFilter),l=[];for(let u of c){let f=t.get(u.path);f!==void 0&&await(0,dd.gitBlobSha)(f,this.deps.sha1)===u.blobSha&&l.push({path:u.path,blobSha:u.blobSha})}return i.push(`first-sync (file mode): synthetic base from ${l.length} already-identical file(s) at head ${s} \u2014 divergence resolves through the remote-wins layer (D22)`),{lastSyncedSha:s,rootTreeSha:o.treeSha,files:l,spaceKind:"file"}}async syncAll(e,t="sync",r){if(this.opInProgress)return e.map(i=>this.busyResult(i));this.opInProgress=!0;try{let i=[];for(let s of e)i.push(await this.syncLocked(s,t,r));return i}finally{this.opInProgress=!1}}async sync(e,t="sync",r){if(this.opInProgress)return this.busyResult(e);this.opInProgress=!0;try{return await this.syncLocked(e,t,r)}finally{this.opInProgress=!1}}emitProgress(e,t,r){if(e!==void 0)try{e({repoKey:t,phase:r})}catch{}}async syncLocked(e,t="sync",r){let i=[],s=[],o=[],c=a((l,u={})=>({repoKey:e.repoKey,status:l,pulledCount:0,pushedCount:0,mergedCount:0,quarantinedCount:0,warnings:i,deferredDeletes:s,...u}),"result");try{let l=await this.deps.materializationCheck.check(e);if(!l.fullyMaterialized)return i.push(`skipped: repo not fully materialized${l.reason?` (${l.reason})`:""} \u2014 deletes NOT inferred (D19)`),c("skipped-not-materialized");let u=this.modeOps(e),f=this.deps.localFilesFor(e);if(u.fileMode&&(f.readBinary===void 0||f.writeBinary===void 0))return c("error",{detail:"file-mode repo requires a LocalFilesPort with readBinary/writeBinary \u2014 refusing to sync through the text-only port (binary would corrupt)"});if(u.fileMode&&this.deps.quarantine===void 0)return c("error",{detail:"file-mode repo requires a quarantine sink (D18 remote-wins preserves losing local bytes there) \u2014 configure the quarantine repo before syncing FileSpaces"});let d=this.deps.maxFileBytes??da.DEFAULT_MAX_FILE_BYTES,h=new Map,p=new Set;for(let N of(await f.list()).filter(u.syncable))if(u.fileMode){let j=await j3(f,N);if(j.byteLength>d){p.add(N),i.push(`skipped oversized file ${N} (${j.byteLength} bytes > ${d} cap) \u2014 excluded from sync symmetrically (Phase C size cap)`);continue}h.set(N,j)}else h.set(N,await f.read(N));let y=await this.deps.watermarkStore.get(e.repoKey);if(y?.spaceKind==="file"&&!u.fileMode)return c("error",{detail:"watermark was written by a FILE-mode sync but the spec now resolves to asset mode \u2014 refusing (fix the conflicting Space declarations, or clear the watermark to restart)"});y!==null&&u.fileMode&&y.spaceKind!=="file"&&(i.push("watermark was written by an ASSET-mode sync \u2014 rebuilding the base through the file-mode first-sync layer (kind flip)"),y=null);let g=!1;if(y===null)if(u.fileMode)g=!0,y=await this.buildFileModeFirstSyncBase(e,h,u,i);else{let N=await this.bootstrapWatermark(e,h,i,c);if(N.kind==="settled")return N.outcome;g=!0,y=N.base}let v=y;u.fileMode&&p.size>0&&(y={...y,files:y.files.filter(N=>!p.has(N.path))}),this.emitProgress(r,e.repoKey,"detecting");let _=await(0,vc.detectChanges)({localFiles:h,watermark:y,actualBaseTreeSha:await this.resolveBaseTreeSha(e,y),sha1:this.deps.sha1});if(_.kind==="full-conflict")return c("full-conflict",{detail:`${_.reason}${_.detail?`: ${_.detail}`:""} \u2014 divergence must go through merge/quarantine (A2/A3), not overwrite`});i.push(..._.warnings);let S=this.pinLocalChanges(_,h,i,s,t);o=[...S.pushDeletionsAll.keys()];let T=await this.runPushLoop(e,y,S,h,i,u,g,p,t,r);if(o=[],T.kind!=="done"&&S.pushDeletionsAll.size>0&&s.push(...S.pushDeletionsAll.keys()),T.kind==="conflict")return c("conflict",{detail:T.detail});if(T.kind==="secret-detected")return c("error",{detail:T.detail});if(T.kind==="retry-exhausted"){i.push(...T.merge.warnings);let N=await this.buildTerminalQuarantineEntries(e,y,T.pushFiles,T.merge.quarantineEntries,h),j=[...T.merge.quarantineEntries,...T.merge.resolvedQuarantineEntries,...N];return await this.flushQuarantine(j,i),c("retry-exhausted",{detail:T.detail,quarantinedCount:j.length,...j.length>0?{quarantinedPaths:j.map(se=>se.path)}:{}})}let{examinedHead:I,pushedSha:A,applyWrites:R,applyDeletes:q,pushFiles:Y}=T,C=T.merge;i.push(...C.warnings),i.push(...T.deferredWarnings),s.push(...T.withheldDeletions);let O=T.deferredPaths.size>0?{deferredPaths:[...T.deferredPaths]}:{},k=T.pushedDeletions.length>0?{pushedDeletes:T.pushedDeletions}:{},H=await this.flushQuarantine([...C.quarantineEntries,...C.resolvedQuarantineEntries],i),G=new Set;if(!H&&C.resolvedQuarantineEntries.length>0){for(let N of C.resolvedQuarantineEntries)G.add(N.path);i.push(`quarantine flush failed \u2014 remote-wins apply withheld for ${G.size} path(s); local files untouched, conflict re-derives next sync (D18 durability gate)`)}if(A===void 0&&I===y.lastSyncedSha&&R.length===0&&q.length===0&&C.mergedWrites.length===0&&C.quarantineEntries.length===0&&C.resolvedQuarantineEntries.length===0&&(y.pinnedPaths?.length??0)===0&&T.alreadyInHead.length===0&&T.deferredPaths.size===0&&!g)return c("synced");let B=A??I,Z=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,B,this.deps.baseURL);if(A!==void 0&&Z.parents[0]!==I)return await this.checkRaceWindow(e,y,I,Z.parents[0],Y,new Set(T.pushedDeletions),i,u),i.push(`race-window: watermark NOT advanced (pushed commit's parent ${Z.parents[0]} != examined head ${I}) \u2014 next sync reconciles the concurrent change`),c("synced",{pushedSha:A,pushedCount:Y.size,mergedCount:C.mergedCount,quarantinedCount:C.quarantineEntries.length+C.resolvedQuarantineEntries.length,...C.mergedPaths.length>0?{mergedPaths:C.mergedPaths}:{},...py(C).length>0?{quarantinedPaths:py(C)}:{},...O,...k});let{pulledCount:_e,pinnedPaths:ie}=await this.applyRemoteChanges(f,h,[...R,...C.mergedWrites].filter(N=>!G.has(N.path)),q.filter(N=>!G.has(N.path)),i);for(let N of C.quarantineEntries)ie.add(N.path);for(let N of T.deferredPaths)ie.add(N);for(let N of G)ie.add(N);if(u.fileMode){for(let N of p)ie.add(N);for(let N of T.remoteOversized)ie.add(N)}return await this.advanceWatermark(e,B,Z.treeSha,h,[...R,...C.mergedWrites,...T.deferredRemoteChanges],v,ie,_.diskBlobShas,u,p),await this.resolveClearedPins(e,v,ie,i,new Set(C.resolvedQuarantineEntries.map(N=>N.path))),c("synced",{pushedSha:A,pulledCount:_e,pushedCount:Y.size,mergedCount:C.mergedCount,quarantinedCount:C.quarantineEntries.length+C.resolvedQuarantineEntries.length,...C.mergedPaths.length>0?{mergedPaths:C.mergedPaths}:{},...py(C).length>0?{quarantinedPaths:py(C)}:{},...O,...k})}catch(l){let u=this.deps.redact??(f=>f);return o.length>0&&s.push(...o),(0,Wz.isAuthError)(l)?c("auth-required",{detail:u(`authentication failed: ${cu(l)} \u2014 the PAT is expired, revoked or under-scoped; update it in the per-device secure storage (R8). Never treated as success.`)}):(i.push(`sync failed: ${u(cu(l))}`),c("error",{detail:u(cu(l))}))}}async flushQuarantine(e,t){if(e.length===0)return!0;let r=this.deps.redact??(s=>s);for(let s of e)t.push(r(`quarantined ${s.path}: ${s.reason}`));let i=this.deps.quarantine;if(i===void 0)return!1;try{if(i.quarantineAll!==void 0)await i.quarantineAll(e);else for(let s of e)await i.quarantine(s);return!0}catch(s){let o=this.deps.redact??(c=>c);return t.push(`quarantine sink failed: ${o(cu(s))} \u2014 files untouched on disk; the conflict re-derives next sync (D17 degradation)`),!1}}async buildTerminalQuarantineEntries(e,t,r,i,s){let o=new Set(i.map(u=>u.path)),c=new Map;try{let u=await(0,Ft.getHeadSha)(this.transport,e.owner,e.repo,e.branch,this.deps.baseURL),f=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,(await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,u,this.deps.baseURL)).treeSha,this.deps.baseURL)).filter(d=>r.has(d.path));for(let d of f)c.set(d.path,await(0,Ft.getBlobText)(this.transport,e.owner,e.repo,d.blobSha,this.deps.baseURL))}catch{}let l=[];for(let[u,f]of r){if(o.has(u))continue;let d=s.get(u),h=d??f,p=d!==void 0&&!(0,da.contentEquals)(d,f),y=typeof h=="string"?(0,vc.extractAssetUid)(h):void 0,g=c.get(u);l.push({repoKey:e.repoKey,path:u,...y!==void 0?{uid:y}:{},reason:`non-fast-forward push failed after ${this.deps.maxPushRetries??Fs.DEFAULT_MAX_PUSH_RETRIES} retries (D16) \u2014 a concurrent writer keeps moving ${e.branch}; base recoverable from git history at ${t.lastSyncedSha}${p?"; the contended push payload was a merged proposal (never applied to disk) \u2014 the merge re-derives next sync":""}`,...typeof h=="string"?{localContent:h}:{localContentBytes:h},...g!==void 0?{remoteContent:g}:{}})}return l}async resolveClearedPins(e,t,r,i,s=new Set){let o=this.deps.quarantine;if(o===void 0||o.markResolved===void 0)return;let c=(t.pinnedPaths??[]).filter(l=>!r.has(l)&&!s.has(l));for(let l of c)try{await o.markResolved?.(e.repoKey,l)}catch(u){let f=this.deps.redact??(d=>d);i.push(`quarantine markResolved failed for ${l}: ${f(cu(u))} \u2014 unresolved-count may overcount until the resolver UI reconciles (CQ4)`)}}async resolveBaseTreeSha(e,t){try{return(await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,t.lastSyncedSha,this.deps.baseURL)).treeSha}catch{return null}}pinLocalChanges(e,t,r,i,s){let o=e.modified.filter(h=>h.basePath!==void 0),c=[...e.added,...e.modified.filter(h=>h.basePath===void 0)],l=new Map;if(s==="pull"){for(let h of o)h.basePath!==void 0&&i.push(h.basePath),r.push(`pull-only: rename (uid ${h.uid??"?"}) ${h.basePath} \u2192 ${h.path} not pushed \u2014 propagates on the next push/Sync (#3473)`);for(let h of e.deleted)i.push(h.path),r.push(`pull-only: delete of ${h.path} not pushed \u2014 propagates on the next push/Sync (#3473)`)}else{for(let h of o)h.basePath!==void 0&&l.set(h.basePath,h.path);for(let h of e.deleted)l.set(h.path,h.path)}let u=[...c,...o,...e.deleted.map(h=>({...h}))],f=new Set(e.deleted.map(h=>h.path)),d=new Map;for(let h of[...c,...s==="pull"?[]:o]){let p=t.get(h.path);p!==void 0&&d.set(h.path,p)}return{localChanges:u,localDeletedPaths:f,pushFilesAll:d,pushDeletionsAll:l,dupUids:e.duplicateUids}}async runPushLoop(e,t,r,i,s,o,c=!1,l=new Set,u="sync",f){let{localChanges:d,localDeletedPaths:h,pushFilesAll:p,pushDeletionsAll:y,dupUids:g}=r,v=this.deps.maxPushRetries??Fs.DEFAULT_MAX_PUSH_RETRIES,_=0,S="",T,I=[],A=[],R=new Map,q=new Set,Y=[],C=GE,O=[],k=new Set,H=[],G=[],B=new Set;for(;;){S=await(0,Ft.getHeadSha)(this.transport,e.owner,e.repo,e.branch,this.deps.baseURL),I=[],A=[],C=GE,O=[],k=new Set,H=[],G=[];let Z,_e=new Set,ie=(t.pinnedPaths?.length??0)>0;if(S!==t.lastSyncedSha||ie||c){this.emitProgress(f,e.repoKey,"pulling-remote");let se=await this.collectRemoteChanges(e,t,S,o,l,s,B);Z=se.headTreeByPath;let be=this.matchLocalVsRemote(d,h,i,se.changes,_e,g,se.headTreeByPath);if(be.conflicts.length>0){if(u==="sync"&&this.emitProgress(f,e.repoKey,"merging"),u!=="sync"){for(let W of be.conflicts){k.add(W.local.path),W.local.basePath!==void 0&&k.add(W.local.basePath);for(let Ee of W.remotes)k.add(Ee.path),Ee.kind==="change"&&H.push(Ee)}G.push(`${u}-only: ${be.conflicts.length} conflict(s) deferred to a full Sync (${be.conflicts.map(W=>W.desc).join("; ")}) \u2014 paths pinned, nothing merged`)}else if(o.fileMode)C=this.resolveFileModeConflicts(e,be.conflicts,i,be.applyWrites,be.applyDeletes);else{if(this.deps.mergeLayer===void 0)return{kind:"conflict",detail:`overlapping change on ${be.conflicts[0].desc} \u2014 merge layer (A2/A3) required; nothing pushed, nothing written`};C=await this.resolveMergeConflicts(e,t,be.conflicts,i)}if(u==="sync")for(let W of be.conflicts)for(let Ee of W.remotes)Ee.path!==W.local.path&&(k.add(Ee.path),Ee.kind==="change"&&H.push(Ee),G.push(`conflict group ${W.desc}: remote change at ${Ee.path} NOT applied \u2014 pinned to re-derive on the next sync (#3477)`))}if(I=be.applyWrites,A=be.applyDeletes,u==="push"&&(I.length>0||A.length>0)){for(let W of I)k.add(W.path),H.push(W);for(let W of A)k.add(W.path);G.push(`push-only: ${I.length+A.length} remote change(s) NOT applied \u2014 pinned to re-derive on the next pull/Sync`),I=[],A=[]}}R=u==="pull"?new Map:new Map([...[...p].filter(([se])=>!_e.has(se)),...C.mergedFiles]),q=new Set,Y=[];for(let[se,be]of y){if(_e.has(be)){Y.push(se);continue}R.has(se)||q.add(se)}if((R.size>0||q.size>0)&&Z===void 0&&(Z=B3(await(0,Ft.getTree)(this.transport,e.owner,e.repo,t.rootTreeSha,this.deps.baseURL))),R.size>0&&Z!==void 0){for(let[se,be]of R){let W=Z.get(se);W!==void 0&&W===await(0,dd.gitBlobSha)(be,this.deps.sha1)&&(R.delete(se),O.push(se))}O.length>0&&s.push(`phantom push skipped: ${O.length} file(s) already identical in remote HEAD (${O.join(", ")}) \u2014 excluded from the commit (#3475)`)}if(q.size>0&&Z!==void 0){for(let se of[...q])Z.has(se)||q.delete(se);R.size===0&&q.size>=Z.size&&(Y.push(...q),G.push(`deletion of ALL ${q.size} remaining file(s) deferred \u2014 GitHub cannot create an empty tree; the deletes re-derive and propagate once the repo has at least one surviving file`),q.clear())}if(R.size===0&&q.size===0)break;let N=new Map;for(let[se,be]of R)if(typeof be=="string")N.set(se,be);else{let W=Kz(be);W!==null&&N.set(se,W)}let j=(0,zz.scanForSecrets)(N);if(j.length>0)return{kind:"secret-detected",detail:`secret-scan: refusing to push \u2014 ${j.map(se=>`${se.path} (${se.kind})`).join(", ")} (R5); remove the secret and re-sync`};try{T=await(0,Gz.restCreateCommit)(this.transport,{owner:e.owner,repo:e.repo,branch:e.branch,files:new Map([...R].map(([se,be])=>[se,Qz(be)])),deletions:[...q],message:this.deps.commitMessage?.(e,R.size,q.size)??`chore(exosync): sync ${R.size} file(s)${q.size>0?`, ${q.size} deletion(s)`:""}`,baseURL:this.deps.baseURL,redact:this.deps.redact});break}catch(se){if(!V3(se))throw se;if(_++,_>v)return{kind:"retry-exhausted",detail:`non-fast-forward push failed after ${v} retries (D16 cap) \u2014 contended files routed to quarantine (D17)`,pushFiles:R,merge:C};s.push(`non-fast-forward push (attempt ${_}/${v}) \u2014 re-pulling and retrying (D16)`)}}return{kind:"done",examinedHead:S,pushedSha:T,applyWrites:I,applyDeletes:A,pushFiles:R,pushedDeletions:T!==void 0?[...q]:[],withheldDeletions:Y,merge:C,remoteOversized:B,alreadyInHead:O,deferredPaths:k,deferredRemoteChanges:H,deferredWarnings:G}}async resolveMergeConflicts(e,t,r,i){let s=this.deps.mergeLayer;if(s===void 0)return GE;let o=new Map(t.files.map(g=>[g.path,g])),c=new Map,l=[],u=[],f=[],d=[],h=0,p=a(g=>typeof g=="string"?g:void 0,"asText"),y=a((g,v,_)=>{let S=p(i.get(g.local.path)),T=p(g.remotes[0]?.content);return{repoKey:e.repoKey,path:g.local.path,...g.local.uid!==void 0?{uid:g.local.uid}:{},reason:v,..._!==void 0?{baseContent:_}:{},...S!==void 0?{localContent:S}:{},...T!==void 0?{remoteContent:T}:{}}},"entry");for(let g of r){let v=o.get(g.local.basePath??g.local.path)??o.get(g.remotes[0]?.path??""),_;if(v!==void 0&&(_=await(0,Ft.getBlobText)(this.transport,e.owner,e.repo,v.blobSha,this.deps.baseURL)),g.remotes.length>1){u.push(y(g,`ambiguous conflict: local change overlaps ${g.remotes.length} remote changes (${g.remotes.map(R=>R.path).join(", ")})`,_));continue}let S=g.remotes[0],T=p(i.get(g.local.path)),I=await s.resolve({path:g.local.path,...g.local.uid!==void 0?{uid:g.local.uid}:{},..._!==void 0?{base:_}:{},...T!==void 0?{local:T}:{},...S.kind==="change"&&typeof S.content=="string"?{remote:S.content}:{}});if(I.action==="quarantine"){u.push(y(g,I.reason,_));continue}h++,d.push(g.local.path);for(let R of I.warnings??[])f.push(`merge(${g.local.path}): ${R}`);let A=S.kind==="change"?S.content:void 0;if(I.content!==A&&c.set(g.local.path,I.content),I.content!==i.get(g.local.path)){let R=(0,vc.extractAssetUid)(I.content)??g.local.uid;l.push({path:g.local.path,kind:"change",content:I.content,blobSha:await(0,dd.gitBlobSha)(I.content,this.deps.sha1),...R!==void 0?{uid:R}:{}})}}return{mergedFiles:c,mergedWrites:l,quarantineEntries:u,resolvedQuarantineEntries:[],mergedCount:h,mergedPaths:d,warnings:f}}resolveFileModeConflicts(e,t,r,i,s){let o=[],c=[];for(let l of t){l.remotes.length>1&&c.push(`file-mode conflict on ${l.local.path} unexpectedly overlaps ${l.remotes.length} remote changes \u2014 resolving against the first`);let u=l.remotes[0],f=r.get(l.local.path);u.kind==="change"?i.push(u):s.push(u),!(l.localIsDelete||f===void 0)&&o.push({repoKey:e.repoKey,path:l.local.path,reason:`file-mode remote-wins (D18): remote ${u.kind==="change"?`version ${u.blobSha}`:"delete"} wins; this is the losing LOCAL version, preserved byte-exact`,...typeof f=="string"?{localContent:f}:{localContentBytes:f}})}return{mergedFiles:new Map,mergedWrites:[],quarantineEntries:[],resolvedQuarantineEntries:o,mergedCount:0,mergedPaths:[],warnings:c}}async applyRemoteChanges(e,t,r,i,s){let o=0,c=new Set,l=a(async(f,d)=>{try{return d?await j3(e,f):await e.read(f)}catch{return}},"tryRead"),u=a(async(f,d)=>{typeof d=="string"?await e.write(f,d):await Xz(e,f,d)},"writeContent");for(let f of r){if(f.content===void 0)continue;if(!$3(f.path)){s.push(`unsafe remote path skipped on pull-apply: ${f.path}`),c.add(f.path);continue}let d=t.get(f.path),h=await l(f.path,typeof(d??f.content)!="string");if(!(0,da.contentEquals)(h,d)){s.push(`pull-apply skipped: ${f.path} changed on disk mid-sync (TOCTOU) \u2014 remote change re-derives next sync`),c.add(f.path);continue}await u(f.path,f.content),o++}for(let f of i){if(!$3(f.path)){s.push(`unsafe remote path skipped on pull-delete: ${f.path}`),c.add(f.path);continue}let d=t.get(f.path);if(d!==void 0){let h=await l(f.path,typeof d!="string");if(h!==void 0&&!(0,da.contentEquals)(h,d)){s.push(`pull-delete skipped: ${f.path} changed on disk mid-sync (TOCTOU) \u2014 delete-vs-modify re-derives next sync`),c.add(f.path);continue}await e.delete(f.path),o++}}return{pulledCount:o,pinnedPaths:c}}async advanceWatermark(e,t,r,i,s,o,c,l,u,f=new Set){let d=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,r,this.deps.baseURL)).filter(p=>u.treeFilter(p)&&!f.has(p.path)),h=Jz(await this.buildWatermarkFiles(e,d,i,s,o,l,u),o,c);await this.deps.watermarkStore.set(e.repoKey,{lastSyncedSha:t,rootTreeSha:r,files:h,...c.size>0?{pinnedPaths:[...c]}:{},...u.fileMode?{spaceKind:"file"}:{}})}async bootstrapWatermark(e,t,r,i){let s=await(0,Ft.getHeadSha)(this.transport,e.owner,e.repo,e.branch,this.deps.baseURL),o=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,s,this.deps.baseURL),c=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,o.treeSha,this.deps.baseURL)).filter(f=>(0,da.isSyncablePath)(f.path));for(let f of c){let d=t.get(f.path);if(d===void 0||await(0,dd.gitBlobSha)(d,this.deps.sha1)!==f.blobSha)return{kind:"settled",outcome:i("full-conflict",{detail:`first-sync: no watermark and local content diverges from remote head at ${f.path} \u2014 A2/A3 scope`})}}let l=c.map(f=>{let d=t.get(f.path),h=typeof d=="string"?(0,vc.extractAssetUid)(d):void 0;return{path:f.path,blobSha:f.blobSha,...h?{uid:h}:{}}}),u={lastSyncedSha:s,rootTreeSha:o.treeSha,files:l};return t.size===c.length?(await this.deps.watermarkStore.set(e.repoKey,u),r.push(`watermark bootstrapped from head ${s} (local tree identical to remote)`),{kind:"settled",outcome:i("synced")}):(r.push(`first-sync (asset mode): local tree (${t.size} files) is a pure superset of remote head ${s} (${c.length} files) \u2014 ${t.size-c.length} local-only addition(s) derive as pushable adds (#3565)`),{kind:"additive-base",base:u})}async collectRemoteChanges(e,t,r,i,s=new Set,o=[],c=new Set){let l=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,r,this.deps.baseURL),u=await(0,Ft.getTree)(this.transport,e.owner,e.repo,l.treeSha,this.deps.baseURL);if(i.fileMode)for(let g of u)i.syncable(g.path)&&!i.treeFilter(g)&&!c.has(g.path)&&(c.add(g.path),o.push(`skipped oversized REMOTE file ${g.path} (${g.size??"?"} bytes over cap) \u2014 excluded from sync symmetrically (Phase C size cap)`));let f=u.filter(g=>i.treeFilter(g)&&!s.has(g.path)),d=t.files.filter(g=>!c.has(g.path)&&!s.has(g.path)),{changed:h,deleted:p}=U3(d,f),y=[];for(let g of h){if(i.fileMode){let _=await(0,Ft.getBlobBytes)(this.transport,e.owner,e.repo,g.blobSha,this.deps.baseURL);y.push({path:g.path,kind:"change",blobSha:g.blobSha,content:_});continue}let v=await(0,Ft.getBlobText)(this.transport,e.owner,e.repo,g.blobSha,this.deps.baseURL);y.push({path:g.path,kind:"change",blobSha:g.blobSha,content:v,uid:(0,vc.extractAssetUid)(v)})}for(let g of p)y.push({path:g.path,kind:"delete",uid:g.uid});return{changes:y,headTreeByPath:B3(u)}}matchLocalVsRemote(e,t,r,i,s,o=new Set,c){let l=new Set,u=[],f=new Map;for(let g of i)g.kind==="change"&&g.uid!==void 0&&f.set(g.uid,(f.get(g.uid)??0)+1);let d=new Set(o);for(let[g,v]of f)v>1&&d.add(g);let h=new Map,p=new Map;for(let g of i){if(g.uid!==void 0&&!d.has(g.uid)){let v=h.get(g.uid)??[];v.push(g),h.set(g.uid,v)}p.set(g.path,g)}for(let g of e){let v=new Set;if(g.uid!==void 0&&!d.has(g.uid))for(let I of h.get(g.uid)??[])I.kind==="change"&&I.path!==g.path&&(c?.has(g.path)===!0||g.basePath!==void 0&&c?.has(g.basePath)===!0)||v.add(I);let _=p.get(g.path);if(_!==void 0&&v.add(_),g.basePath!==void 0){let I=p.get(g.basePath);I!==void 0&&v.add(I)}let S=[],T=!1;for(let I of v){if(T=t.has(g.path)&&!r.has(g.path),T&&I.kind==="delete"){l.add(I);continue}if(!T&&I.kind==="change"&&I.path===g.path&&I.blobSha===g.blobSha){l.add(I),s.add(g.path);continue}if(I.kind==="delete"&&g.basePath!==void 0&&I.path===g.basePath){let A=p.get(g.path);if(A!==void 0&&A.kind==="change"&&A.blobSha===g.blobSha){l.add(I);continue}}S.push(I),l.add(I)}S.length>0&&(u.push({local:g,localIsDelete:T,remotes:S,desc:`${g.uid!==void 0&&!d.has(g.uid)?g.uid:g.path} (local ${T?"delete":"change"} vs remote ${S[0].kind} at ${S[0].path})`}),s.add(g.path))}let y=i.filter(g=>!l.has(g));return{conflicts:u,applyWrites:y.filter(g=>g.kind==="change"),applyDeletes:y.filter(g=>g.kind==="delete")}}async checkRaceWindow(e,t,r,i,s,o,c,l){try{let u=await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,i,this.deps.baseURL),f=(await(0,Ft.getTree)(this.transport,e.owner,e.repo,u.treeSha,this.deps.baseURL)).filter(l.treeFilter),d=r===t.lastSyncedSha?t.files:(await(0,Ft.getTree)(this.transport,e.owner,e.repo,(await(0,Ft.getCommitInfo)(this.transport,e.owner,e.repo,r,this.deps.baseURL)).treeSha,this.deps.baseURL)).filter(l.treeFilter),{changed:h,deleted:p}=U3(d,f);for(let y of h)s.has(y.path)&&c.push(`race-window: concurrent commit ${i} changed ${y.path} between conflict check (head ${r}) and push \u2014 local version won; previous version recoverable from git history`),o.has(y.path)&&c.push(`race-window: concurrent commit ${i} changed ${y.path} which this push DELETED \u2014 the delete won; the concurrent version is recoverable from git history`);for(let y of p)s.has(y.path)&&c.push(`race-window: concurrent commit ${i} deleted ${y.path}; push re-created it`)}catch(u){let f=this.deps.redact??(d=>d);c.push(`race-window check failed: ${f(cu(u))}`)}}async buildWatermarkFiles(e,t,r,i,s,o,c){if(c.fileMode)return t.map(f=>({path:f.path,blobSha:f.blobSha}));let l=new Map;for(let f of i)f.kind==="change"&&f.blobSha!==void 0&&l.set(f.blobSha,f.uid);for(let[f,d]of r){let h=o?.get(f)??await(0,dd.gitBlobSha)(d,this.deps.sha1);l.set(h,typeof d=="string"?(0,vc.extractAssetUid)(d):void 0)}for(let f of s.files)l.has(f.blobSha)||l.set(f.blobSha,f.uid);let u=[];for(let f of t){let d;if(l.has(f.blobSha))d=l.get(f.blobSha);else{let h=await(0,Ft.getBlobText)(this.transport,e.owner,e.repo,f.blobSha,this.deps.baseURL);d=(0,vc.extractAssetUid)(h)}u.push({path:f.path,blobSha:f.blobSha,...d?{uid:d}:{}})}return u}};Fs.SyncEngine=qE});var KE=w(HE=>{"use strict";Object.defineProperty(HE,"__esModule",{value:!0});HE.diff3=Zz;function G3(n,e){let t=n.length,r=e.length,i=Array.from({length:t+1},()=>new Int32Array(r+1));for(let l=t-1;l>=0;l--)for(let u=r-1;u>=0;u--)i[l][u]=n[l]===e[u]?i[l+1][u+1]+1:Math.max(i[l+1][u],i[l][u+1]);let s=new Map,o=0,c=0;for(;o<t&&c<r;)n[o]===e[c]?(s.set(o,c),o++,c++):i[o+1][c]>=i[o][c+1]?o++:c++;return s}a(G3,"lcsMatch");function zE(n,e){if(n.length!==e.length)return!1;for(let t=0;t<n.length;t++)if(n[t]!==e[t])return!1;return!0}a(zE,"sliceEq");function Zz(n,e,t){let r=G3(n,e),i=G3(n,t),s=[],o=0,c=0,l=0;for(;;){let u=o;for(;u<n.length&&!(r.has(u)&&i.has(u));)u++;let f=u<n.length?r.get(u):e.length,d=u<n.length?i.get(u):t.length,h=n.slice(o,u),p=e.slice(c,f),y=t.slice(l,d),g=!zE(p,h),v=!zE(y,h);if(!g&&!v)s.push(...h);else if(!g)s.push(...y);else if(!v)s.push(...p);else if(zE(p,y))s.push(...p);else return{ok:!1,conflict:{base:h,local:p,remote:y}};if(u>=n.length)break;s.push(n[u]),o=u+1,c=f+1,l=d+1}return{ok:!0,merged:s}}a(Zz,"diff3")});var W3=w(md=>{"use strict";Object.defineProperty(md,"__esModule",{value:!0});md.StructuredMerger=void 0;md.splitSections=my;var q3=KE(),eH=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/,hd="exo__Instance_class";function pd(n){if(n===null||typeof n!="object")return!0;if(Array.isArray(n))return n.every(pd);let e=Object.getPrototypeOf(n);return e!==Object.prototype&&e!==null?!1:Object.values(n).every(pd)}a(pd,"isPlainValue");function ha(n,e){if(n===e)return!0;if(n===null||e===null||n===void 0||e===void 0||typeof n!="object"||typeof e!="object"||Array.isArray(n)!==Array.isArray(e))return!1;if(Array.isArray(n)&&Array.isArray(e))return n.length!==e.length?!1:n.every((s,o)=>ha(s,e[o]));let t=n,r=e,i=Object.keys(t);return i.length!==Object.keys(r).length?!1:i.every(s=>ha(t[s],r[s]))}a(ha,"deepEqual");function Ec(n){return typeof n=="string"?`s:${n}`:`j:${JSON.stringify(n)}`}a(Ec,"setKey");function ui(n){return n==null?[]:Array.isArray(n)?n:[n]}a(ui,"toElements");function tH(n,e,t){let r=new Set(ui(n).map(Ec)),i=ui(e),s=ui(t),o=new Set(i.map(Ec)),c=new Set(s.map(Ec)),l=a(d=>o.has(d)&&c.has(d)||o.has(d)&&!r.has(d)||c.has(d)&&!r.has(d),"keep"),u=[],f=new Set;for(let d of[...i,...s]){let h=Ec(d);f.has(h)||!l(h)||(f.add(h),u.push(d))}return u}a(tH,"mergeSet");function rH(n,e,t){let r=[],i=[],s=new Set;for(let c of[...Object.keys(n),...Object.keys(e),...Object.keys(t)])s.has(c)||(s.add(c),i.push(c));let o={};for(let c of i){let l=n[c],u=e[c],f=t[c];if(!pd(l)||!pd(u)||!pd(f))return{ok:!1,reason:`frontmatter key "${c}" contains a non-plain value (Date?) \u2014 the codec must round-trip scalars as strings (CORE_SCHEMA contract)`};if(Array.isArray(l)||Array.isArray(u)||Array.isArray(f)){if(!(c in e)&&!(c in t))continue;let d=tH(l,u,f),h=new Set(ui(l).map(Ec)),p=ui(u).some(g=>!h.has(Ec(g))),y=ui(f).some(g=>!h.has(Ec(g)));p&&y&&!ha(ui(u),ui(f))&&r.push(`both sides added values to multi-valued key "${c}" \u2014 union kept (D20)`),d.length>0&&(o[c]=d);continue}if(ha(u,f)){u!==void 0&&(o[c]=u);continue}if(ha(u,l)){f!==void 0&&(o[c]=f);continue}if(ha(f,l)){u!==void 0&&(o[c]=u);continue}return{ok:!1,reason:`frontmatter key "${c}" changed differently on both sides`}}return{ok:!0,value:o,warnings:r}}a(rH,"mergeFrontmatter");var nH=/^(```|~~~)/,iH=/^#{1,6}\s/;function my(n){let e=n.split(`
464
464
  `),t=[],r=null,i="",s=!1,o=a(()=>{r!==null&&t.push({heading:i,text:r.join(`
465
465
  `)})},"flush");for(let c of e){if(nH.test(c.trimStart())&&(s=!s),!s&&iH.test(c)){o(),r=[c],i=c.trim();continue}r===null&&(r=[],i=""),r.push(c)}return o(),t}a(my,"splitSections");function QE(n){return n.split(/\n{2,}/)}a(QE,"splitParagraphs");function sH(n){return n.join(`
466
466
 
@@ -775,7 +775,7 @@ Next steps:
775
775
  `),process.stdout.write(` File: ${e.file}
776
776
  `),process.stdout.write(` Commit: ${e.sha}
777
777
  `),process.stdout.write(` URL: ${e.url}
778
- `)),process.exit(0)}catch(e){let t=e instanceof Error?e:new Error(String(e)),r=new vi;t.message=r.redact(t.message),t.stack&&(t.stack=r.redact(t.stack)),le.handle(t)}})}a(Mie,"restPushCommand");var jo=require("node:fs"),A4=require("node:crypto"),Ei=J(require("node:path"));var Ti=J(tt());var jie=a(async n=>{let e=await A4.webcrypto.subtle.digest("SHA-1",n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")},"nodeSha1"),$ie={parse:a(n=>Nt.load(n,{schema:Nt.CORE_SCHEMA}),"parse"),stringify:a(n=>Nt.dump(n,{schema:Nt.CORE_SCHEMA,lineWidth:-1}),"stringify")};function Uie(n,e){if(n.tokenFromGh===!0)return vi.resolveGhToken(e.ghTokenRunner);let t=e.env??process.env,r=n.token||t.GITHUB_TOKEN||t.GH_TOKEN||"";if(r.length===0)throw new Error("A GitHub token is required (private sync units read as 404 without one). Use --token-from-gh, --token <pat>, or set GITHUB_TOKEN / GH_TOKEN.");return r}a(Uie,"resolveToken");function Bie(n){let e=a(r=>Ei.join(n,r),"abs"),t=a(async(r,i)=>{let s;try{s=await jo.promises.readdir(r,{withFileTypes:!0})}catch{return}for(let o of s){let c=Ei.join(r,o.name);if(o.isDirectory()){if(o.name===".git")continue;await t(c,i)}else o.isFile()&&i.push(Ei.relative(n,c).split(Ei.sep).join("/"))}},"walk");return{async list(){let r=[];return(0,jo.existsSync)(n)&&await t(n,r),r},read:a(r=>jo.promises.readFile(e(r),"utf-8"),"read"),async readBinary(r){return new Uint8Array(await jo.promises.readFile(e(r)))},async write(){throw new Error("exosync-parity is read-only \u2014 write refused")},async delete(){throw new Error("exosync-parity is read-only \u2014 delete refused")}}}a(Bie,"nodeLocalFilesPort");function mA(n){let e=new dt(n),t=new Ti.SpaceSpecAccumulator;for(let r of e.getAllFiles()){let i=e.getFrontmatter(r);if(!i)continue;let s=(0,Ti.classifySpaceDeclaration)(i,r.path);if(s.kind==="not-space"||(s.warning!==void 0&&t.warnings.push(s.warning),s.kind==="skip"))continue;let o=t.offer(s.candidate);o!==null&&(0,jo.existsSync)(Ei.join(n,o.localPath))&&t.commit(s.candidate)}return{specs:t.specs,warnings:t.warnings}}a(mA,"collectVaultSpecs");function Vie(n,e){for(let t of n.repos){let r=t.headSha!==void 0?` @${t.headSha.slice(0,7)}`:"";e(`${t.repoKey}${r}: ${t.status} \u2014 ${t.inParity}/${t.filesChecked} in parity, M2 diffs ${t.m2SemanticDiffs}, accounted ${t.accountedCount}, M1 violations ${t.m1Violations.length}${t.attachmentHashSetIdentical!==void 0?`, attachment hash-set ${t.attachmentHashSetIdentical?"identical":"DIFFERS"}`:""}`),t.detail!==void 0&&e(` ${t.detail}`);for(let i of t.warnings)e(` warn: ${i}`);for(let i of t.discrepancies)e(` ${i.cls}: ${i.path}${i.detail!==void 0?` (${i.detail})`:""}`);for(let i of t.m1Violations)e(` M1 VIOLATION: ${i.path} \u2014 ${i.detail}`)}e((0,Ti.summarizeParityRound)(n))}a(Vie,"printHumanReport");async function Gie(n,e={}){let t=e.out??(y=>console.log(y)),r=Ei.resolve(n.vault);if(!(0,jo.existsSync)(r))throw new Error(`Vault path does not exist: ${r}`);let i=Uie(n,e),s=new vi({token:i,...n.apiBase!==void 0?{apiBase:n.apiBase}:{}}),o=e.transportFactory?.(i,n.apiBase)??s.transport(),{specs:c,warnings:l}=mA(r);for(let y of l)t(`warn: ${y}`);if(c.length===0)return t("Nothing to check \u2014 no materialized AssetSpaces with a GitHub source found in this vault."),2;let u=n.configDir??".obsidian",f=Ei.join(r,u,"plugins","exocortex",Ti.WATERMARK_STORE_FILENAME),d=new Ti.FileWatermarkStore({read:a(async()=>{try{return await jo.promises.readFile(f,"utf-8")}catch{return null}},"read"),writeAtomic:a(async()=>{throw new Error("exosync-parity: watermark access is read-only by contract")},"writeAtomic")}),h=new Ti.ParityValidator({transport:o,sha1:jie,localFilesFor:a(y=>Bie(Ei.join(r,y.localPath)),"localFilesFor"),watermarks:{get:a(y=>d.get(y),"get")},yaml:$ie,redact:a(y=>s.redact(y),"redact"),...n.apiBase!==void 0?{baseURL:n.apiBase}:{}});t(`ExoSync parity check: ${c.length} repo(s), vault ${r}`);let p=await h.runRound(c,{trigger:"standalone"});return n.json===!0?t(JSON.stringify(p,null,2)):Vie(p,t),p.vacuous?2:p.ok?0:1}a(Gie,"runExosyncParity");function I4(){return new Ae("exosync-parity").description("ExoSync M1/M2 parity report: compare materialized sync units against their remote heads (read-only; RFC 4e4dc453 Phase E)").requiredOption("--vault <path>","Vault root path").option("--config-dir <name>","Obsidian config dir name (watermark location)",".obsidian").option("--json","Print the full round record as JSON").option("--token <pat>","GitHub PAT (or env GITHUB_TOKEN / GH_TOKEN). Prefer --token-from-gh.").option("--token-from-gh","Resolve the PAT via `gh auth token`").option("--api-base <url>","GitHub API base (testing)").action(async n=>{try{process.exitCode=await Gie(n)}catch(e){le.handle(e,{command:"exosync-parity"}),process.exitCode=1}})}a(I4,"exosyncParityCommand");var Dr=require("node:fs"),R4=require("node:crypto"),xn=J(require("node:path"));var Fr=J(tt());var x4=a(async n=>{let e=await R4.webcrypto.subtle.digest("SHA-1",n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")},"nodeSha1"),qie={parse:a(n=>Nt.load(n,{schema:Nt.CORE_SCHEMA}),"parse"),stringify:a(n=>Nt.dump(n,{schema:Nt.CORE_SCHEMA,lineWidth:-1}),"stringify")};function Wie(n,e){if(n.tokenFromGh===!0)return vi.resolveGhToken(e.ghTokenRunner);let t=e.env??process.env,r=n.token||t.GITHUB_TOKEN||t.GH_TOKEN||"";if(r.length===0)throw new Error("A GitHub token is required (private sync units read as 404 and push needs write scope). Use --token-from-gh, --token <pat>, or set GITHUB_TOKEN / GH_TOKEN.");return r}a(Wie,"resolveToken");function zie(n){let e=/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/.exec(n.trim());if(e===null)throw new Error(`Invalid quarantine repo URL (expected https://github.com/<owner>/<repo>): ${n}`);return{owner:e[1],repo:e[2]}}a(zie,"parseGitHubRepoUrl");function Hie(n){let e=a(i=>xn.join(n,i),"abs"),t=a(async(i,s)=>{let o;try{o=await Dr.promises.readdir(i,{withFileTypes:!0})}catch{return}for(let c of o){let l=xn.join(i,c.name);if(c.isDirectory()){if(c.name===".git")continue;await t(l,s)}else c.isFile()&&s.push(xn.relative(n,l).split(xn.sep).join("/"))}},"walk"),r=a(async(i,s)=>{let o=xn.dirname(i);await Dr.promises.mkdir(o,{recursive:!0});let c=`${i}.local.tmp`;await s(c),await Dr.promises.rename(c,i)},"writeAtomic");return{async list(){let i=[];return(0,Dr.existsSync)(n)&&await t(n,i),i},read:a(i=>Dr.promises.readFile(e(i),"utf-8"),"read"),async write(i,s){await r(e(i),o=>Dr.promises.writeFile(o,s,"utf-8"))},async delete(i){await Dr.promises.rm(e(i),{force:!0})},async readBinary(i){return new Uint8Array(await Dr.promises.readFile(e(i)))},async writeBinary(i,s){let o=s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);await r(e(i),c=>Dr.promises.writeFile(c,Buffer.from(o)))}}}a(Hie,"nodeLocalFilesPort");function Kie(n){return{async read(){try{return await Dr.promises.readFile(n,"utf-8")}catch{return null}},async writeAtomic(e){await Dr.promises.mkdir(xn.dirname(n),{recursive:!0});let t=`${n}.local.tmp`;await Dr.promises.writeFile(t,e,"utf-8"),await Dr.promises.rename(t,n)}}}a(Kie,"nodeWatermarkFileIO");function Qie(n){return{async check(e){let t=xn.join(n,e.localPath);if(!(0,Dr.existsSync)(t))return{fullyMaterialized:!1,reason:`mount folder ${e.localPath} does not exist`};let r=0;try{r=(await Dr.promises.readdir(t)).length}catch{return{fullyMaterialized:!1,reason:`mount folder ${e.localPath} is not readable`}}return r===0&&e.spaceKind!=="file"?{fullyMaterialized:!1,reason:`mount folder ${e.localPath} is empty (mid-mount?)`}:{fullyMaterialized:!0}}}}a(Qie,"nodeMaterializationCheck");function Xie(n,e){let t=n.pushedSha!==void 0?` \u2192@${n.pushedSha.slice(0,7)}`:"";e(`${n.repoKey}${t}: ${n.status} \u2014 pulled ${n.pulledCount}, pushed ${n.pushedCount}, merged ${n.mergedCount}, quarantined ${n.quarantinedCount}${(n.pushedDeletes?.length??0)>0?`, deleted ${n.pushedDeletes.length}`:""}`),n.detail!==void 0&&e(` ${n.detail}`);for(let r of n.warnings)e(` warn: ${r}`);(n.deferredPaths?.length??0)>0&&e(` deferred (\u2192 full sync): ${n.deferredPaths.join(", ")}`),(n.deferredDeletes?.length??0)>0&&e(` deferred deletes: ${n.deferredDeletes.join(", ")}`)}a(Xie,"printRepoResult");function Yie(n){return n==="conflict"||n==="full-conflict"||n==="retry-exhausted"||n==="busy"||n==="auth-required"||n==="error"}a(Yie,"isFailureStatus");async function Jie(n,e,t={}){let r=t.out??(_=>console.log(_)),i=xn.resolve(e.vault);if(!(0,Dr.existsSync)(i))throw new Error(`Vault path does not exist: ${i}`);let s=Wie(e,t),o=new vi({token:s,...e.apiBase!==void 0?{apiBase:e.apiBase}:{}}),c=t.transportFactory?.(s,e.apiBase)??o.transport(),{specs:l,warnings:u}=mA(i);for(let _ of u)r(`warn: ${_}`);if(l.length===0)return r("Nothing to sync \u2014 no materialized AssetSpaces with a GitHub source found in this vault."),2;let f=e.configDir??".obsidian",d=xn.join(i,f,"plugins","exocortex",Fr.WATERMARK_STORE_FILENAME),h,p=e.quarantineRepo?.trim()??"";if(p.length>0){let{owner:_,repo:S}=zie(p);h=new Fr.SyncedQuarantineStore({transport:(0,Fr.withRateLimitBackoff)(c),sha1:x4,owner:_,repo:S,branch:Fr.SYNC_BRANCH,redact:a(T=>o.redact(T),"redact")})}let y=new Fr.SyncEngine({transport:c,watermarkStore:new Fr.FileWatermarkStore(Kie(d)),materializationCheck:Qie(i),localFilesFor:a(_=>Hie(xn.join(i,_.localPath)),"localFilesFor"),sha1:x4,redact:a(_=>o.redact(_),"redact"),commitMessage:a((_,S,T=0)=>`exosync: ${S} change(s)${T>0?`, ${T} deletion(s)`:""} (CLI)`,"commitMessage"),mergeLayer:new Fr.GatedStructuredMerger(new Fr.StructuredMerger(qie)),...h!==void 0?{quarantine:h}:{},...e.apiBase!==void 0?{baseURL:e.apiBase}:{}});r(`ExoSync ${n}: ${l.length} repo(s), vault ${i}${h!==void 0?" (quarantine configured)":""}`);let g=(0,Fr.orderChildrenFirst)(l),v=await y.syncAll(g,n);if(e.json===!0)r(JSON.stringify(v,null,2));else{for(let S of v)Xie(S,r);let _=v.reduce((S,T)=>({pulled:S.pulled+T.pulledCount,pushed:S.pushed+T.pushedCount,merged:S.merged+T.mergedCount,quarantined:S.quarantined+T.quarantinedCount}),{pulled:0,pushed:0,merged:0,quarantined:0});r(`Summary: ${v.length} repo(s) \u2014 pulled ${_.pulled}, pushed ${_.pushed}, merged ${_.merged}, quarantined ${_.quarantined}`)}return v.some(_=>Yie(_.status))?1:0}a(Jie,"runExosyncSync");function gA(n){return n.requiredOption("--vault <path>","Vault root path").option("--config-dir <name>","Obsidian config dir name (watermark location)",".obsidian").option("--quarantine-repo <url>","Quarantine repo URL (https://github.com/<owner>/<repo>) \u2014 required for FileSpaces").option("--token <pat>","GitHub PAT (or env GITHUB_TOKEN / GH_TOKEN). Prefer --token-from-gh.").option("--token-from-gh","Resolve the PAT via `gh auth token`").option("--json","Print the full per-repo result array as JSON").option("--api-base <url>","GitHub API base (testing)")}a(gA,"withSyncOptions");function yA(n){return async e=>{try{process.exitCode=await Jie(n,e)}catch(t){le.handle(t,{command:`exosync ${n}`}),process.exitCode=1}}}a(yA,"makeDirectionAction");function P4(){let n=new Ae("exosync").description("ExoSync over the GitHub REST API: sync/pull/push the materialized AssetSpace set (CLI parity with the plugin; RFC 4e4dc453 Phase B). Read-only divergence check: `exosync-parity`.");return gA(n.command("sync").description("Full pull\u2192merge\u2192push cycle for every materialized repo")).action(yA("sync")),gA(n.command("pull").description("Apply remote changes only (nothing leaves the device; local changes re-derive)")).action(yA("pull")),gA(n.command("push").description("Send the local delta only (remote changes are pinned to re-derive on the next pull/sync)")).action(yA("push")),n}a(P4,"exosyncCommand");function C4(n){let e=new Ae;return e.name("exocortex").description("CLI tool for Exocortex knowledge management system").version(n??"16.96.8"),e.addCommand(LM()),e.addCommand(qM()),e.addCommand(Ik()),e.addCommand(Pk()),e.addCommand(iM()),e.addCommand(Fk()),e.addCommand(Lk()),e.addCommand($k()),e.addCommand(aM()),e.addCommand(gM()),e.addCommand(bM()),e.addCommand(EM()),e.addCommand(FM()),e.addCommand(s4()),e.addCommand(f4()),e.addCommand(d4()),e.addCommand(m4()),e.addCommand(_4()),e.addCommand(T4()),e.addCommand(I4()),e.addCommand(P4()),e}a(C4,"createProgram");C4().parse();0&&(module.exports={createProgram});
778
+ `)),process.exit(0)}catch(e){let t=e instanceof Error?e:new Error(String(e)),r=new vi;t.message=r.redact(t.message),t.stack&&(t.stack=r.redact(t.stack)),le.handle(t)}})}a(Mie,"restPushCommand");var jo=require("node:fs"),A4=require("node:crypto"),Ei=J(require("node:path"));var Ti=J(tt());var jie=a(async n=>{let e=await A4.webcrypto.subtle.digest("SHA-1",n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")},"nodeSha1"),$ie={parse:a(n=>Nt.load(n,{schema:Nt.CORE_SCHEMA}),"parse"),stringify:a(n=>Nt.dump(n,{schema:Nt.CORE_SCHEMA,lineWidth:-1}),"stringify")};function Uie(n,e){if(n.tokenFromGh===!0)return vi.resolveGhToken(e.ghTokenRunner);let t=e.env??process.env,r=n.token||t.GITHUB_TOKEN||t.GH_TOKEN||"";if(r.length===0)throw new Error("A GitHub token is required (private sync units read as 404 without one). Use --token-from-gh, --token <pat>, or set GITHUB_TOKEN / GH_TOKEN.");return r}a(Uie,"resolveToken");function Bie(n){let e=a(r=>Ei.join(n,r),"abs"),t=a(async(r,i)=>{let s;try{s=await jo.promises.readdir(r,{withFileTypes:!0})}catch{return}for(let o of s){let c=Ei.join(r,o.name);if(o.isDirectory()){if(o.name===".git")continue;await t(c,i)}else o.isFile()&&i.push(Ei.relative(n,c).split(Ei.sep).join("/"))}},"walk");return{async list(){let r=[];return(0,jo.existsSync)(n)&&await t(n,r),r},read:a(r=>jo.promises.readFile(e(r),"utf-8"),"read"),async readBinary(r){return new Uint8Array(await jo.promises.readFile(e(r)))},async write(){throw new Error("exosync-parity is read-only \u2014 write refused")},async delete(){throw new Error("exosync-parity is read-only \u2014 delete refused")}}}a(Bie,"nodeLocalFilesPort");function mA(n){let e=new dt(n),t=new Ti.SpaceSpecAccumulator;for(let r of e.getAllFiles()){let i=e.getFrontmatter(r);if(!i)continue;let s=(0,Ti.classifySpaceDeclaration)(i,r.path);if(s.kind==="not-space"||(s.warning!==void 0&&t.warnings.push(s.warning),s.kind==="skip"))continue;let o=t.offer(s.candidate);o!==null&&(0,jo.existsSync)(Ei.join(n,o.localPath))&&t.commit(s.candidate)}return{specs:t.specs,warnings:t.warnings}}a(mA,"collectVaultSpecs");function Vie(n,e){for(let t of n.repos){let r=t.headSha!==void 0?` @${t.headSha.slice(0,7)}`:"";e(`${t.repoKey}${r}: ${t.status} \u2014 ${t.inParity}/${t.filesChecked} in parity, M2 diffs ${t.m2SemanticDiffs}, accounted ${t.accountedCount}, M1 violations ${t.m1Violations.length}${t.attachmentHashSetIdentical!==void 0?`, attachment hash-set ${t.attachmentHashSetIdentical?"identical":"DIFFERS"}`:""}`),t.detail!==void 0&&e(` ${t.detail}`);for(let i of t.warnings)e(` warn: ${i}`);for(let i of t.discrepancies)e(` ${i.cls}: ${i.path}${i.detail!==void 0?` (${i.detail})`:""}`);for(let i of t.m1Violations)e(` M1 VIOLATION: ${i.path} \u2014 ${i.detail}`)}e((0,Ti.summarizeParityRound)(n))}a(Vie,"printHumanReport");async function Gie(n,e={}){let t=e.out??(y=>console.log(y)),r=Ei.resolve(n.vault);if(!(0,jo.existsSync)(r))throw new Error(`Vault path does not exist: ${r}`);let i=Uie(n,e),s=new vi({token:i,...n.apiBase!==void 0?{apiBase:n.apiBase}:{}}),o=e.transportFactory?.(i,n.apiBase)??s.transport(),{specs:c,warnings:l}=mA(r);for(let y of l)t(`warn: ${y}`);if(c.length===0)return t("Nothing to check \u2014 no materialized AssetSpaces with a GitHub source found in this vault."),2;let u=n.configDir??".obsidian",f=Ei.join(r,u,"plugins","exocortex",Ti.WATERMARK_STORE_FILENAME),d=new Ti.FileWatermarkStore({read:a(async()=>{try{return await jo.promises.readFile(f,"utf-8")}catch{return null}},"read"),writeAtomic:a(async()=>{throw new Error("exosync-parity: watermark access is read-only by contract")},"writeAtomic")}),h=new Ti.ParityValidator({transport:o,sha1:jie,localFilesFor:a(y=>Bie(Ei.join(r,y.localPath)),"localFilesFor"),watermarks:{get:a(y=>d.get(y),"get")},yaml:$ie,redact:a(y=>s.redact(y),"redact"),...n.apiBase!==void 0?{baseURL:n.apiBase}:{}});t(`ExoSync parity check: ${c.length} repo(s), vault ${r}`);let p=await h.runRound(c,{trigger:"standalone"});return n.json===!0?t(JSON.stringify(p,null,2)):Vie(p,t),p.vacuous?2:p.ok?0:1}a(Gie,"runExosyncParity");function I4(){return new Ae("exosync-parity").description("ExoSync M1/M2 parity report: compare materialized sync units against their remote heads (read-only; RFC 4e4dc453 Phase E)").requiredOption("--vault <path>","Vault root path").option("--config-dir <name>","Obsidian config dir name (watermark location)",".obsidian").option("--json","Print the full round record as JSON").option("--token <pat>","GitHub PAT (or env GITHUB_TOKEN / GH_TOKEN). Prefer --token-from-gh.").option("--token-from-gh","Resolve the PAT via `gh auth token`").option("--api-base <url>","GitHub API base (testing)").action(async n=>{try{process.exitCode=await Gie(n)}catch(e){le.handle(e,{command:"exosync-parity"}),process.exitCode=1}})}a(I4,"exosyncParityCommand");var Dr=require("node:fs"),R4=require("node:crypto"),xn=J(require("node:path"));var Fr=J(tt());var x4=a(async n=>{let e=await R4.webcrypto.subtle.digest("SHA-1",n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength));return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")},"nodeSha1"),qie={parse:a(n=>Nt.load(n,{schema:Nt.CORE_SCHEMA}),"parse"),stringify:a(n=>Nt.dump(n,{schema:Nt.CORE_SCHEMA,lineWidth:-1}),"stringify")};function Wie(n,e){if(n.tokenFromGh===!0)return vi.resolveGhToken(e.ghTokenRunner);let t=e.env??process.env,r=n.token||t.GITHUB_TOKEN||t.GH_TOKEN||"";if(r.length===0)throw new Error("A GitHub token is required (private sync units read as 404 and push needs write scope). Use --token-from-gh, --token <pat>, or set GITHUB_TOKEN / GH_TOKEN.");return r}a(Wie,"resolveToken");function zie(n){let e=/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/.exec(n.trim());if(e===null)throw new Error(`Invalid quarantine repo URL (expected https://github.com/<owner>/<repo>): ${n}`);return{owner:e[1],repo:e[2]}}a(zie,"parseGitHubRepoUrl");function Hie(n){let e=a(i=>xn.join(n,i),"abs"),t=a(async(i,s)=>{let o;try{o=await Dr.promises.readdir(i,{withFileTypes:!0})}catch{return}for(let c of o){let l=xn.join(i,c.name);if(c.isDirectory()){if(c.name===".git")continue;await t(l,s)}else c.isFile()&&s.push(xn.relative(n,l).split(xn.sep).join("/"))}},"walk"),r=a(async(i,s)=>{let o=xn.dirname(i);await Dr.promises.mkdir(o,{recursive:!0});let c=`${i}.local.tmp`;await s(c),await Dr.promises.rename(c,i)},"writeAtomic");return{async list(){let i=[];return(0,Dr.existsSync)(n)&&await t(n,i),i},read:a(i=>Dr.promises.readFile(e(i),"utf-8"),"read"),async write(i,s){await r(e(i),o=>Dr.promises.writeFile(o,s,"utf-8"))},async delete(i){await Dr.promises.rm(e(i),{force:!0})},async readBinary(i){return new Uint8Array(await Dr.promises.readFile(e(i)))},async writeBinary(i,s){let o=s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);await r(e(i),c=>Dr.promises.writeFile(c,Buffer.from(o)))}}}a(Hie,"nodeLocalFilesPort");function Kie(n){return{async read(){try{return await Dr.promises.readFile(n,"utf-8")}catch{return null}},async writeAtomic(e){await Dr.promises.mkdir(xn.dirname(n),{recursive:!0});let t=`${n}.local.tmp`;await Dr.promises.writeFile(t,e,"utf-8"),await Dr.promises.rename(t,n)}}}a(Kie,"nodeWatermarkFileIO");function Qie(n){return{async check(e){let t=xn.join(n,e.localPath);if(!(0,Dr.existsSync)(t))return{fullyMaterialized:!1,reason:`mount folder ${e.localPath} does not exist`};let r=0;try{r=(await Dr.promises.readdir(t)).length}catch{return{fullyMaterialized:!1,reason:`mount folder ${e.localPath} is not readable`}}return r===0&&e.spaceKind!=="file"?{fullyMaterialized:!1,reason:`mount folder ${e.localPath} is empty (mid-mount?)`}:{fullyMaterialized:!0}}}}a(Qie,"nodeMaterializationCheck");function Xie(n,e){let t=n.pushedSha!==void 0?` \u2192@${n.pushedSha.slice(0,7)}`:"";e(`${n.repoKey}${t}: ${n.status} \u2014 pulled ${n.pulledCount}, pushed ${n.pushedCount}, merged ${n.mergedCount}, quarantined ${n.quarantinedCount}${(n.pushedDeletes?.length??0)>0?`, deleted ${n.pushedDeletes.length}`:""}`),n.detail!==void 0&&e(` ${n.detail}`);for(let r of n.warnings)e(` warn: ${r}`);(n.deferredPaths?.length??0)>0&&e(` deferred (\u2192 full sync): ${n.deferredPaths.join(", ")}`),(n.deferredDeletes?.length??0)>0&&e(` deferred deletes: ${n.deferredDeletes.join(", ")}`)}a(Xie,"printRepoResult");function Yie(n){return n==="conflict"||n==="full-conflict"||n==="retry-exhausted"||n==="busy"||n==="auth-required"||n==="error"}a(Yie,"isFailureStatus");async function Jie(n,e,t={}){let r=t.out??(_=>console.log(_)),i=xn.resolve(e.vault);if(!(0,Dr.existsSync)(i))throw new Error(`Vault path does not exist: ${i}`);let s=Wie(e,t),o=new vi({token:s,...e.apiBase!==void 0?{apiBase:e.apiBase}:{}}),c=t.transportFactory?.(s,e.apiBase)??o.transport(),{specs:l,warnings:u}=mA(i);for(let _ of u)r(`warn: ${_}`);if(l.length===0)return r("Nothing to sync \u2014 no materialized AssetSpaces with a GitHub source found in this vault."),2;let f=e.configDir??".obsidian",d=xn.join(i,f,"plugins","exocortex",Fr.WATERMARK_STORE_FILENAME),h,p=e.quarantineRepo?.trim()??"";if(p.length>0){let{owner:_,repo:S}=zie(p);h=new Fr.SyncedQuarantineStore({transport:(0,Fr.withRateLimitBackoff)(c),sha1:x4,owner:_,repo:S,branch:Fr.SYNC_BRANCH,redact:a(T=>o.redact(T),"redact")})}let y=new Fr.SyncEngine({transport:c,watermarkStore:new Fr.FileWatermarkStore(Kie(d)),materializationCheck:Qie(i),localFilesFor:a(_=>Hie(xn.join(i,_.localPath)),"localFilesFor"),sha1:x4,redact:a(_=>o.redact(_),"redact"),commitMessage:a((_,S,T=0)=>`exosync: ${S} change(s)${T>0?`, ${T} deletion(s)`:""} (CLI)`,"commitMessage"),mergeLayer:new Fr.GatedStructuredMerger(new Fr.StructuredMerger(qie)),...h!==void 0?{quarantine:h}:{},...e.apiBase!==void 0?{baseURL:e.apiBase}:{}});r(`ExoSync ${n}: ${l.length} repo(s), vault ${i}${h!==void 0?" (quarantine configured)":""}`);let g=(0,Fr.orderChildrenFirst)(l),v=await y.syncAll(g,n);if(e.json===!0)r(JSON.stringify(v,null,2));else{for(let S of v)Xie(S,r);let _=v.reduce((S,T)=>({pulled:S.pulled+T.pulledCount,pushed:S.pushed+T.pushedCount,merged:S.merged+T.mergedCount,quarantined:S.quarantined+T.quarantinedCount}),{pulled:0,pushed:0,merged:0,quarantined:0});r(`Summary: ${v.length} repo(s) \u2014 pulled ${_.pulled}, pushed ${_.pushed}, merged ${_.merged}, quarantined ${_.quarantined}`)}return v.some(_=>Yie(_.status))?1:0}a(Jie,"runExosyncSync");function gA(n){return n.requiredOption("--vault <path>","Vault root path").option("--config-dir <name>","Obsidian config dir name (watermark location)",".obsidian").option("--quarantine-repo <url>","Quarantine repo URL (https://github.com/<owner>/<repo>) \u2014 required for FileSpaces").option("--token <pat>","GitHub PAT (or env GITHUB_TOKEN / GH_TOKEN). Prefer --token-from-gh.").option("--token-from-gh","Resolve the PAT via `gh auth token`").option("--json","Print the full per-repo result array as JSON").option("--api-base <url>","GitHub API base (testing)")}a(gA,"withSyncOptions");function yA(n){return async e=>{try{process.exitCode=await Jie(n,e)}catch(t){le.handle(t,{command:`exosync ${n}`}),process.exitCode=1}}}a(yA,"makeDirectionAction");function P4(){let n=new Ae("exosync").description("ExoSync over the GitHub REST API: sync/pull/push the materialized AssetSpace set (CLI parity with the plugin; RFC 4e4dc453 Phase B). Read-only divergence check: `exosync-parity`.");return gA(n.command("sync").description("Full pull\u2192merge\u2192push cycle for every materialized repo")).action(yA("sync")),gA(n.command("pull").description("Apply remote changes only (nothing leaves the device; local changes re-derive)")).action(yA("pull")),gA(n.command("push").description("Send the local delta only (remote changes are pinned to re-derive on the next pull/sync)")).action(yA("push")),n}a(P4,"exosyncCommand");function C4(n){let e=new Ae;return e.name("exocortex").description("CLI tool for Exocortex knowledge management system").version(n??"16.96.9"),e.addCommand(LM()),e.addCommand(qM()),e.addCommand(Ik()),e.addCommand(Pk()),e.addCommand(iM()),e.addCommand(Fk()),e.addCommand(Lk()),e.addCommand($k()),e.addCommand(aM()),e.addCommand(gM()),e.addCommand(bM()),e.addCommand(EM()),e.addCommand(FM()),e.addCommand(s4()),e.addCommand(f4()),e.addCommand(d4()),e.addCommand(m4()),e.addCommand(_4()),e.addCommand(T4()),e.addCommand(I4()),e.addCommand(P4()),e}a(C4,"createProgram");C4().parse();0&&(module.exports={createProgram});
779
779
  /*! Bundled license information:
780
780
 
781
781
  reflect-metadata/Reflect.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitelev/exocortex-cli",
3
- "version": "16.96.8",
3
+ "version": "16.96.9",
4
4
  "description": "CLI tool for Exocortex knowledge management system - SPARQL queries, task management, and more",
5
5
  "main": "dist/index.js",
6
6
  "bin": {