@inkeep/open-knowledge 0.20.0-beta.1 → 0.20.0-beta.10

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 (75) hide show
  1. package/dist/assets/skills/discovery/SKILL.md +2 -2
  2. package/dist/assets/skills/packs/codebase-wiki/SKILL.md +1 -1
  3. package/dist/assets/skills/packs/entity-vault/SKILL.md +6 -1
  4. package/dist/assets/skills/project/SKILL.md +69 -455
  5. package/dist/assets/skills/project/references/anti-patterns.md +33 -0
  6. package/dist/assets/skills/project/references/cadence-and-logs.md +17 -0
  7. package/dist/assets/skills/project/references/components-and-visuals.md +53 -0
  8. package/dist/assets/skills/project/references/conflict-resolution.md +28 -0
  9. package/dist/assets/skills/project/references/corpus-qa.md +14 -0
  10. package/dist/assets/skills/project/references/doc-editing.md +11 -0
  11. package/dist/assets/skills/project/references/folder-model.md +42 -0
  12. package/dist/assets/skills/project/references/ingest-and-sources.md +24 -0
  13. package/dist/assets/skills/project/references/linking.md +16 -0
  14. package/dist/assets/skills/project/references/media-and-assets.md +14 -0
  15. package/dist/assets/skills/project/references/preview.md +51 -0
  16. package/dist/assets/skills/project/references/setup.md +2 -2
  17. package/dist/assets/skills/project/references/template-authoring.md +65 -0
  18. package/dist/assets/skills/project/references/workflow-guides.md +30 -0
  19. package/dist/assets/skills/project/references/writing.md +9 -0
  20. package/dist/assets/skills/write-skill/SKILL.md +16 -5
  21. package/dist/cli.mjs +54 -54
  22. package/dist/constants-CrTxXw1w.mjs +2 -0
  23. package/dist/{dist-CcBhqiSK.mjs → dist-CQqrcHvR.mjs} +26 -22
  24. package/dist/{dist-DVWyQ2rE.mjs → dist-DTGzP9at.mjs} +1 -1
  25. package/dist/{gh-detect-DsccWGZs.mjs → gh-detect-BDIdc7oG.mjs} +2 -2
  26. package/dist/index.mjs +1 -1
  27. package/dist/init-BSCPsyJd.mjs +1 -0
  28. package/dist/{init-C0B404am.mjs → init-C-8HqD7u.mjs} +6 -6
  29. package/dist/{loader-DT4U0oyV.mjs → loader-Cj9_FOBM.mjs} +3 -3
  30. package/dist/loader-NjsXkmf7.mjs +1 -0
  31. package/dist/preview-BXlCCBCC.mjs +1 -0
  32. package/dist/{preview-BUN-sd_X.mjs → preview-CUcmvmH1.mjs} +2 -2
  33. package/dist/public/assets/{ActivityModeContent-BS_Y62XF.js → ActivityModeContent-DGw5iUid.js} +1 -1
  34. package/dist/public/assets/{DocumentContext-BzU_wuZ1.js → DocumentContext-CmO1rPM6.js} +16 -16
  35. package/dist/public/assets/{GraphPanel-EZGWljSP.js → GraphPanel-BVt0SfrM.js} +1 -1
  36. package/dist/public/assets/{ManagedArtifactProperties-D2EjV-Hv.js → ManagedArtifactProperties-Cr8eMUCF.js} +1 -1
  37. package/dist/public/assets/{PropertyPanel-CctJB0ZN.js → PropertyPanel-ze_4e3n_.js} +1 -1
  38. package/dist/public/assets/{SettingsDialogBody-DzkJTs5S.js → SettingsDialogBody-hP9Vzn5G.js} +2 -2
  39. package/dist/public/assets/{SkillEditorActions-CnqozQbp.js → SkillEditorActions-Y_e1zC_b.js} +1 -1
  40. package/dist/public/assets/{SourceEditor-Mgjjq3HZ.js → SourceEditor-4T4loRia.js} +2 -2
  41. package/dist/public/assets/{TerminalPanel-DiJi11zw.js → TerminalPanel-C9rmhBG2.js} +2 -2
  42. package/dist/public/assets/{config-validation-events-8rtpnIAB.js → config-validation-events-CA8jFSci.js} +4 -4
  43. package/dist/public/assets/{dist-C0uDGnS5.js → dist-Dst_hB5H.js} +102 -102
  44. package/dist/public/assets/{documents-events-BTsmrZJT.js → documents-events-DMS5a4By.js} +1 -1
  45. package/dist/public/assets/index-BHFFl2Q_.css +1 -0
  46. package/dist/public/assets/index-DNKaMY7F.js +2004 -0
  47. package/dist/public/assets/{keyboard-shortcuts-BzwnpNd_.js → keyboard-shortcuts-DGu1nhPQ.js} +1 -1
  48. package/dist/public/assets/{open-managed-artifact-tab-VuHt1k6e.js → open-managed-artifact-tab-Bvt3X7yV.js} +1 -1
  49. package/dist/public/assets/{prop-types-D6SQBoDq.js → prop-types-Cf7ylXsu.js} +1 -1
  50. package/dist/public/assets/{selection-context-Rr9JEzTX.js → selection-context-kDVHDAV2.js} +1 -1
  51. package/dist/public/assets/{skill-actions-SUqrJBew.js → skill-actions-CQ-n4sOB.js} +1 -1
  52. package/dist/public/assets/{skills-api-F2HCxVlt.js → skills-api-q4V5pwth.js} +1 -1
  53. package/dist/public/assets/{target-navigation-intent-BrunJmhI.js → target-navigation-intent-CCRb_XMp.js} +1 -1
  54. package/dist/public/assets/{typing-burst-detector-BmNkqfX8.js → typing-burst-detector-zGrvqSf8.js} +2 -2
  55. package/dist/public/index.html +15 -15
  56. package/dist/{repair-launch-json-CkcWlQSx.mjs → repair-launch-json-Bdz75Fp8.mjs} +2 -2
  57. package/dist/{repair-mcp-configs-VpKh2oVC.mjs → repair-mcp-configs-Cc8mxsS2.mjs} +2 -2
  58. package/dist/{repair-skills-aa6PY9M2.mjs → repair-skills-BaI9FXaD.mjs} +2 -2
  59. package/dist/repair-skills-DO_ayx3E.mjs +1 -0
  60. package/dist/server-lock-8Lv6A-Xa-iDqi_bbE.mjs +1 -0
  61. package/dist/{server-lock-CN2YHwpP-CemdeDui.mjs → server-lock-CN2YHwpP-COM23IWb.mjs} +42 -42
  62. package/dist/{src-BkOgJBOh.mjs → src-C2V2v9_F.mjs} +2 -2
  63. package/dist/start-CDfxD4Ac.mjs +1 -0
  64. package/dist/{start-qU-nkZGw.mjs → start-DtoTEBi4.mjs} +2 -2
  65. package/dist/{write-project-skill-DF8Mypd7.mjs → write-project-skill-CsHCvxax.mjs} +3 -3
  66. package/package.json +1 -1
  67. package/dist/constants-BDz_rgpj.mjs +0 -2
  68. package/dist/init-CCyX3r7f.mjs +0 -1
  69. package/dist/loader-BbfPz7Hr.mjs +0 -1
  70. package/dist/preview-CWA1TRnG.mjs +0 -1
  71. package/dist/public/assets/index-i9A7tPDf.js +0 -2004
  72. package/dist/public/assets/index-xDiw2wLq.css +0 -1
  73. package/dist/repair-skills-CUAuz35w.mjs +0 -1
  74. package/dist/server-lock-8Lv6A-Xa-C_9VS9L6.mjs +0 -1
  75. package/dist/start-Dis0CHWS.mjs +0 -1
@@ -1,4 +1,4 @@
1
- import{a as __require$2,n as __esmMin,o as __toCommonJS,r as __exportAll,s as __toESM$2,t as __commonJSMin$2}from"./chunk-C94x7I9S.mjs";import{$ as CONFIG_DOC_NAME_PROJECT_LOCAL,$a as array,$i as parseTemplateFile,$n as SkillFileDeleteSuccessSchema,$r as UploadAssetSuccessSchema,$t as LocalOpEmbeddingsSetKeyRequestSchema,A as AgentWriteSuccessSchema,Aa as DEFAULT_EMBEDDINGS_BASE_URL,Ai as getAgentCanonicalDescriptors,An as SKILL_STATE_TARGETS,Ao as $constructor,Ar as SyncResolveConflictRequestSchema,At as ForwardLinksSuccessSchema,B as CC1DerivedViewPayloadSchema,Ba as detectRemovedKeys,Bi as isManagedArtifactDocName,Bn as SeedApplyRequestSchema,Br as TemplateGetSuccessSchema,Bt as InstallSkillRequestSchema,C as AgentPatchRequestSchema,Ca as validateDocName,Ci as emptyInstalledSkills,Cn as RollbackRequestSchema,Co as parseAsync,Cr as SkillUpdateSuccessSchema,Ct as EDITOR_PROJECT_SKILL_ROOT,D as AgentWriteMdRequestSchema,Da as Fragment,Di as extractFrontmatterTags,Dn as SKILL_CONTENT_ROOT,Do as clone,Dr as SuggestLinksSuccessSchema,Dt as FolderConfigGetSuccessSchema,E as AgentUndoSuccessSchema,Ea as PluginKey,Ei as expandTagToHierarchy,En as SANDBOXED_HTML_EXTENSIONS,Eo as prettifyError,Er as StreamingProblemEventSchema,Et as EmptyRequestSchema,F as BridgeInvariantViolationError,Fa as LOCAL_DIR,Fi as instantiateDoc,Fn as SYSTEM_DOC_NAME,Fr as TEMPLATE_IDENTITY_KEY,Ft as HistorySuccessSchema,G as CC1_CHANNEL_CONFIG_VALIDATION_REJECTED,Ga as validatePatchScopes,Gi as mergeThreeWay,Gn as ServerInfoSuccessSchema,Gr as TemplatesListSuccessSchema,Gt as LINKABLE_ASSET_EXTENSIONS,H as CC1ServerInfoPayloadSchema,Ha as isKnownConfigError,Hi as isValidBranchName,Hn as SeedListPacksSuccessSchema,Hr as TemplateMoveSuccessSchema,Ht as InstalledAgentsSuccessSchema,I as BridgeMergeContentLossError,Ia as OK_PROJECT_MARKER,Ii as isBranchNotFoundGitError,In as SaveVersionRequestSchema,Ir as TEMPLATE_NAME_REGEX,It as HistoryVersionSuccessSchema,J as CC1_CONTRACT_VERSION,Ji as parseGlobalSkillBundleDoc,Jn as SharePublishNameCheckResponseSchema,Jr as TestRescanFilesSuccessSchema,Jt as LocalOpAuthHostRequestSchema,K as CC1_CHANNEL_DISK_ACK,Ka as withConfigSpan,Ki as normalizeBridge,Kn as ShareConstructUrlRequestSchema,Kr as TestFlushGitSuccessSchema,Kt as LinkGraphSuccessSchema,L as CC1BranchSwitchedPayloadSchema,Li as isFrontmatterValueEmpty,Ln as SaveVersionSuccessSchema,Lr as TagsForNameSuccessSchema,Lt as HubsSuccessSchema,M as BacklinkCountsSuccessSchema,Ma as DEFAULT_LOGS_MAX_BYTES,Mi as getParseHealth,Mn as SKILL_TARGETS_REL,Mo as require_dist$1,Mr as SyncStatusSchema,Mt as FrontmatterPatchSuccessSchema,N as BacklinksSuccessSchema,Na as DEFAULT_SPANS_MAX_BYTES,Ni as getWikiLinkText,Nr as SyncTriggerRequestSchema,Nt as FrontmatterValueSchema,O as AgentWriteMdSuccessSchema,Oa as CONFIG_SCHEMA_MAJOR_PATH,Oi as fnv1aDigest,On as SKILL_NAME_REGEX,Oo as defineLazy,Or as SyncConflictContentSuccessSchema,Ot as FolderConfigPutRequestSchema,P as BranchInfoResponseSchema,Pa as DEFAULT_TELEMETRY_ATTRIBUTE_DENYLIST,Pi as iconFromClientName,Pn as SUPPORTED_DOC_EXTENSIONS,Pr as SyncTriggerSuccessSchema,Q as CONFIG_DOC_NAME_PROJECT,Qi as parseSkillTargets,Qn as SkillDeleteSuccessSchema,Qr as UA_PATTERNS,Qt as LocalOpEmbeddingsMutationSuccessSchema,R as CC1ConfigIgnoreNestedErrorPayloadSchema,Ra as addConfigSpanEvent,Ri as isHiddenDocName,Rn as SearchRequestSchema,Rr as TagsListSuccessSchema,Rt as INLINE_RENDERABLE_EXTENSIONS,S as AgentBurstDiffSuccessSchema,Sa as unwrapFrontmatterFences,Si as emitToleranceFire,Sn as RescueListSuccessSchema,So as parse$1,Sr as SkillUpdateRequestSchema,St as EDITOR_PROJECT_CONFIG_PATH,T as AgentUndoRequestSchema,Ta as getSchema,Ti as encodeShareUrl,Tn as SANDBOXED_HTML_CSP,To as safeParseAsync$1,Tr as SpawnCursorSuccessSchema,Tt as EmbedDetectSuccessSchema,U as CC1_CHANNEL_BRANCH_SWITCHED,Ua as locateIssue,Ui as managedArtifactDocNameFromContentTarget,Un as SeedPlanSuccessSchema,Ur as TemplatePutRequestSchema,Ut as InstalledSkillsSchema,V as CC1DiskAckPayloadSchema,Va as humanFormat,Vi as isOrphanMode,Vn as SeedApplySuccessSchema,Vr as TemplateMoveRequestSchema,Vt as InstallSkillSuccessSchema,W as CC1_CHANNEL_CONFIG_IGNORE_NESTED_ERROR,Wa as toConfigIssue,Wi as mediaKindForSidebarAssetExtension,Wn as SemanticIndexStatusSchema,Wr as TemplatePutSuccessSchema,Wt as LINEAGE_EPOCH_KEY,X as CONFIG_DOC_NAMES,Xa as _enum,Xi as parseManagedArtifactName,Xn as SharePublishRequestSchema,Xr as TrashCleanupRequestSchema,Xt as LocalOpAuthStatusSuccessSchema,Y as CLIENT_VERSION_HEADER,Ya as ZodOptional$1,Yi as parseInstalledSkills,Yn as SharePublishOwnersResponseSchema,Yr as TestResetSuccessSchema,Yt as LocalOpAuthSetIdentityRequestSchema,Z as CONFIG_DOC_NAME_OKIGNORE,Za as _null,Zi as parseProjectSkillBundleDoc,Zn as SharePublishResponseSchema,Zr as TrashCleanupSuccessSchema,Zt as LocalOpCloneRequestSchema,_ as AGENT_ICON_COLORS,_a as splitLeadingDocBoundary,_i as createWorkspaceSearchDocument,_n as PagesSuccessSchema,_r as SkillTargetsPutRequestSchema,_t as DocumentListSuccessSchema,a as acquireProcessLock,aa as readFmMap,ai as assertNeverProblemType,an as MCP_SERVER_NAME,ao as looseObject,ar as SkillInstallStateSuccessSchema,at as CreateFolderRequestSchema,b as AdvisoryWarningSchema,ba as toBridgeInvariantLog,bi as detectFmRegion,bn as RenamePathRequestSchema,bo as $ZodObject,br as SkillUninstallRequestSchema,bt as DuplicatePathSuccessSchema,c as isValidLockPid,ca as resolveAssetProjectPath,ci as classifyWikiLinkTarget,cn as MetricsParseHealthSuccessSchema,co as optional,cr as SkillMoveSuccessSchema,ct as CreatePageSuccessSchema,da as searchWorkspaceCorpus,di as composeTemplateFile,dn as OrphansSuccessSchema,do as string,dr as SkillRestoreRequestSchema,ea as prependFrontmatter,ei as UploadRequestSchema,en as LocalOpOkInitRequestSchema,eo as boolean,er as SkillFileGetSuccessSchema,et as CONFIG_DOC_NAME_USER,f as readServerLock,fa as serializeFrontmatterMap,fi as containsXmlTag,fn as PREVIEW_EMBED_STARTERS,fo as union,fr as SkillRestoreSuccessSchema,ga as skillLiveDocName,gi as createWorkspaceSearchCorpus,gn as PageHeadingsSuccessSchema,go as toJSONSchema,gr as SkillTargetsGetSuccessSchema,gt as DeletePathSuccessSchema,h as updateProcessLockPort,hi as createTagInTextRegex,hn as PROTOCOL_VERSION,ho as datetime,hr as SkillTargetEditorSchema,ht as DeletePathRequestSchema,ia as projectSkillContentDocName,ii as applyPatchToFm,in as MANAGED_ARTIFACT_SCOPES,io as literal,ir as SkillInstallRequestSchema,it as ClientLogsSuccessSchema,j as ApiConfigSuccessSchema,ja as DEFAULT_EMBEDDINGS_MODEL,ji as getHeadingSlug,jn as SKILL_STATE_VERSION_RE,jr as SyncResolveConflictSuccessSchema,jt as FrontmatterPatchRequestSchema,k as AgentWriteRequestSchema,ka as ConfigSchema$1,ki as formatFileSize,kn as SKILL_STATE_REL,ko as normalizeParams,kr as SyncConflictsSuccessSchema,kt as FolderConfigPutSuccessSchema,la as resolveInternalHref,ln as MetricsReconciliationSuccessSchema,lo as preprocess,lr as SkillPutRequestSchema,lt as DEFAULT_DEDUP_MODE,m as releaseServerLock,ma as sharedExtensions,mi as createCodeFenceTracker,mn as PROJECT_SKILL_EDITOR_IDS,mr as SkillStateSchema,mt as DeadLinksSuccessSchema,n as RUNTIME_VERSION,na as projectFull,ni as applyFastDiff,nn as MANAGED_ARTIFACT_PREFIX_SKILL,no as discriminatedUnion,nr as SkillFilePutSuccessSchema,nt as CheckoutResponseSchema,o as acquireServerLock,oa as reattachLeadingDocBoundary,oi as classifyGitAuthError,on as MarkdownManager,oo as number,or as SkillInstallSuccessSchema,ot as CreateFolderSuccessSchema,p as releaseProcessLock,pa as setToleranceTelemetryHook,pi as createBasenameIndex,pn as PREVIEW_THEME_TOKENS,po as unknown,pr as SkillScopeSchema,pt as DOCUMENT_OPEN_BYTE_LIMIT,q as CC1_CHANNEL_SERVER_INFO,qa as withConfigSpanSync,qi as parseFrontmatterYaml,qn as ShareConstructUrlResponseSchema,qr as TestRescanBacklinksSuccessSchema,qt as LocalOpAuthEmptySuccessSchema,ra as projectMergeBoundarySpace,ri as applyIncrementalDiff,rn as MANAGED_ARTIFACT_PREFIX_TEMPLATE,ro as intersection,rr as SkillGetSuccessSchema,rt as ClientLogsRequestSchema,s as isProcessAlive,sa as renderInventoryFooter,si as classifyMarkdownHref,sn as MetricsAgentPresenceSuccessSchema,so as object$1,sr as SkillMoveRequestSchema,st as CreatePageRequestSchema,t as ProcessLockCollisionError,ta as previewEmbedFence,ti as WorkspaceSuccessSchema,tn as LocalOpOkInitResponseSchema,to as custom,tr as SkillFilePutRequestSchema,tt as CheckoutRequestSchema,u as readProcessLock,ua as resolveSkillBundleWikiTarget,ui as colorFromSeed,un as ORPHAN_MODES,uo as record,ur as SkillPutSuccessSchema,va as stripFrontmatter,vi as defaultScheduler,vn as PrincipalSuccessSchema,vo as describe$1,vr as SkillTargetsPutSuccessSchema,vt as DocumentReadSuccessSchema,w as AgentPatchSuccessSchema,wa as withFences,wi as emptySkillState,wn as RollbackSuccessSchema,wo as safeParse$1,wr as SkillsListSuccessSchema,wt as EXECUTABLE_BLOCKLIST_EXTENSIONS,x as AgentActivitySuccessSchema,xa as toWikiLinkSlug,xi as displayNameFromClientName,xn as RenamePathSuccessSchema,xo as $ZodType,xr as SkillUninstallSuccessSchema,y as ASSET_EXTENSIONS,ya as tagsMatchingPrefix,yi as detectAppliedToleranceClasses,yn as ProblemDetailsSchema,yo as meta$1,yr as SkillTargetsSchema,yt as DuplicatePathRequestSchema,z as CC1ConfigValidationRejectedPayloadSchema,za as applyPatchToDocument,zn as SearchSuccessSchema,zr as TemplateDeleteSuccessSchema,zt as INSTALLED_SKILLS_REL}from"./server-lock-CN2YHwpP-CemdeDui.mjs";import{a as metrics,c as SpanStatusCode,i as propagation,l as SpanKind,n as init_esm$2,o as diag,r as trace,s as context,t as esm_exports$2}from"./esm-BS2W3Uzl.mjs";import{a as simpleGit,i as esm_default,n as createGitInstance,o as require_src$15,r as withParentLock,t as applyGitEnv}from"./git-handle-DY9lXoT3-Cmzgvwd8.mjs";import{t as createPatch}from"./libesm-Ob3yvbRV.mjs";import{n as mimes,t as build_default}from"./build-DCHzh6iE.mjs";import{t as require_yazl}from"./yazl-Docqgl6q.mjs";import{t as b1}from"./chunk-YNYSPYQ5-gU4-j5DO.mjs";import{a as c,c as h,d as m,f as p,h as x,i as b,l as i,m as v,n as C,o as d,p as u,r as a,s as f,t as $$1,u as l}from"./chunk-GFQRA5P5-DbAN9IDm.mjs";import{A as gt,B as wt,C as _i$1,D as da$1,E as bt,F as pe,H as zi$1,I as qi,L as us$1,M as ma$1,N as mt$1,O as di$1,P as pa$1,S as X$1,T as bl,V as xi$1,_ as Ti$1,a as Fi$1,b as W$1,c as M,d as P,f as Pt$1,g as T,h as Sl,i as En$1,j as he,k as ga$1,l as Nl,m as Se,n as Bi$1,o as Fs$1,p as R,r as Ci$1,s as G$1,t as Al,u as Oi$1,v as V,w as be,x as Wi$1,y as Vi$1,z as wl}from"./chunk-FEIOJCZD-NzTooVTc.mjs";import{a as d$1,c as m$1,d as y,i as c$1,l as p$1,n as N,o as f$1,r as P$1,s as h$1,t as $$2,u as v$1}from"./chunk-XHM67O4N-C_wCK9HT.mjs";import{n as l$1,r as o,t as h$2}from"./chunk-R6VWJ2ZL-BVeTwIsz.mjs";import{r as o$1}from"./chunk-CWQS3NFK-BkE4vqrf.mjs";import"./chunk-DXB73IDG-F_tmy-Lz.mjs";import{n as d$2,t as _$1}from"./chunk-5QMZ5MUS-BwpNU33k.mjs";import{n as u$1,t as b$1}from"./chunk-A5O5YHGN-DApqA6Ow.mjs";import{n,r,t as c$2}from"./chunk-OJDRYQWQ-CmrD0Dg2.mjs";import{r as x$1,t as a$1}from"./chunk-24IMIIXA-DaS5XS55.mjs";import{n as n$1}from"./chunk-3THT3N7L-B1WzJUh4.mjs";import{t as n$2}from"./chunk-44UOCSGV-BZ6LfyW2.mjs";import{t as import_websocket_server$1}from"./wrapper-BZO_sIci.mjs";import{createRequire}from"node:module";import{execFile,spawn,spawnSync}from"node:child_process";import*as I from"node:fs";import{appendFileSync,chmodSync,closeSync,cpSync,createReadStream,createWriteStream,existsSync,linkSync,lstatSync,mkdirSync,mkdtempSync,openSync,readFile,readFileSync,readSync,readdirSync,readlinkSync,realpathSync,renameSync,rmSync,rmdirSync,statSync,symlinkSync,unlinkSync,writeFileSync}from"node:fs";import*as U from"node:path";import{basename,dirname,extname,isAbsolute,join,normalize,posix,relative,resolve,sep,win32}from"node:path";import{homedir,hostname,platform,tmpdir}from"node:os";import{URLSearchParams as URLSearchParams$1,fileURLToPath}from"node:url";import{Transform,Writable}from"node:stream";import{access,constants as constants$1,lstat,mkdir,readFile as readFile$1,readdir,realpath,rename,stat as stat$1,unlink,writeFile}from"node:fs/promises";import crypto$1 from"crypto";import crypto$1$1,{createHash,randomUUID as randomUUID$1,webcrypto as webcrypto$1}from"node:crypto";import*as zlib from"zlib";import{Readable as Readable$1}from"stream";import{pipeline}from"node:stream/promises";import{setTimeout as setTimeout$1}from"node:timers/promises";import{promisify}from"node:util";import{Http2ServerRequest,constants as constants$2}from"http2";import{AsyncLocalStorage}from"node:async_hooks";import{lookup}from"node:dns";import{createServer}from"node:http";const WRITER_ID_RE=/^(agent-[^/]+|principal-[^/]+|file-system|git-upstream|openknowledge-service)$/;function classifyGitEntry(e,t,s){let g;try{g=statSync(e)}catch(t){let s=t.code;return s===`ENOENT`||s===`ENOTDIR`?{kind:`absent`}:{kind:`inaccessible`,gitPath:e,cause:t}}let S=computeProjectSubPath(t,s);if(g.isDirectory())return{kind:`directory`,path:e,projectSubPath:S};if(g.isFile()){let s;try{s=readFileSync(e,`utf-8`).trim()}catch(t){return{kind:`malformed-pointer`,gitPath:e,target:``,cause:t}}let g=s.match(/^gitdir:\s*(.+)$/);return g?{kind:`linked`,path:resolve(t,g[1]),gitPath:e,projectSubPath:S}:{kind:`malformed-pointer`,gitPath:e,target:``}}return{kind:`absent`}}function computeProjectSubPath(e,t){let s=relative(e,t);return s===``||s===`.`||s.startsWith(`..`)||isAbsolute(s)?``:s}function findAncestorGitEntry(e){let t=homedir(),s=resolve(e),g=64;for(let e=0;e<64;e++){if(s===t)return null;let e=dirname(s);if(e===s||e===t)return null;let g=resolve(e,`.git`);try{let t=statSync(g);if(t.isDirectory()||t.isFile())return{gitPath:g,workTreeRoot:e}}catch(e){let t=e.code;t!==`ENOENT`&&t!==`ENOTDIR`&&console.warn(`[shadow-repo-layout] Cannot stat ${g} (${t??`unknown`}); skipping ancestor`)}s=e}return null}function resolveGitDirDetailed(e){let t=resolve(e),s=classifyGitEntry(resolve(t,`.git`),t,t);if(s.kind!==`absent`)return s;let g=findAncestorGitEntry(t);return g===null?{kind:`absent`}:classifyGitEntry(g.gitPath,g.workTreeRoot,t)}function resolveGitDir(e){let t=resolveGitDirDetailed(e);return t.kind===`directory`||t.kind===`linked`?t.path:null}function resolveShadowDir(e){let t=resolveGitDirDetailed(e);switch(t.kind){case`directory`:return resolve(t.path,shadowSubdirName(t.projectSubPath));case`linked`:if(!existsSync(t.path))throw new MalformedGitPointerError(t.gitPath,t.path);return resolve(t.path,shadowSubdirName(t.projectSubPath));case`malformed-pointer`:throw new MalformedGitPointerError(t.gitPath,t.target,{cause:t.cause});case`inaccessible`:throw new GitDirAccessError(t.gitPath,{cause:t.cause});case`absent`:return resolve(e,`.git/ok`)}}function shadowSubdirName(e){return e===``?`ok`:`ok-${slugifyShadowSubPath(e)}`}function slugifyShadowSubPath(e){let t=e.split(sep).join(`-`).replace(/\/+/g,`-`).replace(/[^A-Za-z0-9._-]/g,`_`).replace(/^\.+/,`_`),s=64;if(t.length<=64)return t||`sub`;let g=djb2(e).toString(16).padStart(8,`0`);return`${t.slice(0,55)}-${g}`}function djb2(e){let t=5381;for(let s=0;s<e.length;s++)t=t*33+e.charCodeAt(s)>>>0;return t}var MalformedGitPointerError=class extends Error{gitPointerPath;resolvedTarget;constructor(e,t,s){let g=t?`references a missing or unreadable gitdir at ${t}`:`is unreadable or has no valid gitdir: pointer`;super(`\`.git\` pointer at ${e} ${g}. Run \`git worktree prune\` from the source repo and try again.`,s),this.name=`MalformedGitPointerError`,this.gitPointerPath=e,this.resolvedTarget=t}},GitDirAccessError=class extends Error{gitPath;constructor(e,t){let s=t?.cause!==void 0&&t.cause!==null&&typeof t.cause==`object`&&`code`in t.cause&&typeof t.cause.code==`string`?` (${t.cause.code})`:``;super(`Cannot access \`.git\` at ${e}${s}. Check filesystem permissions and that the volume is mounted.`,t),this.name=`GitDirAccessError`,this.gitPath=e}};function getShadowRepoPath(e){let t;try{t=resolveShadowDir(e)}catch(e){if(e instanceof MalformedGitPointerError||e instanceof GitDirAccessError)return null;throw e}return existsSync(resolve(t,`HEAD`))?t:null}function getWipRefPattern(e){return`refs/wip/${e}/`}const OK_CONTRIBUTORS_PREFIX=`ok-contributors: `;function parseContributors(e){if(!e)return[];let t=[];for(let s of e.split(`
1
+ import{a as __require$2,n as __esmMin,o as __toCommonJS,r as __exportAll,s as __toESM$2,t as __commonJSMin$2}from"./chunk-C94x7I9S.mjs";import{$ as CONFIG_DOC_NAME_PROJECT,$i as parseSkillTargets,$n as SkillDeleteSuccessSchema,$r as UA_PATTERNS,$t as LocalOpEmbeddingsMutationSuccessSchema,A as AgentWriteSuccessSchema,Aa as ConfigSchema$1,Ai as formatFileSize,An as SKILL_STATE_REL,Ao as normalizeParams,Ar as SyncConflictsSuccessSchema,At as FolderConfigPutSuccessSchema,B as CC1ConfigValidationRejectedPayloadSchema,Ba as applyPatchToDocument,Bn as SearchSuccessSchema,Br as TemplateDeleteSuccessSchema,Bt as INSTALLED_SKILLS_REL,C as AgentPatchRequestSchema,Ca as unwrapFrontmatterFences,Ci as emitToleranceFire,Cn as RescueListSuccessSchema,Co as parse$1,Cr as SkillUpdateRequestSchema,Ct as EDITOR_PROJECT_CONFIG_PATH,D as AgentWriteMdRequestSchema,Da as PluginKey,Di as expandTagToHierarchy,Dn as SANDBOXED_HTML_EXTENSIONS,Do as prettifyError,Dr as StreamingProblemEventSchema,Dt as EmptyRequestSchema,E as AgentUndoSuccessSchema,Ea as getSchema,Ei as encodeShareUrl,En as SANDBOXED_HTML_CSP,Eo as safeParseAsync$1,Er as SpawnCursorSuccessSchema,Et as EmbedDetectSuccessSchema,F as BridgeInvariantViolationError,Fa as DEFAULT_TELEMETRY_ATTRIBUTE_DENYLIST,Fi as iconFromClientName,Fn as SUPPORTED_DOC_EXTENSIONS,Fr as SyncTriggerSuccessSchema,G as CC1_CHANNEL_CONFIG_IGNORE_NESTED_ERROR,Ga as toConfigIssue,Gi as mediaKindForSidebarAssetExtension,Gn as SemanticIndexStatusSchema,Gr as TemplatePutSuccessSchema,Gt as LINEAGE_EPOCH_KEY,H as CC1DiskAckPayloadSchema,Ha as humanFormat,Hi as isOrphanMode,Hn as SeedApplySuccessSchema,Hr as TemplateMoveRequestSchema,Ht as InstallSkillSuccessSchema,I as BridgeMergeContentLossError,Ia as LOCAL_DIR,Ii as instantiateDoc,In as SYSTEM_DOC_NAME,Ir as TEMPLATE_IDENTITY_KEY,It as HistorySuccessSchema,J as CC1_CHANNEL_SERVER_INFO,Ja as withConfigSpanSync,Ji as parseFrontmatterYaml,Jn as ShareConstructUrlResponseSchema,Jr as TestRescanBacklinksSuccessSchema,Jt as LocalOpAuthEmptySuccessSchema,K as CC1_CHANNEL_CONFIG_VALIDATION_REJECTED,Ka as validatePatchScopes,Ki as mergeThreeWay,Kn as ServerInfoSuccessSchema,Kr as TemplatesListSuccessSchema,Kt as LINKABLE_ASSET_EXTENSIONS,L as BrokenLinkSchema,La as OK_PROJECT_MARKER,Li as isBranchNotFoundGitError,Ln as SaveVersionRequestSchema,Lr as TEMPLATE_NAME_REGEX,Lt as HistoryVersionSuccessSchema,M as BacklinkCountsSuccessSchema,Ma as DEFAULT_EMBEDDINGS_MODEL,Mi as getHeadingSlug,Mn as SKILL_STATE_VERSION_RE,Mr as SyncResolveConflictSuccessSchema,Mt as FrontmatterPatchRequestSchema,N as BacklinksSuccessSchema,Na as DEFAULT_LOGS_MAX_BYTES,Ni as getParseHealth,Nn as SKILL_TARGETS_REL,No as require_dist$1,Nr as SyncStatusSchema,Nt as FrontmatterPatchSuccessSchema,O as AgentWriteMdSuccessSchema,Oa as Fragment,Oi as extractFrontmatterTags,On as SKILL_CONTENT_ROOT,Oo as clone,Or as SuggestLinksSuccessSchema,Ot as FolderConfigGetSuccessSchema,P as BranchInfoResponseSchema,Pa as DEFAULT_SPANS_MAX_BYTES,Pi as getWikiLinkText,Pr as SyncTriggerRequestSchema,Pt as FrontmatterValueSchema,Q as CONFIG_DOC_NAME_OKIGNORE,Qa as _null,Qi as parseProjectSkillBundleDoc,Qn as SharePublishResponseSchema,Qr as TrashCleanupSuccessSchema,Qt as LocalOpCloneRequestSchema,R as CC1BranchSwitchedPayloadSchema,Ri as isFrontmatterValueEmpty,Rn as SaveVersionSuccessSchema,Rr as TagsForNameSuccessSchema,Rt as HubsSuccessSchema,S as AgentBurstDiffSuccessSchema,Sa as toWikiLinkSlug,Si as displayNameFromClientName,Sn as RenamePathSuccessSchema,So as $ZodType,Sr as SkillUninstallSuccessSchema,T as AgentUndoRequestSchema,Ta as withFences,Ti as emptySkillState,Tn as RollbackSuccessSchema,To as safeParse$1,Tr as SkillsListSuccessSchema,Tt as EXECUTABLE_BLOCKLIST_EXTENSIONS,U as CC1ServerInfoPayloadSchema,Ua as isKnownConfigError,Ui as isValidBranchName,Un as SeedListPacksSuccessSchema,Ur as TemplateMoveSuccessSchema,Ut as InstalledAgentsSuccessSchema,V as CC1DerivedViewPayloadSchema,Va as detectRemovedKeys,Vi as isManagedArtifactDocName,Vn as SeedApplyRequestSchema,Vr as TemplateGetSuccessSchema,Vt as InstallSkillRequestSchema,W as CC1_CHANNEL_BRANCH_SWITCHED,Wa as locateIssue,Wi as managedArtifactDocNameFromContentTarget,Wn as SeedPlanSuccessSchema,Wr as TemplatePutRequestSchema,Wt as InstalledSkillsSchema,X as CLIENT_VERSION_HEADER,Xa as ZodOptional$1,Xi as parseInstalledSkills,Xn as SharePublishOwnersResponseSchema,Xr as TestResetSuccessSchema,Xt as LocalOpAuthSetIdentityRequestSchema,Y as CC1_CONTRACT_VERSION,Yi as parseGlobalSkillBundleDoc,Yn as SharePublishNameCheckResponseSchema,Yr as TestRescanFilesSuccessSchema,Yt as LocalOpAuthHostRequestSchema,Z as CONFIG_DOC_NAMES,Za as _enum,Zi as parseManagedArtifactName,Zn as SharePublishRequestSchema,Zr as TrashCleanupRequestSchema,Zt as LocalOpAuthStatusSuccessSchema,_ as AGENT_ICON_COLORS,_a as skillLiveDocName,_i as createWorkspaceSearchCorpus,_n as PageHeadingsSuccessSchema,_o as toJSONSchema,_r as SkillTargetsGetSuccessSchema,_t as DeletePathSuccessSchema,a as acquireProcessLock,aa as projectSkillContentDocName,ai as applyPatchToFm,an as MANAGED_ARTIFACT_SCOPES,ao as literal,ar as SkillInstallRequestSchema,at as ClientLogsSuccessSchema,b as AdvisoryWarningSchema,ba as tagsMatchingPrefix,bi as detectAppliedToleranceClasses,bn as ProblemDetailsSchema,bo as meta$1,br as SkillTargetsSchema,bt as DuplicatePathRequestSchema,c as isValidLockPid,ca as renderInventoryFooter,ci as classifyMarkdownHref,cn as MetricsAgentPresenceSuccessSchema,co as object$1,cr as SkillMoveRequestSchema,ct as CreatePageRequestSchema,da as resolveSkillBundleWikiTarget,di as colorFromSeed,dn as ORPHAN_MODES,do as record,dr as SkillPutSuccessSchema,ea as parseTemplateFile,ei as UploadAssetSuccessSchema,en as LocalOpEmbeddingsSetKeyRequestSchema,eo as array,er as SkillFileDeleteSuccessSchema,et as CONFIG_DOC_NAME_PROJECT_LOCAL,f as readServerLock,fa as searchWorkspaceCorpus,fi as composeTemplateFile,fn as OrphansSuccessSchema,fo as string,fr as SkillRestoreRequestSchema,gi as createTagInTextRegex,gn as PROTOCOL_VERSION,go as datetime,gr as SkillTargetEditorSchema,gt as DeletePathRequestSchema,h as updateProcessLockPort,ha as sharedExtensions,hi as createCodeFenceTracker,hn as PROJECT_SKILL_EDITOR_IDS,hr as SkillStateSchema,ht as DeadLinksSuccessSchema,ia as projectMergeBoundarySpace,ii as applyIncrementalDiff,in as MANAGED_ARTIFACT_PREFIX_TEMPLATE,io as intersection,ir as SkillGetSuccessSchema,it as ClientLogsRequestSchema,j as ApiConfigSuccessSchema,ja as DEFAULT_EMBEDDINGS_BASE_URL,ji as getAgentCanonicalDescriptors,jn as SKILL_STATE_TARGETS,jo as $constructor,jr as SyncResolveConflictRequestSchema,jt as ForwardLinksSuccessSchema,k as AgentWriteRequestSchema,ka as CONFIG_SCHEMA_MAJOR_PATH,ki as fnv1aDigest,kn as SKILL_NAME_REGEX,ko as defineLazy,kr as SyncConflictContentSuccessSchema,kt as FolderConfigPutRequestSchema,la as resolveAssetProjectPath,li as classifyWikiLinkTarget,ln as MetricsParseHealthSuccessSchema,lo as optional,lr as SkillMoveSuccessSchema,lt as CreatePageSuccessSchema,m as releaseServerLock,ma as setToleranceTelemetryHook,mi as createBasenameIndex,mn as PREVIEW_THEME_TOKENS,mo as unknown,mr as SkillScopeSchema,mt as DOCUMENT_OPEN_BYTE_LIMIT,n as RUNTIME_VERSION,na as previewEmbedFence,ni as WorkspaceSuccessSchema,nn as LocalOpOkInitResponseSchema,no as custom,nr as SkillFilePutRequestSchema,nt as CheckoutRequestSchema,o as acquireServerLock,oa as readFmMap,oi as assertNeverProblemType,on as MCP_SERVER_NAME,oo as looseObject,or as SkillInstallStateSuccessSchema,ot as CreateFolderRequestSchema,p as releaseProcessLock,pa as serializeFrontmatterMap,pi as containsXmlTag,pn as PREVIEW_EMBED_STARTERS,po as union,pr as SkillRestoreSuccessSchema,q as CC1_CHANNEL_DISK_ACK,qa as withConfigSpan,qi as normalizeBridge,qn as ShareConstructUrlRequestSchema,qr as TestFlushGitSuccessSchema,qt as LinkGraphSuccessSchema,ra as projectFull,ri as applyFastDiff,rn as MANAGED_ARTIFACT_PREFIX_SKILL,ro as discriminatedUnion,rr as SkillFilePutSuccessSchema,rt as CheckoutResponseSchema,s as isProcessAlive,sa as reattachLeadingDocBoundary,si as classifyGitAuthError,sn as MarkdownManager,so as number,sr as SkillInstallSuccessSchema,st as CreateFolderSuccessSchema,t as ProcessLockCollisionError,ta as prependFrontmatter,ti as UploadRequestSchema,tn as LocalOpOkInitRequestSchema,to as boolean,tr as SkillFileGetSuccessSchema,tt as CONFIG_DOC_NAME_USER,u as readProcessLock,ua as resolveInternalHref,un as MetricsReconciliationSuccessSchema,uo as preprocess,ur as SkillPutRequestSchema,ut as DEFAULT_DEDUP_MODE,va as splitLeadingDocBoundary,vi as createWorkspaceSearchDocument,vn as PagesSuccessSchema,vr as SkillTargetsPutRequestSchema,vt as DocumentListSuccessSchema,w as AgentPatchSuccessSchema,wa as validateDocName,wi as emptyInstalledSkills,wn as RollbackRequestSchema,wo as parseAsync,wr as SkillUpdateSuccessSchema,wt as EDITOR_PROJECT_SKILL_ROOT,x as AgentActivitySuccessSchema,xa as toBridgeInvariantLog,xi as detectFmRegion,xn as RenamePathRequestSchema,xo as $ZodObject,xr as SkillUninstallRequestSchema,xt as DuplicatePathSuccessSchema,y as ASSET_EXTENSIONS,ya as stripFrontmatter,yi as defaultScheduler,yn as PrincipalSuccessSchema,yo as describe$1,yr as SkillTargetsPutSuccessSchema,yt as DocumentReadSuccessSchema,z as CC1ConfigIgnoreNestedErrorPayloadSchema,za as addConfigSpanEvent,zi as isHiddenDocName,zn as SearchRequestSchema,zr as TagsListSuccessSchema,zt as INLINE_RENDERABLE_EXTENSIONS}from"./server-lock-CN2YHwpP-COM23IWb.mjs";import{a as metrics,c as SpanStatusCode,i as propagation,l as SpanKind,n as init_esm$2,o as diag,r as trace,s as context,t as esm_exports$2}from"./esm-BS2W3Uzl.mjs";import{a as simpleGit,i as esm_default,n as createGitInstance,o as require_src$15,r as withParentLock,t as applyGitEnv}from"./git-handle-DY9lXoT3-Cmzgvwd8.mjs";import{t as createPatch}from"./libesm-Ob3yvbRV.mjs";import{n as mimes,t as build_default}from"./build-DCHzh6iE.mjs";import{t as require_yazl}from"./yazl-Docqgl6q.mjs";import{t as b1}from"./chunk-YNYSPYQ5-gU4-j5DO.mjs";import{a as c,c as h,d as m,f as p,h as x,i as b,l as i,m as v,n as C,o as d,p as u,r as a,s as f,t as $$1,u as l}from"./chunk-GFQRA5P5-DbAN9IDm.mjs";import{A as gt,B as wt,C as _i$1,D as da$1,E as bt,F as pe,H as zi$1,I as qi,L as us$1,M as ma$1,N as mt$1,O as di$1,P as pa$1,S as X$1,T as bl,V as xi$1,_ as Ti$1,a as Fi$1,b as W$1,c as M,d as P,f as Pt$1,g as T,h as Sl,i as En$1,j as he,k as ga$1,l as Nl,m as Se,n as Bi$1,o as Fs$1,p as R,r as Ci$1,s as G$1,t as Al,u as Oi$1,v as V,w as be,x as Wi$1,y as Vi$1,z as wl}from"./chunk-FEIOJCZD-NzTooVTc.mjs";import{a as d$1,c as m$1,d as y,i as c$1,l as p$1,n as N,o as f$1,r as P$1,s as h$1,t as $$2,u as v$1}from"./chunk-XHM67O4N-C_wCK9HT.mjs";import{n as l$1,r as o,t as h$2}from"./chunk-R6VWJ2ZL-BVeTwIsz.mjs";import{r as o$1}from"./chunk-CWQS3NFK-BkE4vqrf.mjs";import"./chunk-DXB73IDG-F_tmy-Lz.mjs";import{n as d$2,t as _$1}from"./chunk-5QMZ5MUS-BwpNU33k.mjs";import{n as u$1,t as b$1}from"./chunk-A5O5YHGN-DApqA6Ow.mjs";import{n,r,t as c$2}from"./chunk-OJDRYQWQ-CmrD0Dg2.mjs";import{r as x$1,t as a$1}from"./chunk-24IMIIXA-DaS5XS55.mjs";import{n as n$1}from"./chunk-3THT3N7L-B1WzJUh4.mjs";import{t as n$2}from"./chunk-44UOCSGV-BZ6LfyW2.mjs";import{t as import_websocket_server$1}from"./wrapper-BZO_sIci.mjs";import{createRequire}from"node:module";import{execFile,spawn,spawnSync}from"node:child_process";import*as I from"node:fs";import{appendFileSync,chmodSync,closeSync,cpSync,createReadStream,createWriteStream,existsSync,linkSync,lstatSync,mkdirSync,mkdtempSync,openSync,readFile,readFileSync,readSync,readdirSync,readlinkSync,realpathSync,renameSync,rmSync,rmdirSync,statSync,symlinkSync,unlinkSync,writeFileSync}from"node:fs";import*as U from"node:path";import{basename,dirname,extname,isAbsolute,join,normalize,posix,relative,resolve,sep,win32}from"node:path";import{homedir,hostname,platform,tmpdir}from"node:os";import{URLSearchParams as URLSearchParams$1,fileURLToPath}from"node:url";import{Transform,Writable}from"node:stream";import{access,constants as constants$1,lstat,mkdir,readFile as readFile$1,readdir,realpath,rename,stat as stat$1,unlink,writeFile}from"node:fs/promises";import crypto$1 from"crypto";import crypto$1$1,{createHash,randomUUID as randomUUID$1,webcrypto as webcrypto$1}from"node:crypto";import*as zlib from"zlib";import{Readable as Readable$1}from"stream";import{pipeline}from"node:stream/promises";import{setTimeout as setTimeout$1}from"node:timers/promises";import{promisify}from"node:util";import{Http2ServerRequest,constants as constants$2}from"http2";import{AsyncLocalStorage}from"node:async_hooks";import{lookup}from"node:dns";import{createServer}from"node:http";const WRITER_ID_RE=/^(agent-[^/]+|principal-[^/]+|file-system|git-upstream|openknowledge-service)$/;function classifyGitEntry(e,t,s){let g;try{g=statSync(e)}catch(t){let s=t.code;return s===`ENOENT`||s===`ENOTDIR`?{kind:`absent`}:{kind:`inaccessible`,gitPath:e,cause:t}}let S=computeProjectSubPath(t,s);if(g.isDirectory())return{kind:`directory`,path:e,projectSubPath:S};if(g.isFile()){let s;try{s=readFileSync(e,`utf-8`).trim()}catch(t){return{kind:`malformed-pointer`,gitPath:e,target:``,cause:t}}let g=s.match(/^gitdir:\s*(.+)$/);return g?{kind:`linked`,path:resolve(t,g[1]),gitPath:e,projectSubPath:S}:{kind:`malformed-pointer`,gitPath:e,target:``}}return{kind:`absent`}}function computeProjectSubPath(e,t){let s=relative(e,t);return s===``||s===`.`||s.startsWith(`..`)||isAbsolute(s)?``:s}function findAncestorGitEntry(e){let t=homedir(),s=resolve(e),g=64;for(let e=0;e<64;e++){if(s===t)return null;let e=dirname(s);if(e===s||e===t)return null;let g=resolve(e,`.git`);try{let t=statSync(g);if(t.isDirectory()||t.isFile())return{gitPath:g,workTreeRoot:e}}catch(e){let t=e.code;t!==`ENOENT`&&t!==`ENOTDIR`&&console.warn(`[shadow-repo-layout] Cannot stat ${g} (${t??`unknown`}); skipping ancestor`)}s=e}return null}function resolveGitDirDetailed(e){let t=resolve(e),s=classifyGitEntry(resolve(t,`.git`),t,t);if(s.kind!==`absent`)return s;let g=findAncestorGitEntry(t);return g===null?{kind:`absent`}:classifyGitEntry(g.gitPath,g.workTreeRoot,t)}function resolveGitDir(e){let t=resolveGitDirDetailed(e);return t.kind===`directory`||t.kind===`linked`?t.path:null}function resolveShadowDir(e){let t=resolveGitDirDetailed(e);switch(t.kind){case`directory`:return resolve(t.path,shadowSubdirName(t.projectSubPath));case`linked`:if(!existsSync(t.path))throw new MalformedGitPointerError(t.gitPath,t.path);return resolve(t.path,shadowSubdirName(t.projectSubPath));case`malformed-pointer`:throw new MalformedGitPointerError(t.gitPath,t.target,{cause:t.cause});case`inaccessible`:throw new GitDirAccessError(t.gitPath,{cause:t.cause});case`absent`:return resolve(e,`.git/ok`)}}function shadowSubdirName(e){return e===``?`ok`:`ok-${slugifyShadowSubPath(e)}`}function slugifyShadowSubPath(e){let t=e.split(sep).join(`-`).replace(/\/+/g,`-`).replace(/[^A-Za-z0-9._-]/g,`_`).replace(/^\.+/,`_`),s=64;if(t.length<=64)return t||`sub`;let g=djb2(e).toString(16).padStart(8,`0`);return`${t.slice(0,55)}-${g}`}function djb2(e){let t=5381;for(let s=0;s<e.length;s++)t=t*33+e.charCodeAt(s)>>>0;return t}var MalformedGitPointerError=class extends Error{gitPointerPath;resolvedTarget;constructor(e,t,s){let g=t?`references a missing or unreadable gitdir at ${t}`:`is unreadable or has no valid gitdir: pointer`;super(`\`.git\` pointer at ${e} ${g}. Run \`git worktree prune\` from the source repo and try again.`,s),this.name=`MalformedGitPointerError`,this.gitPointerPath=e,this.resolvedTarget=t}},GitDirAccessError=class extends Error{gitPath;constructor(e,t){let s=t?.cause!==void 0&&t.cause!==null&&typeof t.cause==`object`&&`code`in t.cause&&typeof t.cause.code==`string`?` (${t.cause.code})`:``;super(`Cannot access \`.git\` at ${e}${s}. Check filesystem permissions and that the volume is mounted.`,t),this.name=`GitDirAccessError`,this.gitPath=e}};function getShadowRepoPath(e){let t;try{t=resolveShadowDir(e)}catch(e){if(e instanceof MalformedGitPointerError||e instanceof GitDirAccessError)return null;throw e}return existsSync(resolve(t,`HEAD`))?t:null}function getWipRefPattern(e){return`refs/wip/${e}/`}const OK_CONTRIBUTORS_PREFIX=`ok-contributors: `;function parseContributors(e){if(!e)return[];let t=[];for(let s of e.split(`
2
2
  `)){let e=s.trim();if(e.startsWith(OK_CONTRIBUTORS_PREFIX))try{let s=JSON.parse(e.slice(17));if(typeof s==`object`&&s&&`id`in s&&typeof s.id==`string`&&`name`in s&&typeof s.name==`string`&&`docs`in s&&Array.isArray(s.docs)&&s.docs.every(e=>typeof e==`string`)&&(!(`colorSeed`in s)||typeof s.colorSeed==`string`)){let e=s;if(`summaries`in e){let t=e.summaries;(!Array.isArray(t)||!t.every(e=>typeof e==`string`))&&delete e.summaries}t.push(s)}}catch{}}return t}const OK_CHECKPOINT_PREFIX=`ok-checkpoint-v1: `;function parseCheckpoint(e){if(!e)return null;for(let t of e.split(`
3
3
  `)){let e=t.trim();if(!e.startsWith(OK_CHECKPOINT_PREFIX))continue;let s;try{s=JSON.parse(e.slice(18))}catch{return null}if(typeof s!=`object`||!s)return null;let g=s,S=g.kind,w=g.metadata;if(typeof w!=`object`||!w)return null;let E=typeof g.docName==`string`?g.docName:null,D=typeof g.size==`number`&&Number.isFinite(g.size)?g.size:null;if(S===`bridge-merge-loss`){let e=w;return Array.isArray(e.lostSubstrings)&&e.lostSubstrings.every(e=>typeof e==`string`)?{kind:`bridge-merge-loss`,docName:E,size:D,metadata:{lostSubstrings:e.lostSubstrings}}:null}if(S===`external-change-rescue`){let e=w;return typeof e.incomingDiskSha==`string`?{kind:`external-change-rescue`,docName:E,size:D,metadata:{incomingDiskSha:e.incomingDiskSha}}:null}if(S===`auto-consolidation`){let e=w;return typeof e.foldedRefs==`number`&&Number.isFinite(e.foldedRefs)&&typeof e.trigger==`string`?{kind:`auto-consolidation`,docName:E,size:D,metadata:{foldedRefs:e.foldedRefs,trigger:e.trigger}}:null}return null}return null}function formatCheckpointBodyLine(e){let t={kind:e.kind,metadata:e.metadata};return e.docName!==null&&(t.docName=e.docName),e.size!==null&&(t.size=e.size),`${OK_CHECKPOINT_PREFIX}${JSON.stringify(t)}`}const OK_ACTOR_PREFIX=`ok-actor: `;function formatOkActor(e){let{summaries:t,previous_paths:s,...g}=e,S={...g};return t&&t.length>0&&(S.summaries=t),s&&s.length>0&&(S.previous_paths=s),`${OK_ACTOR_PREFIX}${JSON.stringify(S)}`}function parseOkActorObject(e){if(e.v!==1||!(`display_name`in e)||typeof e.display_name!=`string`||!(`docs`in e)||!Array.isArray(e.docs))return null;let t=typeof e.principal==`string`?e.principal:null,s=typeof e.agent_session==`string`?e.agent_session:null,g;if(typeof e.writer_id==`string`&&e.writer_id.length>0)g=e.writer_id;else if(s)g=`agent-${s}`;else if(t)g=t;else switch(e.display_name){case`File System`:g=`file-system`;break;case`Git (upstream)`:g=`git-upstream`;break;default:g=`openknowledge-service`}let S=`summaries`in e&&Array.isArray(e.summaries)&&e.summaries.every(e=>typeof e==`string`)?e.summaries:void 0,w=parsePreviousPaths(e);return{v:1,writer_id:g,principal:t,agent_session:s,agent_type:typeof e.agent_type==`string`?e.agent_type:null,client_name:typeof e.client_name==`string`?e.client_name:null,client_version:typeof e.client_version==`string`?e.client_version:null,label:typeof e.label==`string`?e.label:null,display_name:e.display_name,color_seed:typeof e.color_seed==`string`?e.color_seed:`unknown`,docs:e.docs.filter(e=>typeof e==`string`),...S&&S.length>0?{summaries:S}:{},...w&&w.length>0?{previous_paths:w}:{}}}function parsePreviousPaths(e){if(!(`previous_paths`in e)||!Array.isArray(e.previous_paths))return;let t=[];for(let s of e.previous_paths){if(typeof s!=`object`||!s)continue;let e=s;typeof e.from!=`string`||typeof e.to!=`string`||t.push({from:e.from,to:e.to})}return t}function parseOkActor(e){if(!e)return null;for(let t of e.split(`
4
4
  `)){let e=t.trim();if(!e.startsWith(OK_ACTOR_PREFIX))continue;let s;try{s=JSON.parse(e.slice(10))}catch{return null}return typeof s!=`object`||!s?null:parseOkActorObject(s)}return null}function parseOkActors(e){if(!e)return[];let t=[];for(let s of e.split(`
@@ -800,7 +800,7 @@ native-divergence-injected
800
800
  `,`
801
801
  `).replaceAll(`\r`,`
802
802
  `).split(`
803
- `))s(S)||collectHrefsFromLine(stripHtmlComments(S,g).replace(/`[^`]*`/g,``),t);return[...t]}function resolveReferencedAssetWithinContentDir(e){let t=decodeHrefPath(e.href);if(!t||isRemoteOrOpaqueHref(t))return null;let s=extname(t).slice(1).toLowerCase();if(!LINKABLE_ASSET_EXTENSIONS.has(s))return null;let g=resolveAssetProjectPath(t,e.fromDocName);if(!g)return null;let S=resolve(e.contentDir,g),w,E;try{if(w=normalize(realpathSync(S)),!isWithinContentDir(w,e.contentDir))return null;E=statSync(w)}catch(t){let s=errnoCode$1(t);return s!==`ENOENT`&&s!==`ENOTDIR`&&console.warn(`[asset-references] unexpected error resolving asset:`,e.href,t),null}return E.isFile()?{absolutePath:w,relativePath:toContentRelativePath(e.contentDir,w),stat:E}:null}function toContentRelativePath(e,t){let s=normalize(realpathSync(e));return normalize(t).slice(s.length+(s.endsWith(sep)?0:1)).split(sep).join(`/`)}function collectReferencedAssets(e){let t;try{t=normalize(realpathSync(e.contentDir))}catch(e){return console.warn(`[asset-references] could not resolve content directory:`,e),[]}let s=new Map;for(let[g,S]of e.fileIndex){let w=e.readMarkdown(S.canonicalPath);if(w!==null)for(let S of extractLocalAssetHrefs(w)){let w=resolveReferencedAssetWithinContentDir({contentDir:t,fromDocName:g,href:S});if(!w||e.isExcluded?.(w.relativePath))continue;let E=mediaKindForAssetPath(w.absolutePath),D=s.get(w.relativePath);if(D){D.referencedBy.includes(g)||D.referencedBy.push(g);continue}s.set(w.relativePath,{kind:`asset`,path:w.relativePath,assetExt:extname(w.relativePath).toLowerCase(),mediaKind:E,size:w.stat.size,modified:w.stat.mtime.toISOString(),referencedBy:[g]})}}return[...s.values()].sort((e,t)=>e.path.localeCompare(t.path))}Object.assign(mimes,{m4v:`video/mp4`,mkv:`video/x-matroska`,flac:`audio/flac`,toml:`application/toml`,lock:`text/plain`,"7z":`application/x-7z-compressed`,tar:`application/x-tar`,rar:`application/vnd.rar`,xls:`application/vnd.ms-excel`,ppt:`application/vnd.ms-powerpoint`,odt:`application/vnd.oasis.opendocument.text`,ods:`application/vnd.oasis.opendocument.spreadsheet`,odp:`application/vnd.oasis.opendocument.presentation`,pages:`application/vnd.apple.pages`,numbers:`application/vnd.apple.numbers`,key:`application/vnd.apple.keynote`,mobi:`application/x-mobipocket-ebook`});function assetContentTypeForPath(e){return mimes[extname(e).slice(1).toLowerCase()]??null}function createAssetServeMiddleware(e){let{contentFilter:t,contentSirv:s,inlineExtensions:g,assetExtensions:S,blocklistExtensions:w}=e;return(e,E,D)=>{let O;try{O=decodeURIComponent(e.url?.split(`?`)[0]?.replace(/^\//,``)??``)}catch{return D()}let k=extname(O).slice(1).toLowerCase(),j=k===`md`||k===`mdx`;if(!O||t.isPathIgnored(O)||!j&&!S.has(k))return D();E.setHeader(`X-Content-Type-Options`,`nosniff`);let F=SANDBOXED_HTML_EXTENSIONS.has(k);j||(g.has(k)||F?E.setHeader(`Content-Disposition`,`inline`):E.setHeader(`Content-Disposition`,`attachment`)),k===`svg`?E.setHeader(`Content-Security-Policy`,`sandbox; default-src 'none'; style-src 'unsafe-inline'`):F&&(E.setHeader(`Content-Security-Policy`,SANDBOXED_HTML_CSP),E.setHeader(`Cache-Control`,`no-store`)),s(e,E,()=>{if(E.headersSent)return;let e=SANDBOXED_HTML_EXTENSIONS.has(k);if(!e&&(S.has(k)||w.has(k))){E.statusCode=404,E.end();return}e&&(E.removeHeader(`Content-Security-Policy`),E.removeHeader(`Content-Disposition`),E.removeHeader(`X-Content-Type-Options`),E.removeHeader(`Cache-Control`)),D()})}}function resolveContentDir(e,t){return resolve(t,e.content.dir)}function getLocalDir(e){return resolve(e,`.ok`,LOCAL_DIR)}function resolveLockDir(e){return getLocalDir(e)}function resolveWithinRoot(e,t){if(typeof e!=`string`||!isAbsolute(e))return{ok:!1,reason:`root path is not absolute: ${String(e)}`};if(typeof t!=`string`)return{ok:!1,reason:`path must be a string`};if(t.includes(`\0`))return{ok:!1,reason:`path contains a NUL byte`};let s=resolve(e),g=resolve(s,t),S=relative(s,g);return S===``?{ok:!0,abs:g,rel:``}:S===`..`||S.startsWith(`../`)||isAbsolute(S)?{ok:!1,reason:`path "${t}" escapes the configured root`}:{ok:!0,abs:g,rel:S}}function agentIdentityFields(e){return e?{agentId:e.connectionId,agentName:e.displayName,clientName:e.clientInfo?.name,colorSeed:e.colorSeed}:{}}const ROUTED_CWD_DESCRIPTION="Absolute host path inside the target OpenKnowledge project. Required when the MCP server is registered globally (e.g. `npx @inkeep/open-knowledge mcp` once at the host level, routing per call), unless the MCP client advertises exactly one root via the `roots` capability — that single root is then used as the implicit `cwd`. Optional when the server is anchored to a single project (the per-project HTTP MCP server defaults to its configured project root).",summaryArgSchema=string().max(200).optional().describe(`Optional one-line user-outcome description (≤80 chars). Appears as a bullet in the timeline.`),VERSION_FIELD_DESCRIBE="A 40-character commit SHA identifying a saved version. Produced by `checkpoint`, listed by `history` as `entries[].version`, and consumed here — the same `version` field name across all three.",versionInputSchema=string().length(40).regex(/^[0-9a-f]+$/i).describe(VERSION_FIELD_DESCRIBE),previewUrlOutputField=string().nullable().describe("Route-only preview URL (`/#/<doc>`, no host:port), or null when no UI is running."),previewUrlSourceField=string().optional().describe(`How the previewUrl was resolved (e.g. the UI lock).`),previousPreviewUrlField=string().optional().describe(`Route of the prior/removed path, for closing a stale preview tab.`),summaryOutputSchema=object$1({value:string(),truncatedFrom:number().optional(),hint:string().optional()}).describe(`Normalized change-note summary, when one was recorded.`),looseObjectArray=array(record(string(),unknown())),previewAttachWarningField=record(string(),unknown()).optional().describe("Preview-attach hint (`{ action, previewUrl?, message? }`) when relevant."),documentResultBaseShape={summary:summaryOutputSchema.optional(),warnings:array(AdvisoryWarningSchema).min(1).optional().describe("Advisory entries discriminated by `kind`. Write-integrity kinds — `content-divergence` (converged Y.Text didn't byte-match what you composed) and `disk-edit-reconciled` (an out-of-band disk edit was folded in before your write) — mean re-read the doc. The renderability kind `mermaid-parse-error` means the write landed but that fence will not render — fix it and re-edit.")};function nestDocResult(e,t,s){let g={};return e&&(g.previewUrl=e.url,g.previewUrlSource=e.source),t&&(g.warning=t),Object.keys(s).length>0&&(g.document=s),g}function textResult(e,t){return{content:[{type:`text`,text:e}],...t?{isError:!0}:{}}}const TEXT_CHANNEL_FIELD=string().optional().describe("Auto-duplicated body text. `textPlusStructured` mirrors the visible body here as a Claude / Claude Desktop client-quirk workaround (those clients hide `content[]` when `structuredContent` is present). Internal — programmatic consumers should prefer the `content[0].text` channel.");function outputSchemaWithText(e){return{text:TEXT_CHANNEL_FIELD,...e}}function textPlusStructured(e,t,s){let g={text:e,...t};return{content:[{type:`text`,text:e}],structuredContent:g,...s?{isError:!0}:{}}}const HOCUSPOCUS_NOT_RUNNING_ERROR="Error: Hocuspocus server is not running. Start it with `ok start`, then retry.\nFor disk-only writes without real-time sync, use your native Edit tool directly.",ROLE_LABEL={ingest:`raw-sources layer (preserve external material, no analysis)`,research:`wiki layer, provisional (synthesize findings that can still change)`,consolidate:`wiki layer, canonical (promote stabilized research to source-of-truth)`},ROLE_BEFORE={ingest:"user shares a URL or file they want preserved, or `research` needs raw sources",research:"`ingest` has captured the relevant sources (or the user points at one)",consolidate:"`research` has produced a provisional article AND a decision has actually been made"},ROLE_AFTER={ingest:"often `research` on the same topic — or just stop; raw preservation is frequently enough on its own",research:"usually stop (research lives as provisional indefinitely) or `consolidate` once a decision lands",consolidate:"update 2–3 neighbor docs to link the new canonical article; research articles it supersedes gain a `superseded_by` pointer"};function buildWorkflowFrame(e){return`## Where this fits
803
+ `))s(S)||collectHrefsFromLine(stripHtmlComments(S,g).replace(/`[^`]*`/g,``),t);return[...t]}function resolveReferencedAssetWithinContentDir(e){let t=decodeHrefPath(e.href);if(!t||isRemoteOrOpaqueHref(t))return null;let s=extname(t).slice(1).toLowerCase();if(!LINKABLE_ASSET_EXTENSIONS.has(s))return null;let g=resolveAssetProjectPath(t,e.fromDocName);if(!g)return null;let S=resolve(e.contentDir,g),w,E;try{if(w=normalize(realpathSync(S)),!isWithinContentDir(w,e.contentDir))return null;E=statSync(w)}catch(t){let s=errnoCode$1(t);return s!==`ENOENT`&&s!==`ENOTDIR`&&console.warn(`[asset-references] unexpected error resolving asset:`,e.href,t),null}return E.isFile()?{absolutePath:w,relativePath:toContentRelativePath(e.contentDir,w),stat:E}:null}function toContentRelativePath(e,t){let s=normalize(realpathSync(e));return normalize(t).slice(s.length+(s.endsWith(sep)?0:1)).split(sep).join(`/`)}function collectReferencedAssets(e){let t;try{t=normalize(realpathSync(e.contentDir))}catch(e){return console.warn(`[asset-references] could not resolve content directory:`,e),[]}let s=new Map;for(let[g,S]of e.fileIndex){let w=e.readMarkdown(S.canonicalPath);if(w!==null)for(let S of extractLocalAssetHrefs(w)){let w=resolveReferencedAssetWithinContentDir({contentDir:t,fromDocName:g,href:S});if(!w||e.isExcluded?.(w.relativePath))continue;let E=mediaKindForAssetPath(w.absolutePath),D=s.get(w.relativePath);if(D){D.referencedBy.includes(g)||D.referencedBy.push(g);continue}s.set(w.relativePath,{kind:`asset`,path:w.relativePath,assetExt:extname(w.relativePath).toLowerCase(),mediaKind:E,size:w.stat.size,modified:w.stat.mtime.toISOString(),referencedBy:[g]})}}return[...s.values()].sort((e,t)=>e.path.localeCompare(t.path))}Object.assign(mimes,{m4v:`video/mp4`,mkv:`video/x-matroska`,flac:`audio/flac`,toml:`application/toml`,lock:`text/plain`,"7z":`application/x-7z-compressed`,tar:`application/x-tar`,rar:`application/vnd.rar`,xls:`application/vnd.ms-excel`,ppt:`application/vnd.ms-powerpoint`,odt:`application/vnd.oasis.opendocument.text`,ods:`application/vnd.oasis.opendocument.spreadsheet`,odp:`application/vnd.oasis.opendocument.presentation`,pages:`application/vnd.apple.pages`,numbers:`application/vnd.apple.numbers`,key:`application/vnd.apple.keynote`,mobi:`application/x-mobipocket-ebook`});function assetContentTypeForPath(e){return mimes[extname(e).slice(1).toLowerCase()]??null}function createAssetServeMiddleware(e){let{contentFilter:t,contentSirv:s,inlineExtensions:g,assetExtensions:S,blocklistExtensions:w}=e;return(e,E,D)=>{let O;try{O=decodeURIComponent(e.url?.split(`?`)[0]?.replace(/^\//,``)??``)}catch{return D()}let k=extname(O).slice(1).toLowerCase(),j=k===`md`||k===`mdx`;if(!O||t.isPathIgnored(O)||!j&&!S.has(k))return D();E.setHeader(`X-Content-Type-Options`,`nosniff`);let F=SANDBOXED_HTML_EXTENSIONS.has(k);j||(g.has(k)||F?E.setHeader(`Content-Disposition`,`inline`):E.setHeader(`Content-Disposition`,`attachment`)),k===`svg`?E.setHeader(`Content-Security-Policy`,`sandbox; default-src 'none'; style-src 'unsafe-inline'`):F&&(E.setHeader(`Content-Security-Policy`,SANDBOXED_HTML_CSP),E.setHeader(`Cache-Control`,`no-store`)),s(e,E,()=>{if(E.headersSent)return;let e=SANDBOXED_HTML_EXTENSIONS.has(k);if(!e&&(S.has(k)||w.has(k))){E.statusCode=404,E.end();return}e&&(E.removeHeader(`Content-Security-Policy`),E.removeHeader(`Content-Disposition`),E.removeHeader(`X-Content-Type-Options`),E.removeHeader(`Cache-Control`)),D()})}}function resolveContentDir(e,t){return resolve(t,e.content.dir)}function getLocalDir(e){return resolve(e,`.ok`,LOCAL_DIR)}function resolveLockDir(e){return getLocalDir(e)}function resolveWithinRoot(e,t){if(typeof e!=`string`||!isAbsolute(e))return{ok:!1,reason:`root path is not absolute: ${String(e)}`};if(typeof t!=`string`)return{ok:!1,reason:`path must be a string`};if(t.includes(`\0`))return{ok:!1,reason:`path contains a NUL byte`};let s=resolve(e),g=resolve(s,t),S=relative(s,g);return S===``?{ok:!0,abs:g,rel:``}:S===`..`||S.startsWith(`../`)||isAbsolute(S)?{ok:!1,reason:`path "${t}" escapes the configured root`}:{ok:!0,abs:g,rel:S}}function agentIdentityFields(e){return e?{agentId:e.connectionId,agentName:e.displayName,clientName:e.clientInfo?.name,colorSeed:e.colorSeed}:{}}const ROUTED_CWD_DESCRIPTION="Absolute host path inside the target OpenKnowledge project. Required when the MCP server is registered globally (e.g. `npx @inkeep/open-knowledge mcp` once at the host level, routing per call), unless the MCP client advertises exactly one root via the `roots` capability — that single root is then used as the implicit `cwd`. Optional when the server is anchored to a single project (the per-project HTTP MCP server defaults to its configured project root).",summaryArgSchema=string().max(200).optional().describe(`Optional one-line user-outcome description (≤80 chars). Appears as a bullet in the timeline.`),VERSION_FIELD_DESCRIBE="A 40-character commit SHA identifying a saved version. Produced by `checkpoint`, listed by `history` as `entries[].version`, and consumed here — the same `version` field name across all three.",versionInputSchema=string().length(40).regex(/^[0-9a-f]+$/i).describe(VERSION_FIELD_DESCRIBE),previewUrlOutputField=string().nullable().describe("Route-only preview URL (`/#/<doc>`, no host:port), or null when no UI is running."),previewUrlSourceField=string().optional().describe(`How the previewUrl was resolved (e.g. the UI lock).`),previousPreviewUrlField=string().optional().describe(`Route of the prior/removed path, for closing a stale preview tab.`),summaryOutputSchema=object$1({value:string(),truncatedFrom:number().optional(),hint:string().optional()}).describe(`Normalized change-note summary, when one was recorded.`),looseObjectArray=array(record(string(),unknown())),previewAttachWarningField=record(string(),unknown()).optional().describe("Preview-attach hint (`{ action, previewUrl?, message? }`) when relevant."),brokenLinksOutputField=array(BrokenLinkSchema).describe('Outbound internal links in the just-written doc that do not resolve. Always present — `[]` means every link resolves. Each: `{ href (as written), resolvedTo (the docName or content-root file path it pointed at, or null), reason: "no-such-doc" | "no-such-file" | "unresolvable" }`. Report-only — the write landed regardless; fix in a follow-up edit.');function docExtensionOnDisk(e,t){for(let s of SUPPORTED_DOC_EXTENSIONS){let g=resolveWithinRoot(e,`${t}${s}`);if(g.ok&&existsSync(g.abs))return s}}const documentResultBaseShape={summary:summaryOutputSchema.optional(),warnings:array(AdvisoryWarningSchema).min(1).optional().describe("Advisory entries discriminated by `kind`. Write-integrity kinds — `content-divergence` (converged Y.Text didn't byte-match what you composed) and `disk-edit-reconciled` (an out-of-band disk edit was folded in before your write) — mean re-read the doc. The renderability kind `mermaid-parse-error` means the write landed but that fence will not render — fix it and re-edit."),brokenLinks:brokenLinksOutputField};function nestDocResult(e,t,s){let g={};return e&&(g.previewUrl=e.url,g.previewUrlSource=e.source),t&&(g.warning=t),Object.keys(s).length>0&&(g.document=s),g}function textResult(e,t){return{content:[{type:`text`,text:e}],...t?{isError:!0}:{}}}const TEXT_CHANNEL_FIELD=string().optional().describe("Auto-duplicated body text. `textPlusStructured` mirrors the visible body here as a Claude / Claude Desktop client-quirk workaround (those clients hide `content[]` when `structuredContent` is present). Internal — programmatic consumers should prefer the `content[0].text` channel.");function outputSchemaWithText(e){return{text:TEXT_CHANNEL_FIELD,...e}}function textPlusStructured(e,t,s){let g={text:e,...t};return{content:[{type:`text`,text:e}],structuredContent:g,...s?{isError:!0}:{}}}const HOCUSPOCUS_NOT_RUNNING_ERROR="Error: Hocuspocus server is not running. Start it with `ok start`, then retry.\nFor disk-only writes without real-time sync, use your native Edit tool directly.",ROLE_LABEL={ingest:`raw-sources layer (preserve external material, no analysis)`,research:`wiki layer, provisional (synthesize findings that can still change)`,consolidate:`wiki layer, canonical (promote stabilized research to source-of-truth)`},ROLE_BEFORE={ingest:"user shares a URL or file they want preserved, or `research` needs raw sources",research:"`ingest` has captured the relevant sources (or the user points at one)",consolidate:"`research` has produced a provisional article AND a decision has actually been made"},ROLE_AFTER={ingest:"often `research` on the same topic — or just stop; raw preservation is frequently enough on its own",research:"usually stop (research lives as provisional indefinitely) or `consolidate` once a decision lands",consolidate:"update 2–3 neighbor docs to link the new canonical article; research articles it supersedes gain a `superseded_by` pointer"};function buildWorkflowFrame(e){return`## Where this fits
804
804
 
805
805
  OpenKnowledge accretes a persistent wiki through three workflow tools, mapped to [Karpathy's three-layer knowledge-base pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f):
806
806
 
@@ -847,7 +847,11 @@ Karpathy's insight: "The tedious part of maintaining a knowledge base is not the
847
847
  `,`
848
848
  `).replaceAll(`\r`,`
849
849
  `).split(`
850
- `),g=[],S=null;for(let e of s)if(S)isFenceClose$1(e,S)&&(S=null);else{let s=matchFence$1(e);if(s)S=s;else{let s=extractExternalMarkdownLinksFromLine(e,t);g.push(...s.occurrences.map(({url:e,label:t,start:g,end:S})=>({url:e,label:t,snippet:snippetAround$1(s.text,g,S)})))}}return g}function serializeState(e){return{backward:Object.fromEntries([...e.backward.entries()].map(([e,t])=>[e,[...t.entries()].map(([e,t])=>({source:e,anchor:t.anchor,snippet:t.snippet}))])),forward:Object.fromEntries([...e.forward.entries()].map(([e,t])=>[e,[...t].sort()])),externalForward:Object.fromEntries([...e.externalForward.entries()].map(([e,t])=>[e,[...t.entries()].map(([e,t])=>({url:e,label:t.label,snippet:t.snippet})).sort((e,t)=>e.url.localeCompare(t.url))]))}}function buildExternalBackward(e){let t=new Map;for(let[s,g]of e)for(let[e,S]of g){let g=t.get(e);g||(g=new Map,t.set(e,g)),g.set(s,S)}return t}function deserializeState(e){let t=new Map(Object.entries(e.externalForward??{}).map(([e,t])=>[e,new Map(t.map(e=>[e.url,{label:e.label??null,snippet:e.snippet??null}]))]));return{backward:new Map(Object.entries(e.backward??{}).map(([e,t])=>[e,new Map(t.map(e=>[e.source,{anchor:e.anchor??null,snippet:e.snippet??null}]))])),forward:new Map(Object.entries(e.forward??{}).map(([e,t])=>[e,new Set(t)])),externalForward:t,externalBackward:buildExternalBackward(t)}}var BacklinkIndex=class{projectDir;contentDir;contentFilter;states=new Map;mtimesByBranch=new Map;activeBranch=`main`;constructor(e){this.projectDir=e.projectDir,this.contentDir=e.contentDir,this.contentFilter=e.contentFilter,this.states.set(this.activeBranch,createEmptyState$1())}getState(e=this.activeBranch){let t=this.states.get(e);return t||(t=createEmptyState$1(),this.states.set(e,t)),t}structuralBundleNeighbors(e,t=this.activeBranch){let s=parseSkillBundleDocAnyScope(e),g=new Set;if(!s)return g;let S=this.getState(t);if(!S.forward.has(e))return g;if(s.kind===`skill`)for(let t of S.forward.keys()){let s=parseSkillBundleDocAnyScope(t);s?.kind===`reference`&&s.skillDocName===e&&g.add(t)}else S.forward.has(s.skillDocName)&&g.add(s.skillDocName);return g}getActiveBranch(){return this.activeBranch}switchBranch(e){this.activeBranch=e,this.getState(e)}cachePath(e=this.activeBranch){return resolve(getLocalDir(this.projectDir),`cache`,e,`backlinks.json`)}registerNodeOnly(e,t=this.activeBranch){let s=this.getState(t),g=s.forward.get(e)??new Set,S=s.externalForward.get(e)??new Map;for(let t of g){let g=s.backward.get(t);g&&(g.delete(e),g.size===0&&s.backward.delete(t))}for(let t of S.keys()){let g=s.externalBackward.get(t);g&&(g.delete(e),g.size===0&&s.externalBackward.delete(t))}s.forward.set(e,new Set),s.externalForward.set(e,new Map)}registerGlobalSkillBundleNode(e,t=this.activeBranch){parseGlobalSkillBundleDoc(e)&&this.registerNodeOnly(e,t)}updateDocument(e,t,s=[],g=this.activeBranch){if(isLinkIndexExcludedDoc(e))return;if(parseGlobalSkillBundleDoc(e)){this.registerNodeOnly(e,g);return}let S=this.getState(g),w=S.forward.get(e)??new Set,E=S.externalForward.get(e)??new Map;for(let t of w){let s=S.backward.get(t);s&&(s.delete(e),s.size===0&&S.backward.delete(t))}for(let t of E.keys()){let s=S.externalBackward.get(t);s&&(s.delete(e),s.size===0&&S.externalBackward.delete(t))}let D=new Set,O=new Map;S.forward.set(e,D),S.externalForward.set(e,O);for(let s of t){if(!s.target)continue;let t=managedArtifactDocNameFromContentTarget(s.target)??s.target;D.add(t);let g=S.backward.get(t);g||(g=new Map,S.backward.set(t,g)),g.set(e,mergeLinkMeta(g.get(e),{anchor:s.anchor,snippet:s.snippet}))}for(let t of s){if(!t.url)continue;O.set(t.url,{label:t.label,snippet:t.snippet});let s=S.externalBackward.get(t.url);s||(s=new Map,S.externalBackward.set(t.url,s)),(!s.has(e)||!s.get(e)?.snippet&&t.snippet)&&s.set(e,{label:t.label,snippet:t.snippet})}}updateDocumentFromMarkdown(e,t,s=this.activeBranch){try{let{body:g}=stripFrontmatter(t),S=extractWikiLinksFromMarkdown(g,e),w=extractMarkdownLinksFromMarkdown(g,e),E=extractExternalWikiLinksFromMarkdown(g),D=extractExternalMarkdownLinksFromMarkdown(g,e),O=new Set(S.map(e=>e.target)),k=[...S,...w.filter(e=>!O.has(e.target))],j=new Set(E.map(e=>e.url)),F=[...E,...D.filter(e=>!j.has(e.url))];this.updateDocument(e,k,F,s)}catch(t){console.warn(`[backlinks] Failed to scan ${e} for link extraction:`,t),this.deleteDocument(e,s)}}deleteDocument(e,t=this.activeBranch){if(isLinkIndexExcludedDoc(e))return;let s=this.getState(t),g=s.forward.get(e)??new Set,S=s.externalForward.get(e)??new Map;for(let t of g){let g=s.backward.get(t);g&&(g.delete(e),g.size===0&&s.backward.delete(t))}for(let t of S.keys()){let g=s.externalBackward.get(t);g&&(g.delete(e),g.size===0&&s.externalBackward.delete(t))}s.forward.delete(e),s.externalForward.delete(e)}renameDocument(e,t,s,g=this.activeBranch){this.deleteDocument(e,g),this.updateDocumentFromMarkdown(t,s,g)}getBacklinks(e,t=this.activeBranch){let s=this.getState(t).backward.get(e),g=new Map;if(s)for(let[e,t]of s)g.set(e,{source:e,anchor:t.anchor,snippet:t.snippet});for(let s of this.structuralBundleNeighbors(e,t))g.has(s)||g.set(s,{source:s,anchor:null,snippet:null});return[...g.values()].sort((e,t)=>e.source.localeCompare(t.source))}getBacklinkCount(e,t=this.activeBranch){let s=this.getState(t).backward.get(e),g=this.structuralBundleNeighbors(e,t);if(g.size===0)return s?.size??0;let S=new Set(s?.keys()??[]);for(let e of g)S.add(e);return S.size}getForwardLinks(e,t=this.activeBranch){let s=this.getState(t),g=new Set(s.forward.get(e)??new Set);for(let s of this.structuralBundleNeighbors(e,t))g.add(s);return[...g].sort((e,t)=>e.localeCompare(t))}getForwardLinkEntries(e,t=this.activeBranch){let s=this.getState(t),g=this.getForwardLinks(e,t).map(t=>({kind:`doc`,target:t,anchor:s.backward.get(t)?.get(e)?.anchor??null,snippet:s.backward.get(t)?.get(e)?.snippet??null})),S=[...(s.externalForward.get(e)??new Map).entries()].map(([e,t])=>({kind:`external`,url:e,label:t.label,snippet:t.snippet})).sort((e,t)=>e.url.localeCompare(t.url));return[...g,...S]}getOrphans(e,t=`both`,s=this.activeBranch){let g=this.getState(s),S=new Set;for(let e of g.forward.keys()){let t=parseSkillBundleDocAnyScope(e);t?.kind===`reference`&&S.add(t.skillDocName)}let w=e=>{let t=parseSkillBundleDocAnyScope(e);return!t||!g.forward.has(e)?!1:t.kind===`skill`?S.has(e):g.forward.has(t.skillDocName)};return[...e].filter(e=>{let s=w(e),S=s||(g.backward.get(e)?.size??0)>0,E=s||(g.forward.get(e)?.size??0)>0;return t===`incoming`?!S:(t===`outgoing`||!S)&&!E}).sort((e,t)=>e.localeCompare(t))}getHubs(e=20,t=this.activeBranch){return[...this.getState(t).backward.entries()].map(([e,t])=>({docName:e,count:t.size})).sort((e,t)=>t.count===e.count?e.docName.localeCompare(t.docName):t.count-e.count).slice(0,e)}getDeadLinks(e,t,s=this.activeBranch){let g=this.getState(s),S=new Set(e),w=t?.length?new Set(t):null;return[...g.backward.entries()].filter(([e,t])=>{if(S.has(e))return!1;if(!w)return t.size>0;for(let e of t.keys())if(w.has(e))return!0;return!1}).map(([e,t])=>({target:e,sources:[...t.entries()].filter(([e])=>!w||w.has(e)).map(([e,t])=>({source:e,anchor:t.anchor,snippet:t.snippet})).sort((e,t)=>e.source.localeCompare(t.source))})).filter(e=>e.sources.length>0).sort((e,t)=>t.sources.length===e.sources.length?e.target.localeCompare(t.target):t.sources.length-e.sources.length)}getLinkGraph(e=this.activeBranch){let t=this.getState(e),s=new Map,g=[];for(let[e,S]of t.forward){s.set(e,{kind:`doc`,id:e,docName:e,anchor:getRepresentativeAnchor(t.backward.get(e))});for(let w of S)s.set(w,{kind:`doc`,id:w,docName:w,anchor:getRepresentativeAnchor(t.backward.get(w))}),g.push({source:e,target:w})}for(let[e,S]of t.externalForward){s.set(e,{kind:`doc`,id:e,docName:e,anchor:getRepresentativeAnchor(t.backward.get(e))});for(let[t,w]of S){let S=externalNodeId(t);s.set(S,{kind:`external`,id:S,url:t,label:w.label}),g.push({source:e,target:S})}}for(let S of t.forward.keys())if(parseSkillBundleDocAnyScope(S)?.kind===`skill`)for(let w of this.structuralBundleNeighbors(S,e))t.forward.get(S)?.has(w)||t.forward.get(w)?.has(S)||(s.set(S,{kind:`doc`,id:S,docName:S,anchor:getRepresentativeAnchor(t.backward.get(S))}),s.set(w,{kind:`doc`,id:w,docName:w,anchor:getRepresentativeAnchor(t.backward.get(w))}),g.push({source:S,target:w}));return{nodes:[...s.values()].sort((e,t)=>e.id.localeCompare(t.id)),links:g}}getLinkGraphNeighborhood(e,t,s=this.activeBranch){let g=this.getState(s),S=new Map;for(let e of g.externalForward.values())for(let[t,s]of e)S.has(t)||S.set(t,s.label);let w=new Set([e]),E=[{nodeId:e,degree:0}],D=0;for(;D<E.length;){let e=E[D++];if(e.degree>=t)continue;let S=externalUrlFromNodeId(e.nodeId),O=new Set;if(S)for(let e of g.externalBackward.get(S)?.keys()??[])O.add(e);else{for(let t of g.forward.get(e.nodeId)??new Set)O.add(t);for(let t of g.externalForward.get(e.nodeId)?.keys()??[])O.add(externalNodeId(t));for(let t of g.backward.get(e.nodeId)?.keys()??[])O.add(t);for(let t of this.structuralBundleNeighbors(e.nodeId,s))O.add(t)}for(let t of O)w.has(t)||(w.add(t),E.push({nodeId:t,degree:e.degree+1}))}let O=[];for(let[e,t]of g.forward)if(w.has(e))for(let s of t)w.has(s)&&O.push({source:e,target:s});for(let[e,t]of g.externalForward)if(w.has(e))for(let s of t.keys()){let t=externalNodeId(s);w.has(t)&&O.push({source:e,target:t})}for(let e of w)if(parseSkillBundleDocAnyScope(e)?.kind===`skill`)for(let t of this.structuralBundleNeighbors(e,s))w.has(t)&&(g.forward.get(e)?.has(t)||g.forward.get(t)?.has(e)||O.push({source:e,target:t}));return{nodes:[...w].sort().map(e=>{let t=externalUrlFromNodeId(e);return t?{kind:`external`,id:e,url:t,label:S.get(t)??null}:{kind:`doc`,id:e,docName:e,anchor:getRepresentativeAnchor(g.backward.get(e))}}),links:O}}async saveToDisk(e=this.activeBranch){let t=this.cachePath(e);mkdirSync(dirname(t),{recursive:!0});let s=this.getState(e),g=this.mtimesByBranch.get(e),S={...serializeState(s),...g?{mtimes:Object.fromEntries(g)}:{}};await writeFile(t,JSON.stringify(S,null,2),`utf-8`)}async loadFromDisk(e=this.activeBranch){let t=this.cachePath(e);if(!existsSync(t))return!1;try{let s=await readFile$1(t,`utf-8`),g=JSON.parse(s);return this.states.set(e,deserializeState(g)),g.mtimes?this.mtimesByBranch.set(e,new Map(Object.entries(g.mtimes))):this.mtimesByBranch.delete(e),!0}catch(t){return console.warn(`[backlinks] Failed to load cache for ${e}:`,t),!1}}clear(e=this.activeBranch){this.states.set(e,createEmptyState$1()),this.mtimesByBranch.delete(e)}async rebuildFromDisk(e=this.activeBranch){let t=createEmptyState$1(),s=new Map,g=[];await this.walkForPaths(this.contentDir,g);let S=new Set,w=g.filter(({docName:e})=>S.has(e)?!1:(S.add(e),!0)),E=50;for(let e=0;e<w.length;e+=50){let g=w.slice(e,e+50),S=await Promise.allSettled(g.map(async({docName:e,filePath:t})=>{let[s,g]=await Promise.all([stat$1(t),readFile$1(t,`utf-8`)]);return{docName:e,mtimeMs:s.mtimeMs,markdown:g}}));for(let e of S){if(e.status===`rejected`){console.warn(`[backlinks] Failed to rebuild entry:`,e.reason);continue}let{docName:g,mtimeMs:S,markdown:w}=e.value;s.set(g,S);let{body:E}=stripFrontmatter(w),D=extractWikiLinksFromMarkdown(E,g),O=extractMarkdownLinksFromMarkdown(E,g),k=extractExternalWikiLinksFromMarkdown(E),j=extractExternalMarkdownLinksFromMarkdown(E,g),F=new Set(D.map(e=>e.target)),L=[...D,...O.filter(e=>!F.has(e.target))],B=new Set(k.map(e=>e.url)),H=[...k,...j.filter(e=>!B.has(e.url))],q=new Set,ee=new Map;t.forward.set(g,q),t.externalForward.set(g,ee);for(let e of L){if(!e.target)continue;let s=managedArtifactDocNameFromContentTarget(e.target)??e.target;q.add(s);let S=t.backward.get(s);S||(S=new Map,t.backward.set(s,S)),S.set(g,mergeLinkMeta(S.get(g),{anchor:e.anchor,snippet:e.snippet}))}for(let e of H){if(!e.url)continue;ee.set(e.url,{label:e.label,snippet:e.snippet});let s=t.externalBackward.get(e.url);s||(s=new Map,t.externalBackward.set(e.url,s)),s.set(g,{label:e.label,snippet:e.snippet})}}}this.states.set(e,t),this.mtimesByBranch.set(e,s)}async walkForPaths(e,t){let s;try{s=await readdir(e,{withFileTypes:!0})}catch(t){console.warn(`[backlinks] Failed to read directory ${e}:`,t);return}for(let g of s){let s=join(e,g.name);if(g.isDirectory()){let e=toPosix(relative(this.contentDir,s));if(this.contentFilter&&e&&this.contentFilter.isDirExcluded(e))continue;await this.walkForPaths(s,t)}else if(g.isFile()&&isSupportedDocFile(g.name)){let e=toPosix(relative(this.contentDir,s));if(this.contentFilter?.isExcluded(e))continue;t.push({docName:stripDocExtension(e),filePath:s})}}}async reconcileWithDisk(e=this.activeBranch){if(!existsSync(this.contentDir))return{added:0,updated:0,deleted:0};let t=this.mtimesByBranch.get(e)??new Map,s=[];await this.walkForPaths(this.contentDir,s);let g=new Set,S=s.filter(({docName:e})=>g.has(e)?!1:(g.add(e),!0)),w=new Set(S.map(e=>e.docName)),E=new Map,D=0,O=0,k=[],j=await Promise.allSettled(S.map(async({docName:e,filePath:t})=>({docName:e,filePath:t,mtimeMs:(await stat$1(t)).mtimeMs})));for(let e of j){if(e.status===`rejected`)continue;let{docName:s,filePath:g,mtimeMs:S}=e.value,w=t.get(s);if(w!==void 0&&w===S){E.set(s,S);continue}k.push({docName:s,filePath:g,mtimeMs:S,isNew:w===void 0})}let F=50;for(let t=0;t<k.length;t+=50){let s=k.slice(t,t+50),g=await Promise.allSettled(s.map(async({docName:e,filePath:t,mtimeMs:s,isNew:g})=>({docName:e,mtimeMs:s,isNew:g,markdown:await readFile$1(t,`utf-8`)})));for(let t of g){if(t.status===`rejected`){console.warn(`[backlinks] Failed to reconcile file:`,t.reason);continue}let{docName:s,mtimeMs:g,isNew:S,markdown:w}=t.value;this.updateDocumentFromMarkdown(s,w,e),E.set(s,g),S?D++:O++}}let L=0,B=new Set([...t.keys(),...this.getState(e).forward.keys()]);for(let t of B)parseGlobalSkillBundleDoc(t)||w.has(t)||(this.deleteDocument(t,e),L++);return this.mtimesByBranch.set(e,E),{added:D,updated:O,deleted:L}}async ingestGlobalSkillBundles(e,t=this.activeBranch){let s=new Set;for(let g of e){if(!existsSync(g))continue;let e;try{e=await readdir(g,{withFileTypes:!0})}catch(e){console.warn(`[backlinks] Failed to read global skills root ${g}:`,e);continue}for(let S of e){if(!S.isDirectory())continue;let e=S.name,w=join(g,e),E=skillLiveDocName(`global`,e);existsSync(join(w,`SKILL.md`))&&parseGlobalSkillBundleDoc(E)&&(this.registerNodeOnly(E,t),s.add(E));let D=[];await this.walkGlobalSkillReferences(join(w,`references`),e,``,D);for(let{docName:e}of D)this.registerNodeOnly(e,t),s.add(e)}}let g=[];for(let e of this.getState(t).forward.keys())parseGlobalSkillBundleDoc(e)&&!s.has(e)&&g.push(e);for(let e of g)this.deleteDocument(e,t)}async walkGlobalSkillReferences(e,t,s,g){let S;try{S=await readdir(e,{withFileTypes:!0})}catch(t){t?.code!==`ENOENT`&&console.warn(`[backlinks] Failed to read skill references dir ${e}:`,t);return}for(let w of S){let S=s?`${s}/${w.name}`:w.name;if(w.isDirectory())await this.walkGlobalSkillReferences(join(e,w.name),t,S,g);else if(w.isFile()&&isSupportedDocFile(w.name)){let e=stripDocExtension(S);g.push({docName:`${MANAGED_ARTIFACT_PREFIX_SKILL}global/${t}/references/${e}`})}}}};function extractActorIdentity(e,t){let s=normalizeSummary(e.summary);if(s.kind===`invalid`)return{kind:`invalid-summary`};let g=parseAgentBodyFields(e),S=t?.()??null;return g.rawAgentId!==void 0&&g.writerId!==void 0?{kind:`agent`,writerId:g.writerId,displayName:g.displayName,colorSeed:g.colorSeed??g.rawAgentId,clientName:g.clientName,clientVersion:g.clientVersion,label:g.label,actor:{principalId:S?.id,agentType:resolveAgentType(g.clientName),clientName:g.clientName,clientVersion:g.clientVersion,label:g.label},summary:s}:S?{kind:`principal`,writerId:S.id,displayName:S.display_name,colorSeed:S.id,actor:{principalId:S.id},summary:s}:{kind:`anonymous`,summary:s}}const ANCESTOR_WALK_DEPTH_LIMIT$1=30;function isProjectRoot(e){try{return statSync(resolve(e,OK_PROJECT_MARKER)).isFile()}catch(e){let t=e?.code;if(t===`ENOENT`||t===`ENOTDIR`)return!1;throw e}}function findEnclosingProjectRoot(e){let t=resolve(e),s=0;for(;s<ANCESTOR_WALK_DEPTH_LIMIT$1;){let e=!1;try{e=isProjectRoot(t)}catch{e=!1}if(e)return{rootPath:t,distance:s};let g=dirname(t);if(g===t)return null;t=g,s+=1}return null}function parsePorcelainPaths(e){let t=[];for(let s of e.split(`
850
+ `),g=[],S=null;for(let e of s)if(S)isFenceClose$1(e,S)&&(S=null);else{let s=matchFence$1(e);if(s)S=s;else{let s=extractExternalMarkdownLinksFromLine(e,t);g.push(...s.occurrences.map(({url:e,label:t,start:g,end:S})=>({url:e,label:t,snippet:snippetAround$1(s.text,g,S)})))}}return g}function computeBrokenOutboundLinks(e,t,s,g){let S=s instanceof Set?s:new Set(s),w;try{({body:w}=stripFrontmatter(e))}catch{w=e}let E=w.replaceAll(`\r
851
+ `,`
852
+ `).replaceAll(`\r`,`
853
+ `).split(`
854
+ `),D=[],O=new Set,k=null,j=(e,t,s)=>{O.has(e)||(O.add(e),D.push({href:e,resolvedTo:t,reason:s}))},F=e=>{let s=e.trim();if(s.startsWith(`#`))return;let w=classifyMarkdownHref(s,t);if(!w){j(s,null,`unresolvable`);return}if(w.kind===`doc`){S.has(w.docName)||j(s,w.docName,`no-such-doc`);return}if(w.kind===`asset`){if(!g)return;let e=resolveAssetProjectPath(w.url,t);if(e===null){j(s,null,`unresolvable`);return}g(e)||j(s,e,`no-such-file`);return}},L=(e,t)=>{let s=classifyWikiLinkTarget(e,t);!s||s.kind!==`doc`||S.has(s.docName)||j(`[[${e}${t?`#${t}`:``}]]`,s.docName,`no-such-doc`)};for(let e of E){if(k){isFenceClose$1(e,k)&&(k=null);continue}let t=matchFence$1(e);if(t){k=t;continue}let s=leadingMarkdownPrefixLength$1(e);for(;s<e.length;){if(e[s]===`\\`&&s+1<e.length){s+=2;continue}if(e[s]==="`"){let t=readInlineCode$1(e,s);if(t){s=t.nextIndex;continue}}if(e[s]===`[`&&e[s+1]===`[`){let t=readWikiLink$1(e,s);if(t){L(t.target,t.anchor),s=t.nextIndex;continue}}if(e[s]===`[`&&e[s-1]!==`!`){let t=readMarkdownLink$1(e,s);if(t){F(t.href),s=t.nextIndex;continue}}s++}}return D}function serializeState(e){return{backward:Object.fromEntries([...e.backward.entries()].map(([e,t])=>[e,[...t.entries()].map(([e,t])=>({source:e,anchor:t.anchor,snippet:t.snippet}))])),forward:Object.fromEntries([...e.forward.entries()].map(([e,t])=>[e,[...t].sort()])),externalForward:Object.fromEntries([...e.externalForward.entries()].map(([e,t])=>[e,[...t.entries()].map(([e,t])=>({url:e,label:t.label,snippet:t.snippet})).sort((e,t)=>e.url.localeCompare(t.url))]))}}function buildExternalBackward(e){let t=new Map;for(let[s,g]of e)for(let[e,S]of g){let g=t.get(e);g||(g=new Map,t.set(e,g)),g.set(s,S)}return t}function deserializeState(e){let t=new Map(Object.entries(e.externalForward??{}).map(([e,t])=>[e,new Map(t.map(e=>[e.url,{label:e.label??null,snippet:e.snippet??null}]))]));return{backward:new Map(Object.entries(e.backward??{}).map(([e,t])=>[e,new Map(t.map(e=>[e.source,{anchor:e.anchor??null,snippet:e.snippet??null}]))])),forward:new Map(Object.entries(e.forward??{}).map(([e,t])=>[e,new Set(t)])),externalForward:t,externalBackward:buildExternalBackward(t)}}var BacklinkIndex=class{projectDir;contentDir;contentFilter;states=new Map;mtimesByBranch=new Map;activeBranch=`main`;constructor(e){this.projectDir=e.projectDir,this.contentDir=e.contentDir,this.contentFilter=e.contentFilter,this.states.set(this.activeBranch,createEmptyState$1())}getState(e=this.activeBranch){let t=this.states.get(e);return t||(t=createEmptyState$1(),this.states.set(e,t)),t}structuralBundleNeighbors(e,t=this.activeBranch){let s=parseSkillBundleDocAnyScope(e),g=new Set;if(!s)return g;let S=this.getState(t);if(!S.forward.has(e))return g;if(s.kind===`skill`)for(let t of S.forward.keys()){let s=parseSkillBundleDocAnyScope(t);s?.kind===`reference`&&s.skillDocName===e&&g.add(t)}else S.forward.has(s.skillDocName)&&g.add(s.skillDocName);return g}getActiveBranch(){return this.activeBranch}switchBranch(e){this.activeBranch=e,this.getState(e)}cachePath(e=this.activeBranch){return resolve(getLocalDir(this.projectDir),`cache`,e,`backlinks.json`)}registerNodeOnly(e,t=this.activeBranch){let s=this.getState(t),g=s.forward.get(e)??new Set,S=s.externalForward.get(e)??new Map;for(let t of g){let g=s.backward.get(t);g&&(g.delete(e),g.size===0&&s.backward.delete(t))}for(let t of S.keys()){let g=s.externalBackward.get(t);g&&(g.delete(e),g.size===0&&s.externalBackward.delete(t))}s.forward.set(e,new Set),s.externalForward.set(e,new Map)}registerGlobalSkillBundleNode(e,t=this.activeBranch){parseGlobalSkillBundleDoc(e)&&this.registerNodeOnly(e,t)}updateDocument(e,t,s=[],g=this.activeBranch){if(isLinkIndexExcludedDoc(e))return;if(parseGlobalSkillBundleDoc(e)){this.registerNodeOnly(e,g);return}let S=this.getState(g),w=S.forward.get(e)??new Set,E=S.externalForward.get(e)??new Map;for(let t of w){let s=S.backward.get(t);s&&(s.delete(e),s.size===0&&S.backward.delete(t))}for(let t of E.keys()){let s=S.externalBackward.get(t);s&&(s.delete(e),s.size===0&&S.externalBackward.delete(t))}let D=new Set,O=new Map;S.forward.set(e,D),S.externalForward.set(e,O);for(let s of t){if(!s.target)continue;let t=managedArtifactDocNameFromContentTarget(s.target)??s.target;D.add(t);let g=S.backward.get(t);g||(g=new Map,S.backward.set(t,g)),g.set(e,mergeLinkMeta(g.get(e),{anchor:s.anchor,snippet:s.snippet}))}for(let t of s){if(!t.url)continue;O.set(t.url,{label:t.label,snippet:t.snippet});let s=S.externalBackward.get(t.url);s||(s=new Map,S.externalBackward.set(t.url,s)),(!s.has(e)||!s.get(e)?.snippet&&t.snippet)&&s.set(e,{label:t.label,snippet:t.snippet})}}updateDocumentFromMarkdown(e,t,s=this.activeBranch){try{let{body:g}=stripFrontmatter(t),S=extractWikiLinksFromMarkdown(g,e),w=extractMarkdownLinksFromMarkdown(g,e),E=extractExternalWikiLinksFromMarkdown(g),D=extractExternalMarkdownLinksFromMarkdown(g,e),O=new Set(S.map(e=>e.target)),k=[...S,...w.filter(e=>!O.has(e.target))],j=new Set(E.map(e=>e.url)),F=[...E,...D.filter(e=>!j.has(e.url))];this.updateDocument(e,k,F,s)}catch(t){console.warn(`[backlinks] Failed to scan ${e} for link extraction:`,t),this.deleteDocument(e,s)}}deleteDocument(e,t=this.activeBranch){if(isLinkIndexExcludedDoc(e))return;let s=this.getState(t),g=s.forward.get(e)??new Set,S=s.externalForward.get(e)??new Map;for(let t of g){let g=s.backward.get(t);g&&(g.delete(e),g.size===0&&s.backward.delete(t))}for(let t of S.keys()){let g=s.externalBackward.get(t);g&&(g.delete(e),g.size===0&&s.externalBackward.delete(t))}s.forward.delete(e),s.externalForward.delete(e)}renameDocument(e,t,s,g=this.activeBranch){this.deleteDocument(e,g),this.updateDocumentFromMarkdown(t,s,g)}getBacklinks(e,t=this.activeBranch){let s=this.getState(t).backward.get(e),g=new Map;if(s)for(let[e,t]of s)g.set(e,{source:e,anchor:t.anchor,snippet:t.snippet});for(let s of this.structuralBundleNeighbors(e,t))g.has(s)||g.set(s,{source:s,anchor:null,snippet:null});return[...g.values()].sort((e,t)=>e.source.localeCompare(t.source))}getBacklinkCount(e,t=this.activeBranch){let s=this.getState(t).backward.get(e),g=this.structuralBundleNeighbors(e,t);if(g.size===0)return s?.size??0;let S=new Set(s?.keys()??[]);for(let e of g)S.add(e);return S.size}getForwardLinks(e,t=this.activeBranch){let s=this.getState(t),g=new Set(s.forward.get(e)??new Set);for(let s of this.structuralBundleNeighbors(e,t))g.add(s);return[...g].sort((e,t)=>e.localeCompare(t))}getForwardLinkEntries(e,t=this.activeBranch){let s=this.getState(t),g=this.getForwardLinks(e,t).map(t=>({kind:`doc`,target:t,anchor:s.backward.get(t)?.get(e)?.anchor??null,snippet:s.backward.get(t)?.get(e)?.snippet??null})),S=[...(s.externalForward.get(e)??new Map).entries()].map(([e,t])=>({kind:`external`,url:e,label:t.label,snippet:t.snippet})).sort((e,t)=>e.url.localeCompare(t.url));return[...g,...S]}getOrphans(e,t=`both`,s=this.activeBranch){let g=this.getState(s),S=new Set;for(let e of g.forward.keys()){let t=parseSkillBundleDocAnyScope(e);t?.kind===`reference`&&S.add(t.skillDocName)}let w=e=>{let t=parseSkillBundleDocAnyScope(e);return!t||!g.forward.has(e)?!1:t.kind===`skill`?S.has(e):g.forward.has(t.skillDocName)};return[...e].filter(e=>{let s=w(e),S=s||(g.backward.get(e)?.size??0)>0,E=s||(g.forward.get(e)?.size??0)>0;return t===`incoming`?!S:(t===`outgoing`||!S)&&!E}).sort((e,t)=>e.localeCompare(t))}getHubs(e=20,t=this.activeBranch){return[...this.getState(t).backward.entries()].map(([e,t])=>({docName:e,count:t.size})).sort((e,t)=>t.count===e.count?e.docName.localeCompare(t.docName):t.count-e.count).slice(0,e)}getDeadLinks(e,t,s=this.activeBranch){let g=this.getState(s),S=new Set(e),w=t?.length?new Set(t):null;return[...g.backward.entries()].filter(([e,t])=>{if(S.has(e))return!1;if(!w)return t.size>0;for(let e of t.keys())if(w.has(e))return!0;return!1}).map(([e,t])=>({target:e,sources:[...t.entries()].filter(([e])=>!w||w.has(e)).map(([e,t])=>({source:e,anchor:t.anchor,snippet:t.snippet})).sort((e,t)=>e.source.localeCompare(t.source))})).filter(e=>e.sources.length>0).sort((e,t)=>t.sources.length===e.sources.length?e.target.localeCompare(t.target):t.sources.length-e.sources.length)}getLinkGraph(e=this.activeBranch){let t=this.getState(e),s=new Map,g=[];for(let[e,S]of t.forward){s.set(e,{kind:`doc`,id:e,docName:e,anchor:getRepresentativeAnchor(t.backward.get(e))});for(let w of S)s.set(w,{kind:`doc`,id:w,docName:w,anchor:getRepresentativeAnchor(t.backward.get(w))}),g.push({source:e,target:w})}for(let[e,S]of t.externalForward){s.set(e,{kind:`doc`,id:e,docName:e,anchor:getRepresentativeAnchor(t.backward.get(e))});for(let[t,w]of S){let S=externalNodeId(t);s.set(S,{kind:`external`,id:S,url:t,label:w.label}),g.push({source:e,target:S})}}for(let S of t.forward.keys())if(parseSkillBundleDocAnyScope(S)?.kind===`skill`)for(let w of this.structuralBundleNeighbors(S,e))t.forward.get(S)?.has(w)||t.forward.get(w)?.has(S)||(s.set(S,{kind:`doc`,id:S,docName:S,anchor:getRepresentativeAnchor(t.backward.get(S))}),s.set(w,{kind:`doc`,id:w,docName:w,anchor:getRepresentativeAnchor(t.backward.get(w))}),g.push({source:S,target:w}));return{nodes:[...s.values()].sort((e,t)=>e.id.localeCompare(t.id)),links:g}}getLinkGraphNeighborhood(e,t,s=this.activeBranch){let g=this.getState(s),S=new Map;for(let e of g.externalForward.values())for(let[t,s]of e)S.has(t)||S.set(t,s.label);let w=new Set([e]),E=[{nodeId:e,degree:0}],D=0;for(;D<E.length;){let e=E[D++];if(e.degree>=t)continue;let S=externalUrlFromNodeId(e.nodeId),O=new Set;if(S)for(let e of g.externalBackward.get(S)?.keys()??[])O.add(e);else{for(let t of g.forward.get(e.nodeId)??new Set)O.add(t);for(let t of g.externalForward.get(e.nodeId)?.keys()??[])O.add(externalNodeId(t));for(let t of g.backward.get(e.nodeId)?.keys()??[])O.add(t);for(let t of this.structuralBundleNeighbors(e.nodeId,s))O.add(t)}for(let t of O)w.has(t)||(w.add(t),E.push({nodeId:t,degree:e.degree+1}))}let O=[];for(let[e,t]of g.forward)if(w.has(e))for(let s of t)w.has(s)&&O.push({source:e,target:s});for(let[e,t]of g.externalForward)if(w.has(e))for(let s of t.keys()){let t=externalNodeId(s);w.has(t)&&O.push({source:e,target:t})}for(let e of w)if(parseSkillBundleDocAnyScope(e)?.kind===`skill`)for(let t of this.structuralBundleNeighbors(e,s))w.has(t)&&(g.forward.get(e)?.has(t)||g.forward.get(t)?.has(e)||O.push({source:e,target:t}));return{nodes:[...w].sort().map(e=>{let t=externalUrlFromNodeId(e);return t?{kind:`external`,id:e,url:t,label:S.get(t)??null}:{kind:`doc`,id:e,docName:e,anchor:getRepresentativeAnchor(g.backward.get(e))}}),links:O}}async saveToDisk(e=this.activeBranch){let t=this.cachePath(e);mkdirSync(dirname(t),{recursive:!0});let s=this.getState(e),g=this.mtimesByBranch.get(e),S={...serializeState(s),...g?{mtimes:Object.fromEntries(g)}:{}};await writeFile(t,JSON.stringify(S,null,2),`utf-8`)}async loadFromDisk(e=this.activeBranch){let t=this.cachePath(e);if(!existsSync(t))return!1;try{let s=await readFile$1(t,`utf-8`),g=JSON.parse(s);return this.states.set(e,deserializeState(g)),g.mtimes?this.mtimesByBranch.set(e,new Map(Object.entries(g.mtimes))):this.mtimesByBranch.delete(e),!0}catch(t){return console.warn(`[backlinks] Failed to load cache for ${e}:`,t),!1}}clear(e=this.activeBranch){this.states.set(e,createEmptyState$1()),this.mtimesByBranch.delete(e)}async rebuildFromDisk(e=this.activeBranch){let t=createEmptyState$1(),s=new Map,g=[];await this.walkForPaths(this.contentDir,g);let S=new Set,w=g.filter(({docName:e})=>S.has(e)?!1:(S.add(e),!0)),E=50;for(let e=0;e<w.length;e+=50){let g=w.slice(e,e+50),S=await Promise.allSettled(g.map(async({docName:e,filePath:t})=>{let[s,g]=await Promise.all([stat$1(t),readFile$1(t,`utf-8`)]);return{docName:e,mtimeMs:s.mtimeMs,markdown:g}}));for(let e of S){if(e.status===`rejected`){console.warn(`[backlinks] Failed to rebuild entry:`,e.reason);continue}let{docName:g,mtimeMs:S,markdown:w}=e.value;s.set(g,S);let{body:E}=stripFrontmatter(w),D=extractWikiLinksFromMarkdown(E,g),O=extractMarkdownLinksFromMarkdown(E,g),k=extractExternalWikiLinksFromMarkdown(E),j=extractExternalMarkdownLinksFromMarkdown(E,g),F=new Set(D.map(e=>e.target)),L=[...D,...O.filter(e=>!F.has(e.target))],B=new Set(k.map(e=>e.url)),H=[...k,...j.filter(e=>!B.has(e.url))],q=new Set,ee=new Map;t.forward.set(g,q),t.externalForward.set(g,ee);for(let e of L){if(!e.target)continue;let s=managedArtifactDocNameFromContentTarget(e.target)??e.target;q.add(s);let S=t.backward.get(s);S||(S=new Map,t.backward.set(s,S)),S.set(g,mergeLinkMeta(S.get(g),{anchor:e.anchor,snippet:e.snippet}))}for(let e of H){if(!e.url)continue;ee.set(e.url,{label:e.label,snippet:e.snippet});let s=t.externalBackward.get(e.url);s||(s=new Map,t.externalBackward.set(e.url,s)),s.set(g,{label:e.label,snippet:e.snippet})}}}this.states.set(e,t),this.mtimesByBranch.set(e,s)}async walkForPaths(e,t){let s;try{s=await readdir(e,{withFileTypes:!0})}catch(t){console.warn(`[backlinks] Failed to read directory ${e}:`,t);return}for(let g of s){let s=join(e,g.name);if(g.isDirectory()){let e=toPosix(relative(this.contentDir,s));if(this.contentFilter&&e&&this.contentFilter.isDirExcluded(e))continue;await this.walkForPaths(s,t)}else if(g.isFile()&&isSupportedDocFile(g.name)){let e=toPosix(relative(this.contentDir,s));if(this.contentFilter?.isExcluded(e))continue;t.push({docName:stripDocExtension(e),filePath:s})}}}async reconcileWithDisk(e=this.activeBranch){if(!existsSync(this.contentDir))return{added:0,updated:0,deleted:0};let t=this.mtimesByBranch.get(e)??new Map,s=[];await this.walkForPaths(this.contentDir,s);let g=new Set,S=s.filter(({docName:e})=>g.has(e)?!1:(g.add(e),!0)),w=new Set(S.map(e=>e.docName)),E=new Map,D=0,O=0,k=[],j=await Promise.allSettled(S.map(async({docName:e,filePath:t})=>({docName:e,filePath:t,mtimeMs:(await stat$1(t)).mtimeMs})));for(let e of j){if(e.status===`rejected`)continue;let{docName:s,filePath:g,mtimeMs:S}=e.value,w=t.get(s);if(w!==void 0&&w===S){E.set(s,S);continue}k.push({docName:s,filePath:g,mtimeMs:S,isNew:w===void 0})}let F=50;for(let t=0;t<k.length;t+=50){let s=k.slice(t,t+50),g=await Promise.allSettled(s.map(async({docName:e,filePath:t,mtimeMs:s,isNew:g})=>({docName:e,mtimeMs:s,isNew:g,markdown:await readFile$1(t,`utf-8`)})));for(let t of g){if(t.status===`rejected`){console.warn(`[backlinks] Failed to reconcile file:`,t.reason);continue}let{docName:s,mtimeMs:g,isNew:S,markdown:w}=t.value;this.updateDocumentFromMarkdown(s,w,e),E.set(s,g),S?D++:O++}}let L=0,B=new Set([...t.keys(),...this.getState(e).forward.keys()]);for(let t of B)parseGlobalSkillBundleDoc(t)||w.has(t)||(this.deleteDocument(t,e),L++);return this.mtimesByBranch.set(e,E),{added:D,updated:O,deleted:L}}async ingestGlobalSkillBundles(e,t=this.activeBranch){let s=new Set;for(let g of e){if(!existsSync(g))continue;let e;try{e=await readdir(g,{withFileTypes:!0})}catch(e){console.warn(`[backlinks] Failed to read global skills root ${g}:`,e);continue}for(let S of e){if(!S.isDirectory())continue;let e=S.name,w=join(g,e),E=skillLiveDocName(`global`,e);existsSync(join(w,`SKILL.md`))&&parseGlobalSkillBundleDoc(E)&&(this.registerNodeOnly(E,t),s.add(E));let D=[];await this.walkGlobalSkillReferences(join(w,`references`),e,``,D);for(let{docName:e}of D)this.registerNodeOnly(e,t),s.add(e)}}let g=[];for(let e of this.getState(t).forward.keys())parseGlobalSkillBundleDoc(e)&&!s.has(e)&&g.push(e);for(let e of g)this.deleteDocument(e,t)}async walkGlobalSkillReferences(e,t,s,g){let S;try{S=await readdir(e,{withFileTypes:!0})}catch(t){t?.code!==`ENOENT`&&console.warn(`[backlinks] Failed to read skill references dir ${e}:`,t);return}for(let w of S){let S=s?`${s}/${w.name}`:w.name;if(w.isDirectory())await this.walkGlobalSkillReferences(join(e,w.name),t,S,g);else if(w.isFile()&&isSupportedDocFile(w.name)){let e=stripDocExtension(S);g.push({docName:`${MANAGED_ARTIFACT_PREFIX_SKILL}global/${t}/references/${e}`})}}}};function extractActorIdentity(e,t){let s=normalizeSummary(e.summary);if(s.kind===`invalid`)return{kind:`invalid-summary`};let g=parseAgentBodyFields(e),S=t?.()??null;return g.rawAgentId!==void 0&&g.writerId!==void 0?{kind:`agent`,writerId:g.writerId,displayName:g.displayName,colorSeed:g.colorSeed??g.rawAgentId,clientName:g.clientName,clientVersion:g.clientVersion,label:g.label,actor:{principalId:S?.id,agentType:resolveAgentType(g.clientName),clientName:g.clientName,clientVersion:g.clientVersion,label:g.label},summary:s}:S?{kind:`principal`,writerId:S.id,displayName:S.display_name,colorSeed:S.id,actor:{principalId:S.id},summary:s}:{kind:`anonymous`,summary:s}}const ANCESTOR_WALK_DEPTH_LIMIT$1=30;function isProjectRoot(e){try{return statSync(resolve(e,OK_PROJECT_MARKER)).isFile()}catch(e){let t=e?.code;if(t===`ENOENT`||t===`ENOTDIR`)return!1;throw e}}function findEnclosingProjectRoot(e){let t=resolve(e),s=0;for(;s<ANCESTOR_WALK_DEPTH_LIMIT$1;){let e=!1;try{e=isProjectRoot(t)}catch{e=!1}if(e)return{rootPath:t,distance:s};let g=dirname(t);if(g===t)return null;t=g,s+=1}return null}function parsePorcelainPaths(e){let t=[];for(let s of e.split(`
851
855
  `)){if(s.length<4)continue;let e=s.slice(3),g=e.indexOf(` -> `),S=g>=0?e.slice(g+4):e;S.length>0&&t.push(S)}return t}function parseDiffPaths(e){return e.split(`
852
856
  `).map(e=>e.trim()).filter(e=>e.length>0)}async function dirtyFilesOverlapWith(e,t){let{git:s}=createGitInstance(e),[g,S]=await Promise.all([s.raw([`status`,`--porcelain`]),s.raw([`diff`,`--name-only`,`HEAD..${t}`])]),w=new Set(parsePorcelainPaths(g));if(w.size===0)return{conflicts:!1,files:[]};let E=parseDiffPaths(S);if(E.length===0)return{conflicts:!1,files:[]};let D=new Set;for(let e of E)w.has(e)&&D.add(e);return D.size===0?{conflicts:!1,files:[]}:{conflicts:!0,files:Array.from(D).sort()}}function isValidBranchInfoPath(e,t){if(typeof e!=`string`)return!1;if(e.length===0)return t===`folder`;if(e.startsWith(`/`)||e.includes(`\\`)||/[\x00-\x1F\x7F]/.test(e))return!1;for(let t of e.split(`/`))if(t.length===0||t===`..`||t===`.git`)return!1;return!0}async function computeBranchInfo(e,t,s,g){let{git:S}=createGitInstance(e);await S.raw([`rev-parse`,`--git-dir`]);let w=(async()=>{try{let e=(await S.raw([`symbolic-ref`,`HEAD`])).trim(),t=/^refs\/heads\/(.+)$/.exec(e);return{detached:!1,currentBranch:t?t[1]:null,currentHeadSha:null}}catch{let e=(await S.raw([`rev-parse`,`--short=7`,`HEAD`])).trim();return e.length===0?{detached:!1,currentBranch:null,currentHeadSha:null}:{detached:!0,currentBranch:null,currentHeadSha:e}}})(),E=w.then(async e=>{if(g===`folder`&&s===``)return!0;let t=e.detached?`HEAD`:e.currentBranch;if(!t)return!1;try{return await S.raw([`cat-file`,`-e`,`${t}:${s}`]),!0}catch{return!1}}),D=S.raw([`rev-parse`,`--verify`,`refs/heads/${t}`]).then(()=>!0).catch(()=>!1),O=dirtyFilesOverlapWith(e,t).catch(e=>{if(isBranchResolutionError(e))return{conflicts:!1,files:[]};let s=e instanceof Error?e.message:String(e),g=s.length>500?`${s.slice(0,500)}…`:s;return console.warn(`[git-branch-info] action=dirty-overlap-failed branch=${t} error=${g}`),{conflicts:!1,files:[]}}),[k,j,F,L]=await Promise.all([w,E,D,O]);return k.detached?{detached:!0,currentBranch:null,currentHeadSha:k.currentHeadSha,shareTargetExists:j,dirtyConflicts:L,branchIsLocal:F}:{detached:!1,currentBranch:k.currentBranch,currentHeadSha:null,shareTargetExists:j,dirtyConflicts:L,branchIsLocal:F}}const BRANCH_INFO_HANDLER_TAG=`git-branch-info`;function isBranchResolutionError(e){let t=e instanceof Error?e.message:String(e);return/unknown revision|bad revision|ambiguous argument/i.test(t)}const BRANCH_IN_OTHER_WORKTREE_RE=/'[^']+' is already (?:checked out|used by worktree) at '([^']+)'/;function isBranchInOtherWorktreeError(e){let t=(e instanceof Error?e.message:typeof e==`string`?e:``).match(BRANCH_IN_OTHER_WORKTREE_RE);if(t===null)return{held:!1};let s=t[1];if(s===void 0||s.length===0)return{held:!1};let g;try{g=realpathSync(s)}catch{g=s}return{held:!0,path:g}}const CHECKOUT_HANDLER_TAG=`git-checkout`,isBranchNotFoundFetchError=isBranchNotFoundGitError;async function runCheckoutFlow(e,t){let{git:s}=createGitInstance(e),g=await s.raw([`rev-parse`,`--verify`,`refs/heads/${t}`]).then(()=>!0).catch(()=>!1);if(!g)try{await s.raw([`fetch`,`origin`,t])}catch(e){return{ok:!1,reason:isBranchNotFoundFetchError(e)?`branch-not-found`:`fetch-failed`}}let S=await dirtyFilesOverlapWith(e,g?t:`origin/${t}`);if(S.conflicts)return{ok:!1,reason:`dirty-conflict`,files:S.files};try{return await s.raw([`checkout`,t]),{ok:!0}}catch(e){let s=isBranchInOtherWorktreeError(e);if(s.held)return console.warn(`[git-checkout] reason=branch-in-other-worktree branch=${t} held_at=${s.path}`),{ok:!1,reason:`branch-in-other-worktree`,otherWorktreePath:s.path};let g=e instanceof Error?e.message:String(e),S=g.length>500?`${g.slice(0,500)}…`:g;return console.warn(`[git-checkout] action=checkout-failed branch=${t} error=${S}`),{ok:!1,reason:`checkout-failed`}}}const defaultGitConfigReader=(e,t,s)=>{let g=spawnSync(`git`,[`config`,s===`worktree`?`--worktree`:s===`local`?`--local`:`--global`,t],{cwd:e,encoding:`utf-8`,timeout:5e3});return g.status!==0||!g.stdout?null:g.stdout.trim()||null};function isLinkedWorktree(e){let t=spawnSync(`git`,[`rev-parse`,`--git-dir`],{cwd:e,encoding:`utf-8`,timeout:5e3}),s=spawnSync(`git`,[`rev-parse`,`--git-common-dir`],{cwd:e,encoding:`utf-8`,timeout:5e3});return t.status!==0||s.status!==0?!1:resolve(e,t.stdout.trim())!==resolve(e,s.stdout.trim())}function ensureWorktreeConfigExtension(e){let t=spawnSync(`git`,[`config`,`--local`,`--get`,`extensions.worktreeConfig`],{cwd:e,encoding:`utf-8`,timeout:5e3});if(t.status===0&&/^(true|yes|on|1)$/i.test(t.stdout.trim()))return;let s=spawnSync(`git`,[`config`,`--local`,`extensions.worktreeConfig`,`true`],{cwd:e,encoding:`utf-8`,timeout:5e3});if(s.status!==0){let e=s.stderr?.trim()??``,t=s.error?` [${s.error.message}]`:``;throw Error(`failed to enable extensions.worktreeConfig: ${e}${t}`)}}async function resolveGitIdentity(e,t,s,g=defaultGitConfigReader){let S=g(e,`user.name`,`worktree`),w=g(e,`user.email`,`worktree`);if(S&&w)return{name:S,email:w};let E=g(e,`user.name`,`local`),D=g(e,`user.email`,`local`);if(E&&D)return{name:E,email:D};let O=g(e,`user.name`,`global`),k=g(e,`user.email`,`global`);if(O&&k)return{name:O,email:k};if(t&&s){let e=await t.get(s);if(e){let t=e.name??e.login,s=e.email??`${e.login}@users.noreply.github.com`;if(t)return{name:t,email:s}}}return null}function writeGitIdentity(e,t,s){let g=`--local`;isLinkedWorktree(e)&&(ensureWorktreeConfigExtension(e),g=`--worktree`);let S=(t,s)=>{let S=spawnSync(`git`,[`config`,g,t,s],{cwd:e,encoding:`utf-8`,timeout:5e3});if(S.status!==0){let e=S.stderr?.trim()??``,s=S.error?` [${S.error.message}]`:``;throw Error(`git config ${g} ${t} failed: ${e}${s}`)}};S(`user.name`,t),S(`user.email`,s)}const CONFIG_FILENAME=`config.yml`;function assertNotSymlink(e,t){let s;try{s=lstatSync(e)}catch(e){if(e.code===`ENOENT`)return;throw e}if(s.isSymbolicLink())throw Error(`Refusing to follow symlink at ${t} (${e}). An untrusted upstream may have committed this symlink to redirect writes outside the project. Remove the symlink and re-run.`)}function packageVersionMajorMinor(e){let[t=`0`,s=`0`]=e.split(`.`);return`${t.length>0?t:`0`}.${s.length>0?s:`0`}`}function quoteYamlScalar(e){return/^[A-Za-z0-9._\-/]+$/.test(e)?e:JSON.stringify(e)}function buildConfigYmlContent(e,t){let s=`# yaml-language-server: $schema=https://unpkg.com/@inkeep/open-knowledge@latest/dist/schemas/${CONFIG_SCHEMA_MAJOR_PATH}/config.project.schema.json
853
857
  # OpenKnowledge — project configuration
@@ -1914,7 +1918,7 @@ Every document outside this file and \`log.md\` carries a non-empty \`type\` in
1914
1918
  `,OKF_LOG_MD=`# Log
1915
1919
 
1916
1920
  Change history for this knowledge base, newest entry first. Add a dated entry (\`## YYYY-MM-DD: <summary>\`) whenever you create, edit, or restructure content — one entry per working session, not per file.
1917
- `,STARTER_PACKS={"knowledge-base":{id:`knowledge-base`,name:`Knowledge base`,description:`Trusted articles from your sources.`,defaultSubfolder:`brain`,folders:KNOWLEDGE_BASE_FOLDERS,templates:KNOWLEDGE_BASE_TEMPLATES,rootFiles:{"log.md":KNOWLEDGE_BASE_LOG_MD}},"software-lifecycle":{id:`software-lifecycle`,name:`Software lifecycle`,description:`Proposals, decisions, and specs.`,defaultSubfolder:`project-docs`,folders:SOFTWARE_LIFECYCLE_FOLDERS,templates:SOFTWARE_LIFECYCLE_TEMPLATES},"codebase-wiki":{id:`codebase-wiki`,name:`Codebase wiki`,description:"An agent-authored, navigable wiki of your codebase — architecture, modules, flows, concepts, and guides, with diagrams, cross-links, and source references. Generated and refreshed by the `wiki` workflow; version-controlled and private by default.",defaultSubfolder:void 0,folders:CODEBASE_WIKI_FOLDERS,templates:CODEBASE_WIKI_TEMPLATES,rootFiles:{"wiki/OVERVIEW.md":CODEBASE_WIKI_OVERVIEW_MD,"wiki/log.md":CODEBASE_WIKI_LOG_MD}},"plain-notes":{id:`plain-notes`,name:`Plain notes`,description:`Notes and daily entries.`,defaultSubfolder:void 0,folders:PLAIN_NOTES_FOLDERS,templates:PLAIN_NOTES_TEMPLATES},okf:{id:`okf`,name:`Open Knowledge Format`,description:`Wiki using Google's Open Knowledge Format.`,defaultSubfolder:void 0,folders:OKF_FOLDERS,templates:OKF_TEMPLATES,rootFiles:{"welcome.md":OKF_WELCOME_MD,"index.md":OKF_INDEX_MD,"log.md":OKF_LOG_MD}},"writing-pipeline":{id:`writing-pipeline`,name:`Writing pipeline`,description:`From first draft to finished piece.`,defaultSubfolder:`writing`,folders:WRITING_PIPELINE_FOLDERS,templates:WRITING_PIPELINE_TEMPLATES},"entity-vault":{id:`entity-vault`,name:`Personal CRM`,description:`Track the people, companies, and meetings.`,defaultSubfolder:`vault`,folders:ENTITY_VAULT_FOLDERS,templates:ENTITY_VAULT_TEMPLATES,rootFiles:{"log.md":ENTITY_VAULT_LOG_MD,"USER.md":ENTITY_VAULT_USER_MD,"SOUL.md":ENTITY_VAULT_SOUL_MD,"ACCESS_POLICY.md":ENTITY_VAULT_ACCESS_POLICY_MD,"HEARTBEAT.md":ENTITY_VAULT_HEARTBEAT_MD}},worldbuilding:{id:`worldbuilding`,name:`Worldbuilding`,description:`A wiki for your story world.`,defaultSubfolder:`world`,folders:WORLDBUILDING_FOLDERS,templates:WORLDBUILDING_TEMPLATES}},STARTER_PACK_IDS=Object.keys(STARTER_PACKS);function resolvePack(e){return e&&STARTER_PACKS[e]||STARTER_PACKS[DEFAULT_PACK_ID]}function isKnownPackId(e){return typeof e==`string`&&STARTER_PACK_IDS.includes(e)}function coercePackId(e){return isKnownPackId(e)?e:void 0}function deriveFolderSummary(e){let t=e.trim(),s=(/^([^.!?]+[.!?])/.exec(t)?.[1]??t).trim();return s.length<=140?s:`${s.slice(0,137)}…`}function listStarterPacks(){return STARTER_PACK_IDS.map(e=>{let t=STARTER_PACKS[e];return{id:t.id,name:t.name,description:t.description,defaultSubfolder:t.defaultSubfolder,folders:t.folders.map(e=>({path:e.path,summary:deriveFolderSummary(e.description)})),entryCounts:computePackEntryCounts(t)}})}function computePackEntryCounts(e){let t=e.folders.length,s=0;for(let t of e.folders)s+=1+(t.extraTemplates?.length??0);return s+=e.rootFiles?Object.keys(e.rootFiles).length:0,{files:s,folders:t}}const STARTER_FOLDERS=KNOWLEDGE_BASE_FOLDERS,STARTER_TEMPLATES=KNOWLEDGE_BASE_TEMPLATES,LOG_MD_TEMPLATE=KNOWLEDGE_BASE_LOG_MD,STARTER_FOLDER_FRONTMATTER_FILENAME=`frontmatter.yml`;function buildStarterFolderFrontmatterYaml(e){let t=[];t.push(`title: ${yamlScalar(e.title)}`),t.push(`description: ${yamlScalar(e.description)}`),t.push(`tags:`);for(let s of e.tags)t.push(` - ${yamlScalar(s)}`);return`${t.join(`
1921
+ `,STARTER_PACKS={"knowledge-base":{id:`knowledge-base`,name:`Knowledge base`,description:`Trusted articles from your sources.`,defaultSubfolder:`brain`,folders:KNOWLEDGE_BASE_FOLDERS,templates:KNOWLEDGE_BASE_TEMPLATES,rootFiles:{"log.md":KNOWLEDGE_BASE_LOG_MD}},"software-lifecycle":{id:`software-lifecycle`,name:`Software lifecycle`,description:`Proposals, decisions, and specs.`,defaultSubfolder:`project-docs`,folders:SOFTWARE_LIFECYCLE_FOLDERS,templates:SOFTWARE_LIFECYCLE_TEMPLATES},"codebase-wiki":{id:`codebase-wiki`,name:`Codebase wiki`,description:`A wiki to help navigate your codebase.`,defaultSubfolder:void 0,folders:CODEBASE_WIKI_FOLDERS,templates:CODEBASE_WIKI_TEMPLATES,rootFiles:{"wiki/OVERVIEW.md":CODEBASE_WIKI_OVERVIEW_MD,"wiki/log.md":CODEBASE_WIKI_LOG_MD}},"plain-notes":{id:`plain-notes`,name:`Plain notes`,description:`Notes and daily entries.`,defaultSubfolder:void 0,folders:PLAIN_NOTES_FOLDERS,templates:PLAIN_NOTES_TEMPLATES},okf:{id:`okf`,name:`Open Knowledge Format`,description:`Wiki using Google's Open Knowledge Format.`,defaultSubfolder:void 0,folders:OKF_FOLDERS,templates:OKF_TEMPLATES,rootFiles:{"welcome.md":OKF_WELCOME_MD,"index.md":OKF_INDEX_MD,"log.md":OKF_LOG_MD}},"writing-pipeline":{id:`writing-pipeline`,name:`Writing pipeline`,description:`From first draft to finished piece.`,defaultSubfolder:`writing`,folders:WRITING_PIPELINE_FOLDERS,templates:WRITING_PIPELINE_TEMPLATES},"entity-vault":{id:`entity-vault`,name:`Personal CRM`,description:`Track the people, companies, and meetings.`,defaultSubfolder:`vault`,folders:ENTITY_VAULT_FOLDERS,templates:ENTITY_VAULT_TEMPLATES,rootFiles:{"log.md":ENTITY_VAULT_LOG_MD,"USER.md":ENTITY_VAULT_USER_MD,"SOUL.md":ENTITY_VAULT_SOUL_MD,"ACCESS_POLICY.md":ENTITY_VAULT_ACCESS_POLICY_MD,"HEARTBEAT.md":ENTITY_VAULT_HEARTBEAT_MD}},worldbuilding:{id:`worldbuilding`,name:`Worldbuilding`,description:`A wiki for your story world.`,defaultSubfolder:`world`,folders:WORLDBUILDING_FOLDERS,templates:WORLDBUILDING_TEMPLATES}},STARTER_PACK_IDS=Object.keys(STARTER_PACKS);function resolvePack(e){return e&&STARTER_PACKS[e]||STARTER_PACKS[DEFAULT_PACK_ID]}function isKnownPackId(e){return typeof e==`string`&&STARTER_PACK_IDS.includes(e)}function coercePackId(e){return isKnownPackId(e)?e:void 0}function deriveFolderSummary(e){let t=e.trim(),s=(/^([^.!?]+[.!?])/.exec(t)?.[1]??t).trim();return s.length<=140?s:`${s.slice(0,137)}…`}function listStarterPacks(){return STARTER_PACK_IDS.map(e=>{let t=STARTER_PACKS[e];return{id:t.id,name:t.name,description:t.description,defaultSubfolder:t.defaultSubfolder,folders:t.folders.map(e=>({path:e.path,summary:deriveFolderSummary(e.description)})),entryCounts:computePackEntryCounts(t)}})}function computePackEntryCounts(e){let t=e.folders.length,s=0;for(let t of e.folders)s+=1+(t.extraTemplates?.length??0);return s+=e.rootFiles?Object.keys(e.rootFiles).length:0,{files:s,folders:t}}const STARTER_FOLDERS=KNOWLEDGE_BASE_FOLDERS,STARTER_TEMPLATES=KNOWLEDGE_BASE_TEMPLATES,LOG_MD_TEMPLATE=KNOWLEDGE_BASE_LOG_MD,STARTER_FOLDER_FRONTMATTER_FILENAME=`frontmatter.yml`;function buildStarterFolderFrontmatterYaml(e){let t=[];t.push(`title: ${yamlScalar(e.title)}`),t.push(`description: ${yamlScalar(e.description)}`),t.push(`tags:`);for(let s of e.tags)t.push(` - ${yamlScalar(s)}`);return`${t.join(`
1918
1922
  `)}\n`}function yamlScalar(e){return e===``?`""`:/[:#\n"'\\]|^\s|\s$/.test(e)?`"${e.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`)}"`:e}function resolveFileContent(e,t){if(t.rootFiles?.[e]!==void 0)return t.rootFiles[e];let s=/^(.+)\/\.ok\/frontmatter\.yml$/.exec(e);if(s){let e=t.folders.find(e=>e.path===s[1]);return e?buildStarterFolderFrontmatterYaml(e):void 0}let g=/^(.+)\/\.ok\/templates\/([^/]+)\.md$/.exec(e);if(g){let e=g[2]??``;return t.templates[e]}}async function applySeed(e,t={}){let s=Date.now(),g=resolve(t.projectDir??process.cwd()),S=resolvePack(t.packId??`knowledge-base`),w=0,E=[],D=[];for(let t of e.created)try{let e=assertEntryPathInProject(g,t.path);D.push({entry:t,absPath:e})}catch(e){E.push({path:typeof t.path==`string`?t.path:String(t.path),error:e instanceof SeedRootDirError||e instanceof Error?e.message:String(e)})}for(let{entry:e,absPath:t}of D.filter(e=>e.entry.kind===`folder`))try{mkdirSync(t,{recursive:!0}),w+=1}catch(t){E.push({path:e.path,error:t instanceof Error?t.message:String(t)})}for(let{entry:e,absPath:t}of D.filter(e=>e.entry.kind===`file`)){let s=e.template??e.path,g=resolveFileContent(s,S);if(g===void 0){E.push({path:e.path,error:`No content template registered for template id "${s}" in pack "${S.id}"`});continue}if(!existsSync(t))try{writeFileSync(t,g,`utf-8`),w+=1}catch(t){E.push({path:e.path,error:t instanceof Error?t.message:String(t)})}}let O=await installPackSkill(g,S.id);return{applied:w,errors:E,durationMs:Date.now()-s,packSkillsInstalled:O}}function frontmatterTemplateId(e){return`${e}/.ok/frontmatter.yml`}function templateFileTemplateId(e,t){return`${e}/.ok/templates/${t}.md`}function normalizeRootDir(e,t){if(!e)return``;let s=e.trim();if(s===``||s===`.`||s===`./`)return``;if(s.startsWith(`/`))throw new SeedRootDirError(`rootDir must be relative to the project directory, got: ${e}`);let g=s.replace(/\\/g,`/`).replace(/^\.\//,``).replace(/\/+$/,``);if(g.split(`/`).some(e=>e===`..`))throw new SeedRootDirError(`rootDir must not contain '..' segments, got: ${e}`);return assertEntryPathInProject(t,g),g}function joinRelative(e,t){return e===``?t:`${e}/${t}`}async function planSeed(e={}){let t=resolve(e.projectDir??process.cwd());if(!isProjectRoot(t))throw new SeedPrerequisiteError(`No ${OK_PROJECT_MARKER} found at ${t}. Run \`ok init\` first to scaffold the tool config.`);let s=normalizeRootDir(e.rootDir,t),g=resolvePack(e.packId??`knowledge-base`),S=[],w=[],E=[];s!==``&&(existsSync(join(t,s))?w.push({path:s,reason:`already-exists`}):S.push({path:s,kind:`folder`}));for(let e of g.folders){let D=joinRelative(s,e.path);existsSync(join(t,D))?w.push({path:D,reason:`already-exists`}):S.push({path:D,kind:`folder`});let O=`${D}/.ok`;existsSync(join(t,O))?w.push({path:O,reason:`already-exists`}):S.push({path:O,kind:`folder`});let k=`${O}/${STARTER_FOLDER_FRONTMATTER_FILENAME}`;existsSync(join(t,k))?w.push({path:k,reason:`already-exists`}):S.push({path:k,kind:`file`,template:frontmatterTemplateId(e.path)});let j=`${O}/templates`;existsSync(join(t,j))?w.push({path:j,reason:`already-exists`}):S.push({path:j,kind:`folder`});let F=[e.starterTemplate,...e.extraTemplates??[]];for(let s of F){let D=`${j}/${s}.md`;if(existsSync(join(t,D))){w.push({path:D,reason:`already-exists`});continue}if(g.templates[s]===void 0){let t=s===e.starterTemplate;E.push(t?`No starter template body registered for "${s}" in pack "${g.id}". The folder will land without a pre-selected template.`:`No body registered for extra template "${s}" in pack "${g.id}". The folder will land without that optional variant.`);continue}S.push({path:D,kind:`file`,template:templateFileTemplateId(e.path,s)})}}if(g.rootFiles)for(let e of Object.keys(g.rootFiles)){let g=joinRelative(s,e);existsSync(join(t,g))?w.push({path:g,reason:`already-exists`}):S.push({path:g,kind:`file`,template:e})}let D=resolvePackSkillSource(g.id),O=D?{name:D.name,pending:!existsSync(join(t,`.ok`,`skills`,D.name,`SKILL.md`))}:void 0;return{created:S,skipped:w,warnings:E,...O?{packSkill:O}:{}}}const PACK_INSPIRATION_NOTE=[`These are patterns to adapt to your domain, not a layout to copy verbatim.`,"To build a variant: create your own folders (via `write` or your editor) and reuse only the ideas that fit.","To adopt this pack as-is: re-run without `--dry-run`."].join(`
1919
1923
  `);function folderTemplateNames(e){return[e.starterTemplate,...e.extraTemplates??[]].join(`, `)}function formatPackRationale(e){let t=[`Pack: ${e.name} — ${e.description}`,``,PACK_INSPIRATION_NOTE,``];t.push(`Layout & rationale:`);for(let s of e.folders)t.push(` ${s.path}/ — ${s.title}`),t.push(` why: ${s.description}`),t.push(` templates: ${folderTemplateNames(s)}`);let s=e.rootFiles?Object.keys(e.rootFiles):[];return s.length>0&&t.push(``,`Root files: ${s.join(`, `)}`),t.join(`
1920
1924
  `)}function createSingleFlight(){let e=new Map;return{run(t,s){let g=e.get(t);if(g)return{promise:g,coalesced:!0};let S=s();e.set(t,S);let w=()=>{e.get(t)===S&&e.delete(t)};return S.then(w,w),{promise:S,coalesced:!1}},get size(){return e.size}}}function skillShadowPath(e,t){let s=e===`.`?``:e.replace(/^\.\//,``);return s?`${s}/.ok/skills/${t}`:`.ok/skills/${t}`}function isGitObjectNotFound(e){return/not a valid object name|not a tree object|bad revision|unknown revision|invalid object name/i.test(e)}async function restoreSkillVersion(e){let{shadow:t,contentDir:s,contentRoot:g,name:S,version:w}=e;if(!existsSync(t.workTree)||!existsSync(t.gitDir))return{ok:!1,code:`no-shadow`,error:`No shadow repo — nothing to restore from.`};let E=skillShadowPath(g,S),D=shadowGit(t),O;try{O=await D.raw(`ls-tree`,`-r`,`--name-only`,w,`--`,E)}catch(e){let t=e instanceof Error?e.message:String(e);return isGitObjectNotFound(t)?{ok:!1,code:`version-not-found`,error:`Version ${w.slice(0,8)} not found.`}:{ok:!1,code:`io-error`,error:`Failed to read version ${w.slice(0,8)}: ${t}`}}let k=O.split(`
@@ -1931,11 +1935,11 @@ Change history for this knowledge base, newest entry first. Add a dated entry (\
1931
1935
  `).filter(Boolean);ce.push(...e)}catch{}if(ce.length===0&&se.length===0&&de.length===0)return EMPTY;let fe=[...se,...de],me=[];if(fe.length>0){let t=parseGitLogOutput(await oe.raw(`log`,`--no-walk`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`,...fe)).map(e=>({...e,type:`checkpoint`}));if(ne&&(t=await filterEntriesByChain(e,t,O,S,ee,ae,Y)),ue&&se.length>0&&de.length>0){let e=new Set(se),s=t.filter(t=>e.has(t.sha)),g=t.filter(t=>!e.has(t.sha)),S=s.reduce((e,t)=>{let s=new Date(t.timestamp).getTime();return s<e?s:e},1/0);me=[...s,...g.filter(e=>new Date(e.timestamp).getTime()<S)]}else me=t}let ge=[...ce];for(let e of fe)ge.push(e);let _e=[];if(ge.length>0&&(_e=parseGitLogOutput(await oe.raw(`log`,`--full-history`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`,`-n`,String(D),...ge,...ne?[`--`,ne]:[])),_e.length>=D&&(k=!0),J))for(let t=0;t<O.length-1;t++){let s=O[t];if(s.renameCommit!==null)try{let t=await buildSeeds(e,s.renameCommit,S,Y);if(t.length===0)continue;let g=ee(s.path),w=parseGitLogOutput(await logSeededReachable(e,[`--full-history`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`,`-n`,String(D)],t,g));w.length>=D&&(k=!0),_e=[..._e,...w]}catch(e){console.warn(`[timeline] predecessor walk failed for step ${t} (${s.path}); skipping:`,e)}}let ve=[...me,..._e],ye=new Set,Ce=[];for(let e of ve)ye.has(e.sha)||(ye.add(e.sha),Ce.push(e));let we=Ce;Ce.length>0&&O.length>0&&(we=filterEntriesByOkActorDocs(Ce,O,await Promise.all(O.map(async t=>{if(t.renameCommit===null)return null;let s=await buildSeeds(e,t.renameCommit,S,Y);return s.length===0?new Set:buildAncestorShaSet(e,s,S,ae)})))),we.sort((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime());let Te=we;Te=Te.filter(e=>e.type!==`park`),H||(Te=Te.filter(e=>e.checkpoint?.kind!==`auto-consolidation`)),F.length>0&&(Te=Te.filter(e=>F.includes(e.type))),L.length>0&&(Te=Te.filter(e=>matchesAuthor(e,L))),B.length>0&&(Te=Te.filter(e=>!matchesAuthor(e,B)));let De=Te.length,je=Te.slice(E,E+w),Me=je.map(({rawBody:e,...t})=>t);return j(ge.length,Ce.length),{entries:Me,total:De,hasMore:k&&je.length>0||E+w<De}}catch(e){return console.warn(`[timeline] getDocumentHistory failed, returning empty result:`,e),j(0,0,!0),EMPTY}}async function getFolderTimeline(e,t,s=`.`,g){if(!existsSync(e.workTree)||!existsSync(e.gitDir)||t.includes(`..`)||t.includes(`\0`))return EMPTY;let S=g?.branch??`main`,w=Math.max(1,g?.limit??50),E=Math.max(0,g?.offset??0),D=s===`.`?``:s.replace(/^\.\//,``),O=t.replace(/^\.?\/+/,``).replace(/\/+$/,``),k=[D,O,`.ok`].filter(Boolean).join(`/`),j=shadowGit(e);try{let e=[];for(let t of[`refs/wip/${S}/`,`refs/checkpoints/${S}/`])try{let s=(await j.raw(`for-each-ref`,`--format=%(refname)`,t)).trim().split(`
1932
1936
  `).filter(Boolean);e.push(...s)}catch{}if(e.length===0)return EMPTY;let t=historyWalkCap(E,w),s=parseGitLogOutput(await j.raw(`log`,`--full-history`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`,`-n`,String(t),...e,`--`,k)),g=s.length>=t,D=O?`${O}/.ok/`:`.ok/`,F=new Set,L=[];for(let e of s){if(F.has(e.sha)||!isFolderArtifactSubject(e.message)||!e.contributors.some(e=>e.docs.some(e=>e.startsWith(D))))continue;F.add(e.sha);let{rawBody:t,...s}=e;L.push(s)}let B=L.length,H=L.slice(E,E+w);return{entries:H,total:B,hasMore:g&&H.length>0||E+w<B}}catch(e){return console.warn(`[timeline] getFolderTimeline failed, returning empty result:`,e),EMPTY}}let _httpDurationHist=null;function httpDurationHist(){return _httpDurationHist||=getMeter().createHistogram(`http.server.request.duration`,{description:`HTTP server request duration in seconds`,unit:`s`}),_httpDurationHist}let _hintEmittedCounter=null;function hintEmittedCounter(){return _hintEmittedCounter||=getMeter().createCounter(`ok.preview_attach.hint_emitted`,{description:`Count of preview-attach hints emitted on write-tool responses when no editor is attached to __system__. Covers both attach-preview-once (URL exists, no browser) and start-ui (no UI running anywhere) variants — the tool side disambiguates via the warning action; the metric name is retained as-is so existing dashboards keep working.`}),_hintEmittedCounter}let _agentPatchFmTouchCounter=null;function agentPatchFmTouchCounter(){return _agentPatchFmTouchCounter||=getMeter().createCounter(`ok.frontmatter.agent_patch_fm_touch_total`,{description:`Count of agent-patch calls whose find string targets the frontmatter region. Measures incidence during the soft-deprecation window before agent-patch FM-intersecting calls are enforced as 400. Bounded label: result ∈ {rejected, pre_deprecation_passthrough}.`}),_agentPatchFmTouchCounter}function findLooksLikeFrontmatter(e){return!!(/(^|\n)---(\s|\n|$)/.test(e)||/^\s*[\w-]+:\s+\S/.test(e))}let _renameAttributionCounter=null;function renameAttributionCounter(){return _renameAttributionCounter||=getMeter().createCounter(`ok.rename.attribution_kind`,{description:`Count of rename and rollback handler dispatches by attribution kind (agent | principal | anonymous)`}),_renameAttributionCounter}let _agentWriteGateFiredCounter=null;function agentWriteGateFiredCounter(){return _agentWriteGateFiredCounter||=getMeter().createCounter(`ok.agent_write.gate_fired_total`,{description:`Count of agent writes that ran the Site A content-divergence gate (denominator for the divergence rate). Bounded label: handler ∈ {agent-write-md, agent-patch, rollback}.`}),_agentWriteGateFiredCounter}let _agentWriteContentDivergenceCounter=null;function agentWriteContentDivergenceCounter(){return _agentWriteContentDivergenceCounter||=getMeter().createCounter(`ok.agent_write.content_divergence_total`,{description:`Count of agent writes whose converged Y.Text diverged from the composed intent (numerator for the divergence rate). Bounded labels: handler ∈ {agent-write-md, agent-patch, rollback}, divergence_type.`}),_agentWriteContentDivergenceCounter}let _searchCorpusTruncatedCounter=null;function searchCorpusTruncatedCounter(){return _searchCorpusTruncatedCounter||=getMeter().createCounter(`ok.search.corpus_truncated_total`,{description:`Count of search-corpus rebuilds where the name-only file tier hit OK_SEARCH_MAX_ENTRIES and dropped deepest-tail paths. One increment per truncated build; non-truncated builds do not increment.`}),_searchCorpusTruncatedCounter}function recordContentDivergenceGate(e,t){agentWriteGateFiredCounter().add(1,{handler:e}),t!==void 0&&agentWriteContentDivergenceCounter().add(1,{handler:e,divergence_type:t.divergenceType})}function resumeSyncOnAuthEvent(e,t){e.type===`complete`&&t?.()?.notifyCredentialsChanged().catch(()=>{})}const ROLLBACK_ORIGIN={source:`local`,skipStoreHooks:!1,context:{origin:`rollback-apply`,paired:!0}},MANAGED_RENAME_ORIGIN={source:`local`,skipStoreHooks:!1,context:{origin:`managed-rename`,paired:!0}},log$6=getLogger(`api`);function ytextHasConflictMarkers(e){return/^<{7} /m.test(e)&&/^={7}$/m.test(e)&&/^>{7} /m.test(e)}function safeDocPath(e,t){if(!e||e.includes(`..`)||e.includes(`\0`))return{error:`Invalid document name.`};let s=t===`.`?``:t.replace(/^\.\//,``),g=managedArtifactTimelinePaths(e);if(g.managed&&g.versioned)return{path:s?`${s}/${g.filePath}`:g.filePath};let S=getDocExtension(e);return{path:s?`${s}/${e}${S}`:`${e}${S}`}}const GENERIC_PASTE_NAMES=/^(image\.(png|jpe?g|gif|webp)|Clipboard.*|Untitled.*)$/i,SAFE_FILENAME_CHARS=/[^\p{L}\p{N}\p{M}\p{Extended_Pictographic}.\-_ ]/gu,STRIP_ON_SIGHT=/[/\\\x00-\x1f\x7f]/g;function sanitizeFilename(e){let t=e.replace(STRIP_ON_SIGHT,``);if(t=t.replace(SAFE_FILENAME_CHARS,`_`),t=t.replace(/_+/g,`_`).replace(/\.{2,}/g,`.`),t=t.replace(/^[._]+/,``),t=t.replace(/\.+$/,``),t===``)return`upload`;let s=255,g=new TextEncoder;if(g.encode(t).length>255){let e=t.lastIndexOf(`.`),s=e>=0?t.slice(e):``,S=e>=0?t.slice(0,e):t;for(;g.encode(S+s).length>255&&S.length>0;)S=S.slice(0,-1);t=(S||`upload`)+s,g.encode(t).length>255&&(t=`upload`)}return t}function resolveUploadDestDir(e,t,s){let g=t.trim();return g===``||g===`./`?resolve(s,dirname(e)):g===`/`?s:g.startsWith(`./`)?resolve(s,dirname(e),g.slice(2)):resolve(s,g)}function readTempFileHead(e,t){let s=openSync(e,`r`);try{let e=Buffer.alloc(t),g=readSync(s,e,0,t,0);return e.subarray(0,g)}finally{closeSync(s)}}const MAX_DEDUP_SCAN_CANDIDATES=1e3;async function streamingHashFile(e){let t=createHash(`sha256`);return await pipeline(createReadStream(e),t),t.digest(`hex`)}async function findDuplicateAsset(e,t,s){let g;try{g=await readdir(e)}catch{return null}let S=getLogger(`upload`),w=0;for(let E of g){let g=extname(E).slice(1).toLowerCase();if(!ASSET_EXTENSIONS.has(g))continue;let D=resolve(e,E),O;try{O=await stat$1(D)}catch{continue}if(!O.isFile()||O.size!==s)continue;if(w++,w>MAX_DEDUP_SCAN_CANDIDATES)return S.warn({event:`upload-dedup-skip`,reason:`scan-cap-exceeded`,destDir:e,scanned:MAX_DEDUP_SCAN_CANDIDATES,expectedSize:s},`[upload-dedup] candidate scan exceeded ${MAX_DEDUP_SCAN_CANDIDATES} same-size siblings — degrading to no-dedup for this upload`),null;let k;try{k=await streamingHashFile(D)}catch(e){let t=e.code;t!==`ENOENT`&&S.warn({event:`upload-dedup-skip`,reason:`read-failed`,code:t,entry:E},`[upload-dedup] skipped candidate — read failed`);continue}if(k===t)return E}return null}function readUploadBody(e,t){return new Promise((s,g)=>{let S;try{S=(0,import_lib.default)({headers:e.headers,limits:{files:1,fields:10,fieldSize:2*1024}})}catch(e){g(new UploadWriteError(`urn:ok:error:malformed-upload`,e));return}let w=!1,E=`upload`,D=``,O=``,k,j,F=!1,L=(e,t)=>{if(!w){if(w=!0,k)try{unlinkSync(k)}catch{}g(t instanceof UploadWriteError?t:new UploadWriteError(e,t))}},B=classifyUploadErrno;S.on(`field`,(e,t)=>{e===`parentDocName`&&(O=t)}),S.on(`file`,(e,g,S)=>{F=!0,E=S.filename||`upload`,D=S.mimeType||``;let H;try{H=mintTempUploadPath(t)}catch(e){L(B(e),e),g.resume();return}k=H;let q=new HashingPassThrough;pipeline(g,q,createWriteStream(H)).then(()=>{w||(w=!0,s({filename:E,mimeType:D,parentDocName:O,tempPath:H,sha:q.digest(),byteLength:q.byteLength()}))}).catch(e=>{j=e,L(B(e),e)})}),S.on(`error`,e=>{L(`urn:ok:error:malformed-upload`,e)}),S.on(`close`,()=>{w||j||F||(w=!0,s({filename:``,mimeType:``,parentDocName:O,tempPath:``,sha:``,byteLength:0}))}),e.on(`close`,()=>{w||j||e.complete||L(`urn:ok:error:malformed-upload`,Error(`client disconnected`))}),e.pipe(S)})}function safeSubdir(e,t){let s=resolve(e,t);if(!isWithinDir(s,e))throw Error(`Invalid directory: ${t}`);return s}function synthesizeShowAllAssetExt(e){let t=extname(e);return t?t.slice(1).toLowerCase():e.startsWith(`.`)&&e.length>1?e.slice(1).toLowerCase():`file`}const DEFAULT_SHOWALL_MAX_ENTRIES=5e4;function getShowAllMaxEntries(){let e=process.env.OK_SHOWALL_MAX_ENTRIES;if(e===void 0)return DEFAULT_SHOWALL_MAX_ENTRIES;let t=Number(e);return Number.isInteger(t)&&t>0?t:DEFAULT_SHOWALL_MAX_ENTRIES}const DEFAULT_SEARCH_MAX_ENTRIES=5e4;function getSearchMaxEntries(){let e=process.env.OK_SEARCH_MAX_ENTRIES;if(e===void 0)return DEFAULT_SEARCH_MAX_ENTRIES;let t=Number(e);return Number.isInteger(t)&&t>0?t:DEFAULT_SEARCH_MAX_ENTRIES}let showAllWalkInvocations=0,showAllWalkAborts=0;function __getShowAllWalkStatsForTesting(){return{invocations:showAllWalkInvocations,aborts:showAllWalkAborts}}function __resetShowAllWalkStatsForTesting(){showAllWalkInvocations=0,showAllWalkAborts=0}function showAllWantsNdjson(e){let t=e.headers.accept;return typeof t==`string`&&t.includes(`application/x-ndjson`)}async function*streamShowAllEntries(e){let{contentDir:t,contentFilter:s,dirFilter:g,getDocExtension:S,maxEntries:w,signal:E}=e,D=e.maxDepth??1/0;showAllWalkInvocations+=1;let O=0,k=!1,j=!1,F=e=>g?e===g||e.startsWith(`${g}/`):!0,L;try{L=await realpath(t)}catch{L=t}let B=e=>isWithinDir(e,L);async function H(e,t){let g;try{g=await readdir(e,{withFileTypes:!0})}catch(t){return console.warn(`[document-list][showAll] probe readdir failed for ${e}:`,t),!1}for(let S of g){let g=t?`${t}/${S.name}`:S.name;if(S.isDirectory()){if(s.isDirExcluded(g,{bypassFilters:!0}))continue;try{if(!B(await realpath(join(e,S.name))))continue}catch(t){console.warn(`[document-list][showAll] probe realpath failed for ${e}/${S.name}:`,t);continue}return!0}if(S.isFile()&&!s.isExcluded(g,{bypassFilters:!0}))return!0}return!1}async function*q(e,g,L){let q=[{absDir:e,relDir:g,depth:L}];for(let e=0;e<q.length;e++){if(E?.aborted){j=!0;return}let{absDir:g,relDir:L,depth:ee}=q[e],J;try{J=await readdir(g,{withFileTypes:!0})}catch(e){console.warn(`[document-list][showAll] readdir failed for ${g}:`,e);continue}for(let e of J){if(E?.aborted){j=!0;return}if(O>=w){k=!0;return}let J=L?`${L}/${e.name}`:e.name;if(e.isDirectory()){if(s.isDirExcluded(J,{bypassFilters:!0}))continue;let t=join(g,e.name),S;try{S=await realpath(t)}catch(e){console.warn(`[document-list][showAll] realpath failed for ${t}:`,e);continue}if(!B(S)){console.warn(`[document-list][showAll] refusing symlink-escape ${t} -> ${S}`);continue}if(F(J)){let e=null;try{e=await stat$1(t)}catch(e){console.warn(`[document-list][showAll] stat failed for ${t}:`,e)}O+=1;let s=ee>=D?await H(t,J):void 0;yield{kind:`folder`,path:J,size:0,modified:e?e.mtime.toISOString():``,docExt:`.md`,isSymlink:!1,canonicalDocName:null,targetPath:null,...s===void 0?{}:{hasChildren:s}}}ee<D&&q.push({absDir:t,relDir:J,depth:ee+1});continue}if(e.isSymbolicLink()){let w=join(g,e.name),E;try{E=await realpath(w)}catch(e){console.warn(`[document-list][showAll] symlink realpath failed for ${w}:`,e);continue}if(!B(E)){console.warn(`[document-list][showAll] refusing symlink-escape ${w} -> ${E}`);continue}let D;try{D=await stat$1(E)}catch(e){console.warn(`[document-list][showAll] symlink target stat failed for ${w}:`,e);continue}let k=toPosix(relative(t,E));if(D.isDirectory()){if(s.isDirExcluded(J,{bypassFilters:!0})||!F(J))continue;O+=1,yield{kind:`folder`,path:J,size:0,modified:D.mtime.toISOString(),docExt:`.md`,isSymlink:!0,canonicalDocName:k,targetPath:k,hasChildren:await H(E,J)};continue}if(!D.isFile()||s.isExcluded(J,{bypassFilters:!0})||!F(J))continue;if(O+=1,isSupportedDocFile(e.name)){let e=J.replace(/\.(md|mdx)$/i,``);yield{kind:`document`,docName:e,docExt:S(e),size:D.size,modified:D.mtime.toISOString(),isSymlink:!0,canonicalDocName:k.replace(/\.(md|mdx)$/i,``),targetPath:k}}else{let t=synthesizeShowAllAssetExt(e.name);yield{kind:`asset`,docName:J,docExt:t,path:J,assetExt:t,mediaKind:mediaKindForSidebarAssetExtension(t),referencedBy:[],size:D.size,modified:D.mtime.toISOString(),isSymlink:!0,canonicalDocName:null,targetPath:k}}continue}if(!e.isFile()||s.isExcluded(J,{bypassFilters:!0})||!F(J))continue;let Y=null;try{Y=await stat$1(join(g,e.name))}catch(t){console.warn(`[document-list][showAll] stat failed for ${g}/${e.name}:`,t);continue}if(isSupportedDocFile(e.name)){let e=J.replace(/\.(md|mdx)$/i,``),t=S(e);O+=1,yield{kind:`document`,docName:e,docExt:t,size:Y.size,modified:Y.mtime.toISOString(),isSymlink:!1,canonicalDocName:null,targetPath:null};continue}let te=synthesizeShowAllAssetExt(e.name),ne=mediaKindForSidebarAssetExtension(te);O+=1,yield{kind:`asset`,docName:J,docExt:te,path:J,assetExt:te,mediaKind:ne,referencedBy:[],size:Y.size,modified:Y.mtime.toISOString(),isSymlink:!1,canonicalDocName:null,targetPath:null}}}}return yield*q(g?join(t,g):t,g??``,1),j&&(showAllWalkAborts+=1),{truncated:k}}async function walkContentDirForShowAll(e){let{documents:t,...s}=e,g=streamShowAllEntries(s),S=await g.next();for(;!S.done;)t.push(S.value),S=await g.next();return S.value}function isValidRelativeContentPath(e){return!e||e.startsWith(`/`)||e.includes(`\\`)||e.includes(`\0`)?!1:e.split(`/`).every(e=>e&&e!==`.`&&e!==`..`)}function isReservedProjectStatePath(e){return e===`.ok`||e.startsWith(`.ok/`)||e===`.git`||e.startsWith(`.git/`)}function isReservedSyntheticFolderPath(e){return e===`__system__`||e===`__config__`||e===`__user__`||e===`__local__`||e.startsWith(`__system__/`)||e.startsWith(`__config__/`)||e.startsWith(`__user__/`)||e.startsWith(`__local__/`)}function listAffectedDocNames(e,t,s){let g=[...e.keys()].filter(e=>t===`file`?e===s:e===s||e.startsWith(`${s}/`));return g.sort((e,t)=>e.localeCompare(t)),g}function remapDocNameForRename(e,t,s,g){return t===`file`||e===s?g:`${g}${e.slice(s.length)}`}function requireNonEmptyDocName(e,t,s){return e!==void 0&&e.length>0?e:(errorResponse(t,400,`urn:ok:error:invalid-request`,"`docName` must be a non-empty document name.",{handler:s}),null)}function assertNoSymlinkEscape(e,t){let s;try{s=realpathSync(t)}catch(e){throw e.code===`ENOENT`?new SymlinkEscapeError(`content directory does not exist`):e}let g=e;for(;;)try{if(!isWithinContentDir(realpathSync(g),s))throw new SymlinkEscapeError(`path resolves outside content directory`);return}catch(e){let s=e.code;if(s===`ELOOP`)throw new SymlinkEscapeError(`symlink cycle in path`);if(s!==`ENOENT`)throw e;let S=dirname(g);if(S===g||S!==t&&!S.startsWith(`${t}${sep}`))throw e;g=S}}function resolveContentEntryPath(e,t,s){if(!isValidRelativeContentPath(s))throw Error(`path must be a relative content path`);let g=resolve(e),S=resolve(g,t===`file`?isSupportedDocFile(s)?s:`${s}${getDocExtension(s)}`:s);if(S!==g&&!S.startsWith(`${g}${sep}`))throw Error(`path must not escape content directory`);return assertNoSymlinkEscape(S,g),S}function splitContentPath(e){let t=e.lastIndexOf(`/`);return t===-1?{parent:``,basename:e}:{parent:e.slice(0,t),basename:e.slice(t+1)}}function joinContentPath(e,t){return e?`${e}/${t}`:t}function duplicateBasename(e,t){return t===1?`${e} copy`:`${e} copy ${t}`}var DuplicateNameExhaustedError=class extends Error{constructor(e){super(`Could not find an available duplicate name for ${e}`),this.sourcePath=e,this.name=`DuplicateNameExhaustedError`}};function isAlreadyExistsError(e){let t=e.code;return t===`EEXIST`||t===`ERR_FS_CP_EEXIST`}function classifyDuplicatePathFilesystemProblem(e){let t=e.code;return t===`ENOSPC`||t===`EDQUOT`?{status:507,type:`urn:ok:error:storage-full`,title:`Could not duplicate path because storage is full.`}:t===`EPERM`||t===`EACCES`||t===`EROFS`?{status:500,type:`urn:ok:error:storage-readonly`,title:`Could not duplicate path because storage is not writable.`}:null}function docNameExistsWithAnySupportedExtension(e,t){return SUPPORTED_DOC_EXTENSIONS.some(s=>existsSync(resolve(e,`${t}${s}`)))}function resolveDuplicateDocPath(e,t,s){if(!isValidRelativeContentPath(t))throw Error(`path must be a relative content path`);let g=resolve(e),S=resolve(g,`${t}${s}`);if(S!==g&&!S.startsWith(`${g}${sep}`))throw Error(`path must not escape content directory`);return assertNoSymlinkEscape(S,g),S}function nextAvailableDuplicateDocName(e,t){let{parent:s,basename:g}=splitContentPath(t);for(let t=1;t<=1e4;t+=1){let S=joinContentPath(s,duplicateBasename(g,t));if(!docNameExistsWithAnySupportedExtension(e,S))return{docName:S,attempt:t}}throw new DuplicateNameExhaustedError(t)}function nextAvailableDuplicateFolderPath(e,t){let{parent:s,basename:g}=splitContentPath(t);for(let t=1;t<=1e4;t+=1){let S=joinContentPath(s,duplicateBasename(g,t));if(!existsSync(resolveContentEntryPath(e,`folder`,S)))return{folderPath:S,attempt:t}}throw new DuplicateNameExhaustedError(t)}function collectMarkdownCopies(e,t){let s=resolveContentEntryPath(e,`folder`,t),g=[];function S(e,t){for(let s of readdirSync(e,{withFileTypes:!0})){let w=resolve(e,s.name),E=t?`${t}/${s.name}`:s.name;if(s.isDirectory()){S(w,E);continue}!s.isFile()||!isSupportedDocFile(E)||g.push({docName:stripDocExtension(E),fullPath:w,content:readFileSync(w,`utf-8`)})}}return S(s,t),g.sort((e,t)=>e.docName.localeCompare(t.docName)),g}function collectFolderPaths(e,t){let s=resolveContentEntryPath(e,`folder`,t),g=[t];function S(e,t){for(let s of readdirSync(e,{withFileTypes:!0})){if(!s.isDirectory())continue;let w=resolve(e,s.name),E=t?`${t}/${s.name}`:s.name;g.push(E),S(w,E)}}return S(s,t),g.sort((e,t)=>e.localeCompare(t)),g}function probeAndRegisterSourceFileExtension(e,t){if(!isValidRelativeContentPath(t))return;let s=resolve(e);if(isSupportedDocFile(t)){let e=resolve(s,t);e!==s&&e.startsWith(`${s}${sep}`)&&existsSync(e)&&registerDocExtension(stripDocExtension(t),extname(t));return}for(let e of SUPPORTED_DOC_EXTENSIONS){let g=resolve(s,`${t}${e}`);if(!(g!==s&&!g.startsWith(`${s}${sep}`))&&existsSync(g)){registerDocExtension(t,e);return}}}function toGitRelativePath(e,t){let s=resolve(e),g=resolve(t);return g!==s&&!g.startsWith(`${s}${sep}`)?null:relative(s,g).split(sep).join(`/`)}function stringsDifferOnlyByCase(e,t){return e!==t&&e.toLowerCase()===t.toLowerCase()}function pathsDifferOnlyByCase(e,t){return stringsDifferOnlyByCase(resolve(e),resolve(t))}function isCaseOnlySelfCollision(e,t){if(!pathsDifferOnlyByCase(e,t)||!existsSync(e)||!existsSync(t))return!1;try{let s=statSync(e),g=statSync(t);return s.dev===g.dev&&s.ino===g.ino}catch{return!1}}function createCaseOnlyRenameTempPath(e){let t=dirname(e);for(let e=0;e<10;e+=1){let e=resolve(t,`.ok-case-rename-${randomUUID$1()}`);if(!existsSync(e))return e}throw Error(`Unable to allocate temporary path for case-only rename`)}function writeFileIfContentDiffers(e,t){(existsSync(e)?readFileSync(e,`utf-8`):null)!==t&&tracedWriteFileSync(e,t,`utf-8`)}function renamePathOnDisk(e,t){if(tracedMkdirSync(dirname(t),{recursive:!0}),!pathsDifferOnlyByCase(e,t)){tracedRenameSync(e,t);return}let s=createCaseOnlyRenameTempPath(e);tracedRenameSync(e,s);try{tracedRenameSync(s,t)}catch(t){try{let t=existsSync(s),g=existsSync(e);t&&!g?tracedRenameSync(s,e):console.warn(`[renamePathOnDisk] skipped case-only rollback due to unexpected state:`,{tempExists:t,sourceExists:g})}catch(e){console.warn(`[renamePathOnDisk] failed to roll back temporary case-only rename:`,e)}throw t}}async function renameTrackedPathInGit(e,t,s){if(!e)return!1;let g=toGitRelativePath(e,t),S=toGitRelativePath(e,s);return!g||!S?!1:await withParentLock(async()=>{let w=esm_default({baseDir:e,timeout:{block:15e3}}),E=``;try{E=(await w.raw(`ls-files`,`--`,g)).trim()}catch(e){return console.warn(`[renameTrackedPathInGit] git ls-files failed, falling back to fs rename:`,e),!1}if(!E)return!1;mkdirSync(dirname(s),{recursive:!0});let D=!1;try{if(pathsDifferOnlyByCase(t,s)){let s=toGitRelativePath(e,createCaseOnlyRenameTempPath(t));if(!s)return!1;await w.raw(`mv`,`--`,g,s);try{await w.raw(`mv`,`--`,s,S)}catch(e){try{await w.raw(`mv`,`--`,s,g)}catch(e){console.warn(`[renameTrackedPathInGit] case-only git rename failed and rollback also failed; git index and disk may have diverged:`,e),D=!0}throw e}}else await w.raw(`mv`,`--`,g,S);return!0}catch(e){if(D)throw e;return console.warn(`[renameTrackedPathInGit] git mv failed, falling back to fs rename:`,e),!1}})}const workspaceSearchCaches=new Map;function extractHeadings(e){let{body:t}=stripFrontmatter(e),s=[],g=new Map,S=createCodeFenceTracker();for(let e of t.split(`
1933
1937
  `)){if(S(e))continue;let t=e.match(/^(#{1,6})\s+(.+)$/);if(t){let e=t[2].trim(),S=getHeadingSlug(e,g);S&&s.push({level:t[1].length,text:e,slug:S})}}return s}function isSafeDocName(e){return!(e.includes(`..`)||e.startsWith(`/`)||e.includes(`\0`)||e.includes(`\\`))}function applyDiskEventToLiveAllFilesIndex(e,t){let s=t();s instanceof Map&&updateFileIndex(e,s)}function createApiExtension(e){let{hocuspocus:t,sessionManager:s,contentDir:g,serverInstanceId:S,getFileIndex:w,getAllFilesIndex:E=w,mutateFileIndex:D=e=>applyDiskEventToLiveAllFilesIndex(e,E),getFileIndexGeneration:O,getFolderIndex:k,onReferencedAssetsCacheInvalidator:j,getAliasMap:F,getFolderAliasIndex:L,rescanFiles:B,enableTestRoutes:H=!1,shadowRef:q,flushGitCommit:ee,flushContributors:J,takeStoreFailure:Y,takeStoreDivergence:te,markAgentWriteStore:ne,getCurrentBranch:ae,getDiskAckSVs:oe,contentRoot:se,backlinkIndex:ce,tagIndex:ue,signalChannel:de,agentFocusBroadcaster:fe,agentPresenceBroadcaster:me,onAgentWrite:ge,getSyncEngine:_e,localOpCliArgs:ve=[`open-knowledge`],projectDir:ye,getPrincipal:Ce,homeDirOverride:we,contentFilter:Te,installedAgentsProbe:De,forceUnloadDocument:je,ready:Me,recentlyRemovedDocs:Pe,serializeDoc:Ie,evictManagedArtifactLkg:Re,semanticSearch:ze,getSemanticSimilarityFloor:Be,embeddingsSecretsFile:Ve,ephemeral:Ue=!1}=e,We=createConcurrencyGuard(),Ge=new Map,Ke=createSingleFlight(),Xe=null;function $e(){let e=k?.();return e instanceof Map?e:null}function nt(e){let t=$e();if(t)try{upsertFolderIndexEntry(t,g,e,statSync(e),e)}catch(t){console.warn(`[api-extension] folder index stat failed for ${e}:`,t)}}function rt(e){let t=e.split(`/`).filter(Boolean);for(let e=1;e<=t.length;e+=1)nt(resolve(g,t.slice(0,e).join(`/`)))}function it(e){let t=$e();t&&removeFolderIndexEntries(t,e)}function at(e,t){let s=$e();if(!s)return;let S=[];for(let[g,w]of s.entries()){if(g!==e&&!g.startsWith(`${e}/`))continue;s.delete(g);let E=g.slice(e.length);S.push([`${t}${E}`,w])}if(S.length===0){let e=resolveContentEntryPath(g,`folder`,t);existsSync(e)&&nt(e);return}for(let[e,t]of S)s.set(e,{...t,modified:new Date().toISOString(),canonicalPath:resolve(g,e)})}function st(e){return[...e.entries()].map(([e,t])=>`${e}\0${t.canonicalPath}\0${t.size}\0${t.modified}\0${t.aliases.join(`\0`)}`).sort().join(`
1934
- `)}function vt(){Xe=null}j?.(vt);let Tt=createInstalledAgentsProbe({probe:De??createOsProbe(process.platform)});function Et(e){if(isManagedArtifactDocName(e))try{return managedArtifactAbsPath(e,{projectDir:ye??g,homedirOverride:we})}catch{return null}if(!isSafeDocName(e))return null;let t=resolve(g),s=resolve(t,`${e}${getDocExtension(e)}`);return isWithinDir(s,t)?s:null}function Dt(e){let t=Et(e);if(!t||!existsSync(t))return e;try{return extractPageTitle(readFileSync(t,`utf-8`),e)}catch{return e}}function jt(e,t){return t.has(e)?Dt(e):e}let Mt={cluster:void 0,category:void 0,tags:void 0};function Ft(e){try{let s=t.documents.get(e);if(s){let e=readFmMap(s.getText(`source`).toString());if(Object.keys(e).length>0){let t=typeof e.cluster==`string`?e.cluster:void 0,s=typeof e.category==`string`?e.category:void 0,g;if(Array.isArray(e.tags)){let t=e.tags.filter(e=>typeof e==`string`);g=t.length>0?t:void 0}else typeof e.tags==`string`&&e.tags&&(g=[e.tags]);return{cluster:t,category:s,tags:g}}}}catch{}try{let t=Et(e);if(!t||!existsSync(t))return Mt;let{frontmatter:s}=stripFrontmatter(readFileSync(t,`utf-8`));return s?parseFrontmatterMetadata(s):Mt}catch{return Mt}}function It(e,t){return t.has(e)?Ft(e):Mt}function Lt(e){if(ce)try{if(ce.getBacklinks(e).length>0)return;let t=performance.now(),s=findHubCandidates(e,w()),g=performance.now()-t;return g>5&&log$6.debug({docName:e,elapsedMs:g,candidateCount:s.length},`[orphan-hint] findHubCandidates slow`),s.length===0?void 0:[{type:`orphan`,parentCandidates:s,message:`This doc has no backlinks yet. To make it discoverable, consider linking from a parent hub doc (index/overview files in the folder tree): ${s.map(e=>`[[${e}]]`).join(`, `)}.`}]}catch(e){console.warn(`[orphan-hint] computeOrphanHints failed:`,e);return}}function Rt(e){return F?.().get(e)??e}function zt(e){try{return t.documents.get(e)?.connections.size??0}catch{return 0}}function Bt(){try{return t.documents.get(`__system__`)?.connections.size??0}catch{return 0}}function Vt(e,s){let g=`onStoreDocument-${e}`;(t.debouncer.isDebounced(g)?t.debouncer.executeNow(g):Promise.resolve()).then(()=>ee?.()).catch(e=>{log$6.warn({err:e},`[${s}] post-write flush failed`)})}async function Ht(e){let s=`onStoreDocument-${e}`;t.debouncer.isDebounced(s)&&(ne?.(e),await t.debouncer.executeNow(s));let g=Y?.(e)??null;return g?{kind:`failure`,failure:g}:te?.(e)?{kind:`divergence`}:null}function Ut(e,t,s){let g=classifyUploadErrno({code:t.code});errorResponse(e,uploadStatusFor(g),g,`Write applied in memory but failed to persist to disk (${t.code??`unknown error`}): ${t.message}. The content was NOT saved and will be lost if the server restarts.`,{handler:s})}function Wt(e,t){errorResponse(e,409,`urn:ok:error:disk-divergence`,`The document changed on disk after your edit was prepared; your edit was NOT applied, to avoid overwriting the newer on-disk content. Re-read the document and retry.`,{handler:t})}function Kt(e){if(e.reconciled)return{kind:`disk-edit-reconciled`,intendedBytes:e.baseBytes,actualBytes:e.diskBytes,byteDelta:e.diskBytes-e.baseBytes,...e.mergeOutcome?{mergeOutcome:e.mergeOutcome}:{},hint:e.mergeOutcome===`merged`?'An out-of-band edit was three-way merged into this document before your edit was applied on top; the merge may have interleaved content blocks. Re-read it (e.g. `exec("cat <path>")`) and review the combined result carefully before continuing.':'An out-of-band edit was reconciled into this document before your edit was applied on top; the document now reflects that edit plus yours. Re-read it (e.g. `exec("cat <path>")`) to see the combined result before continuing.'}}function $t(){let e=new Set;for(let[t,s]of w()){e.add(t);for(let t of s.aliases)e.add(t)}try{for(let t of[`project`,`global`]){let s=resolve(t===`global`?Ql:g,`.ok`,`skills`);for(let g of au(s,t).skills)e.add(`${MANAGED_ARTIFACT_PREFIX_SKILL}${t}/${g.name}`)}for(let t of resolveProjectTemplates(resolve(g)).templates)e.add(eu(t.source_folder,t.name))}catch(e){log$6.warn({err:e},`[collectAdmittedDocNames] managed-artifact enumeration failed`)}return e}function en(){let e=Promise.resolve();return async function(t){let s=e,g=()=>{};e=new Promise(e=>{g=e}),await s;try{return await t()}finally{g()}}}let jr=en(),Mr=e=>e.endsWith(`.`)?e:`${e}.`;function Fr(e){return e instanceof Error?e instanceof ManagedRenameSourceNotFoundError?{status:404,type:`urn:ok:error:doc-not-found`,error:Mr(e.message)}:e instanceof ManagedRenameDestinationExistsError?{status:409,type:`urn:ok:error:doc-already-exists`,error:Mr(e.message)}:e instanceof ManagedRenameSourceTypeMismatchError||e instanceof ManagedRenameInvalidRequestError?{status:400,type:`urn:ok:error:invalid-request`,error:Mr(e.message)}:e instanceof ManagedRenameReservedPathError?{status:400,type:`urn:ok:error:reserved-doc-name`,error:Mr(e.message)}:e instanceof ManagedRenameMissingDocumentError||e instanceof ManagedRenameSnapshotMissingError?{status:404,type:`urn:ok:error:doc-not-found`,error:Mr(e.message)}:e instanceof SymlinkEscapeError?{status:400,type:`urn:ok:error:path-escape`,error:Mr(e.message)}:e instanceof BacklinkIndexRequiredError?{status:503,type:`urn:ok:error:backlink-index-not-configured`,error:Mr(e.message)}:{status:500,type:`urn:ok:error:internal-server-error`,error:`Failed to rename document.`}:{status:500,type:`urn:ok:error:internal-server-error`,error:`Failed to rename document.`}}async function Ir(e){let g=new Map;for(let s of e){let e=t.documents.get(s);e&&g.set(s,e.getText(`source`).toString())}for(let t of e)await s.closeAllForDoc(t).catch(e=>{console.warn(`[file-ops] Failed to close agent session for ${t}:`,e)});for(let s of e){let e=t.documents.get(s);deleteReconciledBase(s),Re?.(s),e&&(t.closeConnections(s),await(je??t.unloadDocument.bind(t))(e))}return g}function Lr(e,t){for(let{fromDocName:s,toDocName:S}of e){let e=safeContentPath(S,g),w=t.get(s);typeof w==`string`&&writeFileIfContentDiffers(e,w);let E=typeof w==`string`?w:existsSync(e)?readFileSync(e,`utf-8`):null;typeof E==`string`&&registerWrite(e,contentHash(E))}}function zr(e,t){return e.map(e=>{let s=t.get(e);if(typeof s==`string`)return{docName:e,content:s};let S=safeContentPath(e,g);if(!existsSync(S))throw new ManagedRenameSnapshotMissingError(e);return{docName:e,content:readFileSync(S,`utf-8`)}})}function Br(e){let s=t.documents.get(e);if(s)return s.getText(`source`).toString();let S=resolveContentEntryPath(g,`file`,e);return existsSync(S)?readFileSync(S,`utf-8`):null}function Vr(e,t){let s=resolveContentEntryPath(g,`file`,e);tracedMkdirSync(dirname(s),{recursive:!0}),writeFileIfContentDiffers(s,t),registerWrite(s,contentHash(t)),setReconciledBase(e,t),D?.({kind:`update`,path:s,docName:e,content:t})}function Hr(e,s,g=[]){let S=t.documents.get(e);if(!S)throw Error(`Document is not loaded: ${e}`);let w={markdown:``,rewrites:0};return S.transact(()=>{w=Wr(S.getText(`source`).toString(),e,s.get(e)??e,s,g),w.rewrites!==0&&composeAndWriteRawBody(S,w.markdown,`managed-rename`,!1)},MANAGED_RENAME_ORIGIN),w}function Ur(e,t,s){let g=e,S=0;for(let{fromPath:e,toPath:w}of s){let s=rewriteAssetReferencesForRename(g,t,e,w);g=s.markdown,S+=s.rewrites}return{markdown:g,rewrites:S}}function Wr(e,t,s,g,S){let w=applyRenameMap(e,t,g),E=Ur(w.markdown,s,S);return{markdown:E.markdown,rewrites:E.markdown===e?0:w.rewrites+E.rewrites}}function Gr(e,s){let g=t.documents.get(e);if(!g)throw Error(`Document is not loaded: ${e}`);let S={markdown:``,rewrites:0};return g.transact(()=>{S=Ur(g.getText(`source`).toString(),e,s),S.rewrites!==0&&composeAndWriteRawBody(g,S.markdown,`managed-rename`,!1)},MANAGED_RENAME_ORIGIN),S}function Kr(e){let t=[];if(e.length===0)return t;let s=[...w().keys()].sort((e,t)=>e.localeCompare(t));for(let g of s){let s=Br(g);if(typeof s!=`string`)continue;let S=Ur(s,g,e);S.rewrites!==0&&t.push({docName:g,markdown:S.markdown,rewrites:S.rewrites})}return t}function qr(e){let s=_e?.(),g=new Set(s?s.getConflicts().map(e=>e.file):[]);for(let s of e){let e=t.documents.get(s),S=`${s}${getDocExtension(s)}`,w=e!==void 0&&isDocInConflict(e),E=g.has(S);if(w||E)throw new DocInConflictError({file:S})}}function Jr(e,s){let g=[];for(let S of e){let e=t.documents.get(S.docName)?Gr(S.docName,s):S;e.rewrites!==0&&(Vr(S.docName,e.markdown),ce?.updateDocumentFromMarkdown(S.docName,e.markdown),g.push({docName:S.docName,rewrites:e.rewrites}))}return g}function Yr(e){if(extname(e))return{path:e,ambiguous:!1};let t=e.lastIndexOf(`/`),s=t===-1?``:e.slice(0,t),S=t===-1?e:e.slice(t+1),w=s?resolveContentEntryPath(g,`folder`,s):g,E;try{E=readdirSync(w,{withFileTypes:!0})}catch(t){let s=t.code;if(s===`ENOENT`||s===`ENOTDIR`)return{path:e,ambiguous:!1};throw t}let D=E.filter(e=>e.isFile()&&e.name.startsWith(`${S}.`)).map(e=>s?`${s}/${e.name}`:e.name).filter(e=>isSupportedAssetFile(e,LINKABLE_ASSET_EXTENSIONS));return D.length===1?{path:D[0],ambiguous:!1}:{path:e,ambiguous:D.length>1}}function Xr(e){let t=[];try{if(!statSync(e).isDirectory())return t}catch(e){let s=e.code;if(s===`ENOENT`||s===`ENOTDIR`)return t;throw e}function s(e){for(let S of readdirSync(e,{withFileTypes:!0})){let w=resolve(e,S.name),E=relative(g,w).split(sep).join(`/`);if(isReservedProjectStatePath(E))continue;if(S.isDirectory()){if(Te?.isDirExcluded(E))continue;s(w);continue}if(!S.isFile()||!isSupportedDocFile(E)||Te?.isExcluded(E))continue;let D=stripDocExtension(E);registerDocExtension(D,extname(E)),t.push(D)}}return s(e),t.sort((e,t)=>e.localeCompare(t)),t}function Zr(e,t,s){let S=[];function w(e){for(let E of readdirSync(e,{withFileTypes:!0})){let D=resolve(e,E.name),O=relative(g,D).split(sep).join(`/`);if(!isReservedProjectStatePath(O)){if(E.isDirectory()){if(Te?.isDirExcluded(O))continue;w(D);continue}!E.isFile()||isSupportedDocFile(O)||Te?.isExcluded(O)||(O===t?S.push({fromPath:O,toPath:s}):O.startsWith(`${t}/`)&&S.push({fromPath:O,toPath:`${s}${O.slice(t.length)}`}))}}}return w(e),S.sort((e,t)=>e.fromPath.localeCompare(t.fromPath)),S}async function Qr(e,t){return jr(async()=>withSpan(`rename.executeAssetRewrites`,{attributes:{"rename.kind":`asset`}},async s=>{if(!ce)throw new BacklinkIndexRequiredError;let S=extname(t)?t:`${t}${extname(e)}`;if(isReservedProjectStatePath(e)||isReservedProjectStatePath(S))throw new ManagedRenameReservedPathError(`.ok and .git are reserved directories.`);if(Te?.isPathIgnored(S))throw new ManagedRenameInvalidRequestError(`Destination asset is excluded by the project content config.`);let w=resolveContentEntryPath(g,`folder`,e),E=resolveContentEntryPath(g,`folder`,S);if(w===E)return{renamedAssets:[],rewrittenDocs:[]};if(stringsDifferOnlyByCase(e,S))throw new ManagedRenameInvalidRequestError(`Case-only renames are not supported.`);if(!existsSync(w))throw new ManagedRenameSourceNotFoundError(`asset`,`Asset does not exist.`);if(existsSync(E))throw new ManagedRenameDestinationExistsError;if(!statSync(w).isFile())throw new ManagedRenameSourceTypeMismatchError(`asset`,`Source path is not an asset file.`);let D=[{fromPath:e,toPath:S}],O=Kr(D);s.setAttribute(`rename.rewrite_candidates`,O.length),qr(O.map(e=>e.docName)),await renameTrackedPathInGit(ye,w,E)||renamePathOnDisk(w,E);let k=Jr(O,D);return ce.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist asset rename cache for ${e} -> ${S}:`,t)}),de?.(`files`),k.length>0&&(de?.(`backlinks`),de?.(`graph`)),k.sort((e,t)=>e.docName.localeCompare(t.docName)),s.setAttribute(`rename.rewrite_count`,k.length),{renamedAssets:D,rewrittenDocs:k}}))}async function ji(e,s){return jr(async()=>withSpan(`rename.executeDocumentToFileRewrites`,{attributes:{"rename.kind":`asset`,"rename.transition":`document-to-file`}},async S=>{if(!ce)throw new BacklinkIndexRequiredError;if(!isSupportedDocFile(e)||isSupportedDocFile(s))throw new ManagedRenameInvalidRequestError(`Document-to-file rename requires a markdown source and non-markdown destination.`);let w=stripDocExtension(e);if(isSystemDoc(w)||isConfigDoc(w))throw new ManagedRenameReservedPathError(`Reserved document names cannot be renamed.`);if(isReservedProjectStatePath(e)||isReservedProjectStatePath(s))throw new ManagedRenameReservedPathError(`.ok and .git are reserved directories.`);if(Te?.isPathIgnored(s))throw new ManagedRenameInvalidRequestError(`Destination file is excluded by the project content config.`);let E=resolveContentEntryPath(g,`folder`,e),O=resolveContentEntryPath(g,`folder`,s);if(E===O)return{renamedAssets:[],rewrittenDocs:[]};if(stringsDifferOnlyByCase(e,s))throw new ManagedRenameInvalidRequestError(`Case-only renames are not supported.`);if(!existsSync(E))throw new ManagedRenameSourceNotFoundError(`file`);if(existsSync(O))throw new ManagedRenameDestinationExistsError;if(!statSync(E).isFile())throw new ManagedRenameSourceTypeMismatchError(`file`,`Source path is not a document file.`);let k=_e?.(),j=new Set(k?k.getConflicts().map(e=>e.file):[]),F=t.documents.get(w);if(F!==void 0&&isDocInConflict(F)||j.has(e))throw new DocInConflictError({file:e});let L=[{fromPath:e,toPath:s}],B=Kr(L).filter(e=>e.docName!==w);S.setAttribute(`rename.rewrite_candidates`,B.length),qr(B.map(e=>e.docName)),reconcileDiskBeforeAgentWrite(t,w,g),Pe&&!isSystemDoc(w)&&!isConfigDoc(w)&&Pe.setDeleted(w);let H=(await Ir([w])).get(w),q=typeof H==`string`?H:readFileSync(E,`utf-8`),ee=createManagedRenameRecoveryJournal({fromPath:e,toPath:s,affectedDocs:[{from:w,to:w}],snapshots:[{docName:w,content:q}],cleanupPaths:[s]}),J=[];return await withManagedRenameRecovery(ye??g,ee,async()=>{writeFileIfContentDiffers(E,q),registerWrite(E,contentHash(q)),await renameTrackedPathInGit(ye,E,O)||renamePathOnDisk(E,O),ce.deleteDocument(w),forgetDocExtension(w),D?.({kind:`delete`,path:E,docName:w});let t=statSync(O);D?.({kind:`file-create`,path:O,relativePath:s,size:t.size,modifiedTs:t.mtimeMs,inode:t.ino}),J=Jr(B,L),ce.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist document-to-file rename cache for ${e} -> ${s}:`,t)}),de?.(`files`),J.length>0&&(de?.(`backlinks`),de?.(`graph`))}),J.sort((e,t)=>e.docName.localeCompare(t.docName)),S.setAttribute(`rename.rewrite_count`,J.length),{renamedAssets:L,rewrittenDocs:J}}))}async function Hi(e,s,S,E){return jr(async()=>withSpan(`rename.executeRewrites`,{attributes:{"rename.kind":S}},async O=>{if(!ce)throw new BacklinkIndexRequiredError;let k=resolveContentEntryPath(g,S,e),j=resolveContentEntryPath(g,S,s);if(k===j)return{renamed:[],renamedAssets:[],rewrittenDocs:[]};if(!existsSync(k))throw new ManagedRenameSourceNotFoundError(S);if(existsSync(j)&&!isCaseOnlySelfCollision(k,j))throw new ManagedRenameDestinationExistsError;let F=statSync(k);if(S===`file`&&!F.isFile()||S===`folder`&&!F.isDirectory())throw new ManagedRenameSourceTypeMismatchError(S);let L=S===`folder`?Zr(k,e,s):[];O.setAttribute(`rename.affected_assets`,L.length);let B=(S===`file`?[stripDocExtension(e)]:Xr(k)).map(t=>({from:t,to:S===`file`?stripDocExtension(s):remapDocNameForRename(t,S,e,s)}));if(O.setAttribute(`rename.affected_docs`,B.length),B.length===0){let t=Kr(L);qr(t.map(e=>e.docName));let g=[];return S===`folder`&&(await renameTrackedPathInGit(ye,k,j)||renamePathOnDisk(k,j),at(e,s),de?.(`files`)),g.push(...Jr(t,L)),g.length>0&&(ce.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist managed rename cache for ${e} -> ${s}:`,t)}),de?.(`backlinks`),de?.(`graph`)),g.sort((e,t)=>e.docName.localeCompare(t.docName)),{renamed:[],renamedAssets:L,rewrittenDocs:g}}let H=buildRenameMap(B),ee=B.map(({from:e,to:t})=>({fromDocName:e,toDocName:t})),J=new Set;for(let{from:e}of B)for(let t of ce.getBacklinks(e))H.has(t.source)||J.add(t.source);let Y=[...J].sort((e,t)=>e.localeCompare(t)),te=new Map,ne=new Set,oe=new Set,se=[];for(let e of[...H.keys(),...Y]){if(te.has(e))continue;if(!H.has(e)&&!existsSync(resolveContentEntryPath(g,`file`,e))){se.push(e);continue}reconcileDiskBeforeAgentWrite(t,e,g);let s=Br(e);typeof s==`string`?(te.set(e,s),H.has(e)||ne.add(e)):H.has(e)||se.push(e)}if(L.length>0){let e=[...w().keys()].sort((e,t)=>e.localeCompare(t));for(let t of e){let e=te.get(t)??Br(t);typeof e==`string`&&Wr(e,t,H.get(t)??t,H,L).rewrites!==0&&(te.has(t)||te.set(t,e),oe.add(t),H.has(t)||ne.add(t))}}qr(oe);for(let{from:e}of B)if(typeof te.get(e)!=`string`)throw new ManagedRenameMissingDocumentError(e);let ue=createManagedRenameRecoveryJournal({fromPath:e,toPath:s,affectedDocs:[...B],snapshots:zr([...te.keys()],te)}),fe=[],me=[...ne].sort((e,t)=>e.localeCompare(t));return await withManagedRenameRecovery(ye??g,ue,async()=>{for(let e of se)ce.deleteDocument(e);for(let e of me){let s=t.documents.get(e)?Hr(e,H,L):Wr(te.get(e)??``,e,e,H,L);s.rewrites>0&&(Vr(e,s.markdown),fe.push({docName:e,rewrites:s.rewrites})),ce.updateDocumentFromMarkdown(e,s.markdown)}if(Pe)for(let{from:e,to:t}of B)isSystemDoc(e)||isConfigDoc(e)||(Pe.setRenamed(e,t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,from:e,to:t,kind:`renamed`,source:`spine`})));let w=resolveContentEntryPath(g,S,e),O=resolveContentEntryPath(g,S,s);await renameTrackedPathInGit(ye,w,O)||renamePathOnDisk(w,O),S===`folder`&&at(e,s);let k=await Ir([...H.keys()]);if(process.env.NODE_ENV===`test`&&process.env.OK_TEST_RENAME_FAULT===`pre-append`)throw Error(`OK_TEST_RENAME_FAULT=pre-append`);if(q?.current){let e=q.current,t=B.filter(({from:e,to:t})=>e!==t);t.length>0&&withSpanSync(`rename.appendLog`,{attributes:{"rename.kind":S}},s=>{let g=randomUUID$1(),w=new Date().toISOString(),D=ae?.()??`main`,O=getOrLoadRenameLogIndex(e.gitDir),k=E?.actor?{writerId:E.actor.writerId,displayName:E.actor.displayName}:{writerId:SERVICE_WRITER.id,displayName:SERVICE_WRITER.name},j=0;for(let{from:s,to:F}of t){let t={v:1,from:s,to:F,at:w,commitSha:``,branch:D,groupId:g,kind:S,actor:k};appendRenameLogEntry(e.gitDir,t,O,e),j+=1,E?.actor?recordContributor(F,E.actor.writerId,E.actor.displayName,E.actor.colorSeed,formatRenameSubject(s,F),E.actor.actorMetadata,void 0,[{from:s,to:F}]):recordContributor(F,SERVICE_WRITER.id,SERVICE_WRITER.name,SERVICE_WRITER.id,formatRenameSubject(s,F),void 0,void 0,[{from:s,to:F}])}s.setAttribute(`rename.entries_appended`,j)})}let j=S===`file`&&isSupportedDocFile(s)?extname(s):null;for(let{from:e,to:t}of B){let s=getDocExtension(e);forgetDocExtension(e),registerDocExtension(t,j??s)}let F=[...B].sort((e,t)=>e.from.localeCompare(t.from));for(let{from:e,to:t}of F){let s=resolveContentEntryPath(g,`file`,e),S=resolveContentEntryPath(g,`file`,t),w=Wr(k.get(e)??te.get(e)??readFileSync(S,`utf-8`),e,t,H,L);Lr([{fromDocName:e,toDocName:t}],new Map([[e,w.markdown]])),setReconciledBase(t,w.markdown),D?.({kind:`rename`,oldPath:s,newPath:S,oldDocName:e,newDocName:t,content:w.markdown}),ce.renameDocument(e,t,w.markdown),w.rewrites>0&&fe.push({docName:t,rewrites:w.rewrites})}if(process.env.NODE_ENV===`test`&&process.env.OK_TEST_RENAME_FAULT===`pre-journal-clear`)throw Error(`OK_TEST_RENAME_FAULT=pre-journal-clear`)}),ce.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist managed rename cache for ${e} -> ${s}:`,t)}),de?.(`files`),de?.(`backlinks`),de?.(`graph`),fe.sort((e,t)=>e.docName.localeCompare(t.docName)),O.setAttribute(`rename.rewrite_count`,fe.length),{renamed:ee,renamedAssets:L,rewrittenDocs:fe}}))}function Ui(e){let t=parseAgentBodyFields(e),s=t.writerId??`claude-1`;return{rawAgentId:t.rawAgentId,agentId:s,agentName:t.displayName,colorSeed:t.colorSeed??t.rawAgentId??s,clientName:t.clientName,clientVersion:t.clientVersion,label:t.label}}function Gi(e){return{principalId:Ce?.()?.id,agentType:resolveAgentType(e.clientName),clientName:e.clientName,clientVersion:e.clientVersion,label:e.label}}function Ki(e){return e.kind===`value`?e.truncatedFrom===void 0?{response:{value:e.value},stored:e.value}:{response:{value:e.value,truncatedFrom:e.truncatedFrom,hint:`Summary truncated from ${e.truncatedFrom} chars to 80 (max 80).`},stored:e.value}:{stored:void 0}}function Yi(e){return{value:e.value}}function Xi(e,t=!1){e.kind===`value`&&(incrementSummariesProvided(),e.truncatedFrom!==void 0&&!t&&incrementSummariesTruncated())}function Zi(e,t,s,g){if(s.length!==0)switch(e.kind){case`agent`:{let g=e.summary.kind===`value`,S=g?e.summary:normalizeSummary(t),w=Ki(S),E=g||!w.response?w.response:Yi(w.response);for(let t=0;t<s.length;t++){let{docName:g,subject:S}=s[t];recordContributor(g,e.writerId,e.displayName,e.colorSeed,S,e.actor,t===0?w.stored:void 0)}incrementAgentWriteCalls(),Xi(S,!g);for(let{docName:e}of s)Vt(e,`rename-path`);return E}case`principal`:{let t=Ki(e.summary);for(let g=0;g<s.length;g++){let{docName:S,subject:w}=s[g];recordContributor(S,e.writerId,e.displayName,e.colorSeed,w,e.actor,g===0?t.stored:void 0)}Xi(e.summary,!1);for(let{docName:e}of s)Vt(e,`rename-path`);return t.response}case`anonymous`:g.onAnonymous?.();return;default:{let t=e;throw Error(`Unhandled actor kind in ${g.context}: ${String(t.kind)}`)}}}function ka(e,t,s){let g=t.replace(/\/$/,``),S=g===``?``:`${g}/`;return e===`template`?`${S}.ok/templates/${s}`:e===`skill`?`${S}.ok/skills/${s}`:e===`folder-frontmatter`?`${S}.ok/frontmatter`:g===``?`.`:g}function _s(e,t,s,g){if(e.kind!==`agent`&&e.kind!==`principal`)return;let S=Ki(e.summary);recordContributor(t,e.writerId,e.displayName,e.colorSeed,s,e.actor,S.stored,g)}async function xs(e){if(J)try{await J()}catch(t){console.warn(`[${e}] flushContributors failed; attribution stays queued for the next flush:`,t)}}let Cs=withValidation(AgentWriteRequestSchema,async(S,w,E)=>{try{let S=requireNonEmptyDocName(E.docName,w,`agent-write`);if(S===null)return;let D=Rt(S),{agentId:O,agentName:k,colorSeed:j,clientName:F,clientVersion:L,label:B}=Ui(E);if(isSystemDoc(D)||isConfigDoc(D)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${D}' is a reserved document name.`,{handler:`agent-write`});return}let H=normalizeSummary(E.summary),q=await s.getSession(D,O,{displayName:k,colorSeed:j,clientName:F}),ee=reconcileDiskBeforeAgentWrite(t,D,g,e.resolveEmbed),J=new Date().toISOString(),Y=typeof E.content==`string`?E.content:`Hello from the agent! ${J}`,{response:te,stored:ne}=Ki(H);try{let t=iconFromClientName(F),s=AGENT_ICON_COLORS[t]??colorFromSeed(j??O);me?.setPresence(O,{displayName:k,icon:t,color:s,currentDoc:D,mode:`writing`,ts:Date.now()}),captureEffect(q.dc.document.getText(`source`),O,j,F),q.dc.document.transact(()=>{applyAgentMarkdownWrite(q.dc.document,`${Y}\n`,`append`,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:D}:void 0),q.dc.document.getMap(`agent-flash`).set(O,{agentId:O,timestamp:Date.now(),type:`insert`,description:`Added (${k}): ${Y.slice(0,50)}`})},q.origin),recordContributor(D,O,k,j,void 0,Gi({clientName:F,clientVersion:L,label:B}),ne),incrementAgentWriteCalls(),Xi(H)}finally{me?.touchMode(O,`idle`)}let ae=await Ht(D);if(ae?.kind===`failure`){Ut(w,ae.failure,`agent-write`);return}if(ae?.kind===`divergence`){Wt(w,`agent-write`);return}Vt(D,`agent-write`),ge?.();let oe=Kt(ee);successResponse(w,200,AgentWriteSuccessSchema,{timestamp:J,...te?{summary:te}:{},...oe?{warning:oe,warnings:[oe]}:{}},{handler:`agent-write`})}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(w,e,`agent-write`);return}if(e instanceof FrontmatterMalformedError){respondFrontmatterMalformed(w,e,`agent-write`);return}if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-write`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$6.error({err:e},`[agent-write] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-write`,cause:e})}},{handler:`agent-write`,method:`POST`}),Ts=withValidation(AgentWriteMdRequestSchema,async(S,w,E)=>{try{let S=E.position??`append`,D=requireNonEmptyDocName(E.docName,w,`agent-write-md`);if(D===null)return;let O=Rt(D),{agentId:k,agentName:j,colorSeed:F,clientName:L,clientVersion:B,label:H}=Ui(E);if(isSystemDoc(O)||isConfigDoc(O)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${O}' is a reserved document name.`,{handler:`agent-write-md`});return}E.extension!==void 0&&!docNameExistsWithAnySupportedExtension(g,O)&&registerDocExtension(O,E.extension);let q=normalizeSummary(E.summary),{response:ee,stored:J}=Ki(q),Y=await s.getSession(O,k,{displayName:j,colorSeed:F,clientName:L}),te=reconcileDiskBeforeAgentWrite(t,O,g,e.resolveEmbed),ne=new Date().toISOString(),ae;try{let t=iconFromClientName(L),s=AGENT_ICON_COLORS[t]??colorFromSeed(F??k);me?.setPresence(k,{displayName:j,icon:t,color:s,currentDoc:O,mode:`writing`,ts:Date.now()}),captureEffect(Y.dc.document.getText(`source`),k,F,L),Y.dc.document.transact(()=>{ae=applyAgentMarkdownWrite(Y.dc.document,E.markdown,S,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:O}:void 0),Y.dc.document.getMap(`agent-flash`).set(k,{agentId:k,timestamp:Date.now(),type:`insert`,description:`Added (${j}): ${E.markdown.trim().slice(0,50)}`})},Y.origin),ae!==void 0&&console.warn(JSON.stringify({event:`agent-write-content-divergence`,"doc.name":O,position:S,intendedBytes:ae.intendedBytes,actualBytes:ae.actualBytes,byteDelta:ae.byteDelta,"agent.id":k,"agent.client_name":L})),recordContentDivergenceGate(`agent-write-md`,ae),recordContributor(O,k,j,F,void 0,Gi({clientName:L,clientVersion:B,label:H}),J),incrementAgentWriteCalls(),Xi(q)}finally{me?.touchMode(k,`idle`)}let oe=await Ht(O);if(oe?.kind===`failure`){Ut(w,oe.failure,`agent-write-md`);return}if(oe?.kind===`divergence`){Wt(w,`agent-write-md`);return}Vt(O,`agent-write-md`),fe?.setFocus(k,{agentName:j,currentDoc:O,writeKind:`write`,ts:Date.now()}),ge?.();let se=Lt(O),ce=await validateMermaidFences(Y.dc.document.getText(`source`).toString(),O),ue=zt(O),de=Bt();de===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(L)});let _e=Kt(te),ve=ae===void 0?void 0:toContentDivergenceWarning(ae),ye=[...ve?[ve]:[],..._e?[_e]:[],...ce??[]];successResponse(w,200,AgentWriteMdSuccessSchema,{timestamp:ne,subscriberCount:ue,systemSubscriberCount:de,...se?{hints:se}:{},...ee?{summary:ee}:{},...ve?{warning:ve}:_e?{warning:_e}:{},...ye.length>0?{warnings:ye}:{}},{handler:`agent-write-md`})}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(w,e,`agent-write-md`);return}if(e instanceof FrontmatterMalformedError){respondFrontmatterMalformed(w,e,`agent-write-md`);return}if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-write-md`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$6.error({err:e},`[agent-write-md] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-write-md`,cause:e})}},{handler:`agent-write-md`,method:`POST`}),Ds=withValidation(FrontmatterPatchRequestSchema,async(S,w,E)=>{try{let S=requireNonEmptyDocName(E.docName,w,`frontmatter-patch`);if(S===null)return;let D=Rt(S),{agentId:O,agentName:k,colorSeed:j,clientName:F,clientVersion:L,label:B}=Ui(E);if(isSystemDoc(D)||isConfigDoc(D)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${D}' is a reserved document name.`,{handler:`frontmatter-patch`});return}let H=E.patch??{},q=Object.keys(H),ee=normalizeSummary(E.summary),{response:J,stored:Y}=Ki(ee),te=await s.getSession(D,O,{displayName:k,colorSeed:j,clientName:F}),ne=reconcileDiskBeforeAgentWrite(t,D,g,e.resolveEmbed),ae=new Date().toISOString(),oe,se=!1,ce=!1,ue=[];try{let e=iconFromClientName(F),t=AGENT_ICON_COLORS[e]??colorFromSeed(j??O);me?.setPresence(O,{displayName:k,icon:e,color:t,currentDoc:D,mode:`writing`,ts:Date.now()}),withSpanSync(`ok.frontmatter_patch`,{attributes:{"doc.name":D,"frontmatter_patch.keys":q.length}},()=>{te.dc.document.transact(()=>{let{fenced:e,body:t}=detectFmRegion(te.dc.document.getText(`source`).toString()),s=applyPatchToFm(e,H);if(!s.ok){oe=s.error;return}for(let e of Object.keys(H))ue.push(e);if(s.nextFenced!==e){let g=e===``&&t!==``&&!t.startsWith(`
1938
+ `)}function vt(){Xe=null}j?.(vt);let Tt=createInstalledAgentsProbe({probe:De??createOsProbe(process.platform)});function Et(e){if(isManagedArtifactDocName(e))try{return managedArtifactAbsPath(e,{projectDir:ye??g,homedirOverride:we})}catch{return null}if(!isSafeDocName(e))return null;let t=resolve(g),s=resolve(t,`${e}${getDocExtension(e)}`);return isWithinDir(s,t)?s:null}function Dt(e){let t=Et(e);if(!t||!existsSync(t))return e;try{return extractPageTitle(readFileSync(t,`utf-8`),e)}catch{return e}}function jt(e,t){return t.has(e)?Dt(e):e}let Mt={cluster:void 0,category:void 0,tags:void 0};function Ft(e){try{let s=t.documents.get(e);if(s){let e=readFmMap(s.getText(`source`).toString());if(Object.keys(e).length>0){let t=typeof e.cluster==`string`?e.cluster:void 0,s=typeof e.category==`string`?e.category:void 0,g;if(Array.isArray(e.tags)){let t=e.tags.filter(e=>typeof e==`string`);g=t.length>0?t:void 0}else typeof e.tags==`string`&&e.tags&&(g=[e.tags]);return{cluster:t,category:s,tags:g}}}}catch{}try{let t=Et(e);if(!t||!existsSync(t))return Mt;let{frontmatter:s}=stripFrontmatter(readFileSync(t,`utf-8`));return s?parseFrontmatterMetadata(s):Mt}catch{return Mt}}function It(e,t){return t.has(e)?Ft(e):Mt}function Lt(e){if(ce)try{if(ce.getBacklinks(e).length>0)return;let t=performance.now(),s=findHubCandidates(e,w()),g=performance.now()-t;return g>5&&log$6.debug({docName:e,elapsedMs:g,candidateCount:s.length},`[orphan-hint] findHubCandidates slow`),s.length===0?void 0:[{type:`orphan`,parentCandidates:s,message:`This doc has no backlinks yet. To make it discoverable, consider linking from a parent hub doc (index/overview files in the folder tree): ${s.map(e=>`[[${e}]]`).join(`, `)}.`}]}catch(e){console.warn(`[orphan-hint] computeOrphanHints failed:`,e);return}}function Rt(e){return F?.().get(e)??e}function zt(e){try{return t.documents.get(e)?.connections.size??0}catch{return 0}}function Bt(){try{return t.documents.get(`__system__`)?.connections.size??0}catch{return 0}}function Vt(e,s){let g=`onStoreDocument-${e}`;(t.debouncer.isDebounced(g)?t.debouncer.executeNow(g):Promise.resolve()).then(()=>ee?.()).catch(e=>{log$6.warn({err:e},`[${s}] post-write flush failed`)})}async function Ht(e){let s=`onStoreDocument-${e}`;t.debouncer.isDebounced(s)&&(ne?.(e),await t.debouncer.executeNow(s));let g=Y?.(e)??null;return g?{kind:`failure`,failure:g}:te?.(e)?{kind:`divergence`}:null}function Ut(e,t,s){let g=classifyUploadErrno({code:t.code});errorResponse(e,uploadStatusFor(g),g,`Write applied in memory but failed to persist to disk (${t.code??`unknown error`}): ${t.message}. The content was NOT saved and will be lost if the server restarts.`,{handler:s})}function Wt(e,t){errorResponse(e,409,`urn:ok:error:disk-divergence`,`The document changed on disk after your edit was prepared; your edit was NOT applied, to avoid overwriting the newer on-disk content. Re-read the document and retry.`,{handler:t})}function Kt(e){if(e.reconciled)return{kind:`disk-edit-reconciled`,intendedBytes:e.baseBytes,actualBytes:e.diskBytes,byteDelta:e.diskBytes-e.baseBytes,...e.mergeOutcome?{mergeOutcome:e.mergeOutcome}:{},hint:e.mergeOutcome===`merged`?'An out-of-band edit was three-way merged into this document before your edit was applied on top; the merge may have interleaved content blocks. Re-read it (e.g. `exec("cat <path>")`) and review the combined result carefully before continuing.':'An out-of-band edit was reconciled into this document before your edit was applied on top; the document now reflects that edit plus yours. Re-read it (e.g. `exec("cat <path>")`) to see the combined result before continuing.'}}function $t(){let e=new Set;for(let[t,s]of w()){e.add(t);for(let t of s.aliases)e.add(t)}try{for(let t of[`project`,`global`]){let s=resolve(t===`global`?$l:g,`.ok`,`skills`);for(let g of ou(s,t).skills)e.add(`${MANAGED_ARTIFACT_PREFIX_SKILL}${t}/${g.name}`)}for(let t of resolveProjectTemplates(resolve(g)).templates)e.add(tu(t.source_folder,t.name))}catch(e){log$6.warn({err:e},`[collectAdmittedDocNames] managed-artifact enumeration failed`)}return e}let en=e=>existsSync(resolve(g,e));function jr(){let e=Promise.resolve();return async function(t){let s=e,g=()=>{};e=new Promise(e=>{g=e}),await s;try{return await t()}finally{g()}}}let Mr=jr(),Fr=e=>e.endsWith(`.`)?e:`${e}.`;function Ir(e){return e instanceof Error?e instanceof ManagedRenameSourceNotFoundError?{status:404,type:`urn:ok:error:doc-not-found`,error:Fr(e.message)}:e instanceof ManagedRenameDestinationExistsError?{status:409,type:`urn:ok:error:doc-already-exists`,error:Fr(e.message)}:e instanceof ManagedRenameSourceTypeMismatchError||e instanceof ManagedRenameInvalidRequestError?{status:400,type:`urn:ok:error:invalid-request`,error:Fr(e.message)}:e instanceof ManagedRenameReservedPathError?{status:400,type:`urn:ok:error:reserved-doc-name`,error:Fr(e.message)}:e instanceof ManagedRenameMissingDocumentError||e instanceof ManagedRenameSnapshotMissingError?{status:404,type:`urn:ok:error:doc-not-found`,error:Fr(e.message)}:e instanceof SymlinkEscapeError?{status:400,type:`urn:ok:error:path-escape`,error:Fr(e.message)}:e instanceof BacklinkIndexRequiredError?{status:503,type:`urn:ok:error:backlink-index-not-configured`,error:Fr(e.message)}:{status:500,type:`urn:ok:error:internal-server-error`,error:`Failed to rename document.`}:{status:500,type:`urn:ok:error:internal-server-error`,error:`Failed to rename document.`}}async function Lr(e){let g=new Map;for(let s of e){let e=t.documents.get(s);e&&g.set(s,e.getText(`source`).toString())}for(let t of e)await s.closeAllForDoc(t).catch(e=>{console.warn(`[file-ops] Failed to close agent session for ${t}:`,e)});for(let s of e){let e=t.documents.get(s);deleteReconciledBase(s),Re?.(s),e&&(t.closeConnections(s),await(je??t.unloadDocument.bind(t))(e))}return g}function zr(e,t){for(let{fromDocName:s,toDocName:S}of e){let e=safeContentPath(S,g),w=t.get(s);typeof w==`string`&&writeFileIfContentDiffers(e,w);let E=typeof w==`string`?w:existsSync(e)?readFileSync(e,`utf-8`):null;typeof E==`string`&&registerWrite(e,contentHash(E))}}function Br(e,t){return e.map(e=>{let s=t.get(e);if(typeof s==`string`)return{docName:e,content:s};let S=safeContentPath(e,g);if(!existsSync(S))throw new ManagedRenameSnapshotMissingError(e);return{docName:e,content:readFileSync(S,`utf-8`)}})}function Vr(e){let s=t.documents.get(e);if(s)return s.getText(`source`).toString();let S=resolveContentEntryPath(g,`file`,e);return existsSync(S)?readFileSync(S,`utf-8`):null}function Hr(e,t){let s=resolveContentEntryPath(g,`file`,e);tracedMkdirSync(dirname(s),{recursive:!0}),writeFileIfContentDiffers(s,t),registerWrite(s,contentHash(t)),setReconciledBase(e,t),D?.({kind:`update`,path:s,docName:e,content:t})}function Ur(e,s,g=[]){let S=t.documents.get(e);if(!S)throw Error(`Document is not loaded: ${e}`);let w={markdown:``,rewrites:0};return S.transact(()=>{w=Gr(S.getText(`source`).toString(),e,s.get(e)??e,s,g),w.rewrites!==0&&composeAndWriteRawBody(S,w.markdown,`managed-rename`,!1)},MANAGED_RENAME_ORIGIN),w}function Wr(e,t,s){let g=e,S=0;for(let{fromPath:e,toPath:w}of s){let s=rewriteAssetReferencesForRename(g,t,e,w);g=s.markdown,S+=s.rewrites}return{markdown:g,rewrites:S}}function Gr(e,t,s,g,S){let w=applyRenameMap(e,t,g),E=Wr(w.markdown,s,S);return{markdown:E.markdown,rewrites:E.markdown===e?0:w.rewrites+E.rewrites}}function Kr(e,s){let g=t.documents.get(e);if(!g)throw Error(`Document is not loaded: ${e}`);let S={markdown:``,rewrites:0};return g.transact(()=>{S=Wr(g.getText(`source`).toString(),e,s),S.rewrites!==0&&composeAndWriteRawBody(g,S.markdown,`managed-rename`,!1)},MANAGED_RENAME_ORIGIN),S}function qr(e){let t=[];if(e.length===0)return t;let s=[...w().keys()].sort((e,t)=>e.localeCompare(t));for(let g of s){let s=Vr(g);if(typeof s!=`string`)continue;let S=Wr(s,g,e);S.rewrites!==0&&t.push({docName:g,markdown:S.markdown,rewrites:S.rewrites})}return t}function Jr(e){let s=_e?.(),g=new Set(s?s.getConflicts().map(e=>e.file):[]);for(let s of e){let e=t.documents.get(s),S=`${s}${getDocExtension(s)}`,w=e!==void 0&&isDocInConflict(e),E=g.has(S);if(w||E)throw new DocInConflictError({file:S})}}function Yr(e,s){let g=[];for(let S of e){let e=t.documents.get(S.docName)?Kr(S.docName,s):S;e.rewrites!==0&&(Hr(S.docName,e.markdown),ce?.updateDocumentFromMarkdown(S.docName,e.markdown),g.push({docName:S.docName,rewrites:e.rewrites}))}return g}function Xr(e){if(extname(e))return{path:e,ambiguous:!1};let t=e.lastIndexOf(`/`),s=t===-1?``:e.slice(0,t),S=t===-1?e:e.slice(t+1),w=s?resolveContentEntryPath(g,`folder`,s):g,E;try{E=readdirSync(w,{withFileTypes:!0})}catch(t){let s=t.code;if(s===`ENOENT`||s===`ENOTDIR`)return{path:e,ambiguous:!1};throw t}let D=E.filter(e=>e.isFile()&&e.name.startsWith(`${S}.`)).map(e=>s?`${s}/${e.name}`:e.name).filter(e=>isSupportedAssetFile(e,LINKABLE_ASSET_EXTENSIONS));return D.length===1?{path:D[0],ambiguous:!1}:{path:e,ambiguous:D.length>1}}function Zr(e){let t=[];try{if(!statSync(e).isDirectory())return t}catch(e){let s=e.code;if(s===`ENOENT`||s===`ENOTDIR`)return t;throw e}function s(e){for(let S of readdirSync(e,{withFileTypes:!0})){let w=resolve(e,S.name),E=relative(g,w).split(sep).join(`/`);if(isReservedProjectStatePath(E))continue;if(S.isDirectory()){if(Te?.isDirExcluded(E))continue;s(w);continue}if(!S.isFile()||!isSupportedDocFile(E)||Te?.isExcluded(E))continue;let D=stripDocExtension(E);registerDocExtension(D,extname(E)),t.push(D)}}return s(e),t.sort((e,t)=>e.localeCompare(t)),t}function Qr(e,t,s){let S=[];function w(e){for(let E of readdirSync(e,{withFileTypes:!0})){let D=resolve(e,E.name),O=relative(g,D).split(sep).join(`/`);if(!isReservedProjectStatePath(O)){if(E.isDirectory()){if(Te?.isDirExcluded(O))continue;w(D);continue}!E.isFile()||isSupportedDocFile(O)||Te?.isExcluded(O)||(O===t?S.push({fromPath:O,toPath:s}):O.startsWith(`${t}/`)&&S.push({fromPath:O,toPath:`${s}${O.slice(t.length)}`}))}}}return w(e),S.sort((e,t)=>e.fromPath.localeCompare(t.fromPath)),S}async function ji(e,t){return Mr(async()=>withSpan(`rename.executeAssetRewrites`,{attributes:{"rename.kind":`asset`}},async s=>{if(!ce)throw new BacklinkIndexRequiredError;let S=extname(t)?t:`${t}${extname(e)}`;if(isReservedProjectStatePath(e)||isReservedProjectStatePath(S))throw new ManagedRenameReservedPathError(`.ok and .git are reserved directories.`);if(Te?.isPathIgnored(S))throw new ManagedRenameInvalidRequestError(`Destination asset is excluded by the project content config.`);let w=resolveContentEntryPath(g,`folder`,e),E=resolveContentEntryPath(g,`folder`,S);if(w===E)return{renamedAssets:[],rewrittenDocs:[]};if(stringsDifferOnlyByCase(e,S))throw new ManagedRenameInvalidRequestError(`Case-only renames are not supported.`);if(!existsSync(w))throw new ManagedRenameSourceNotFoundError(`asset`,`Asset does not exist.`);if(existsSync(E))throw new ManagedRenameDestinationExistsError;if(!statSync(w).isFile())throw new ManagedRenameSourceTypeMismatchError(`asset`,`Source path is not an asset file.`);let D=[{fromPath:e,toPath:S}],O=qr(D);s.setAttribute(`rename.rewrite_candidates`,O.length),Jr(O.map(e=>e.docName)),await renameTrackedPathInGit(ye,w,E)||renamePathOnDisk(w,E);let k=Yr(O,D);return ce.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist asset rename cache for ${e} -> ${S}:`,t)}),de?.(`files`),k.length>0&&(de?.(`backlinks`),de?.(`graph`)),k.sort((e,t)=>e.docName.localeCompare(t.docName)),s.setAttribute(`rename.rewrite_count`,k.length),{renamedAssets:D,rewrittenDocs:k}}))}async function Hi(e,s){return Mr(async()=>withSpan(`rename.executeDocumentToFileRewrites`,{attributes:{"rename.kind":`asset`,"rename.transition":`document-to-file`}},async S=>{if(!ce)throw new BacklinkIndexRequiredError;if(!isSupportedDocFile(e)||isSupportedDocFile(s))throw new ManagedRenameInvalidRequestError(`Document-to-file rename requires a markdown source and non-markdown destination.`);let w=stripDocExtension(e);if(isSystemDoc(w)||isConfigDoc(w))throw new ManagedRenameReservedPathError(`Reserved document names cannot be renamed.`);if(isReservedProjectStatePath(e)||isReservedProjectStatePath(s))throw new ManagedRenameReservedPathError(`.ok and .git are reserved directories.`);if(Te?.isPathIgnored(s))throw new ManagedRenameInvalidRequestError(`Destination file is excluded by the project content config.`);let E=resolveContentEntryPath(g,`folder`,e),O=resolveContentEntryPath(g,`folder`,s);if(E===O)return{renamedAssets:[],rewrittenDocs:[]};if(stringsDifferOnlyByCase(e,s))throw new ManagedRenameInvalidRequestError(`Case-only renames are not supported.`);if(!existsSync(E))throw new ManagedRenameSourceNotFoundError(`file`);if(existsSync(O))throw new ManagedRenameDestinationExistsError;if(!statSync(E).isFile())throw new ManagedRenameSourceTypeMismatchError(`file`,`Source path is not a document file.`);let k=_e?.(),j=new Set(k?k.getConflicts().map(e=>e.file):[]),F=t.documents.get(w);if(F!==void 0&&isDocInConflict(F)||j.has(e))throw new DocInConflictError({file:e});let L=[{fromPath:e,toPath:s}],B=qr(L).filter(e=>e.docName!==w);S.setAttribute(`rename.rewrite_candidates`,B.length),Jr(B.map(e=>e.docName)),reconcileDiskBeforeAgentWrite(t,w,g),Pe&&!isSystemDoc(w)&&!isConfigDoc(w)&&Pe.setDeleted(w);let H=(await Lr([w])).get(w),q=typeof H==`string`?H:readFileSync(E,`utf-8`),ee=createManagedRenameRecoveryJournal({fromPath:e,toPath:s,affectedDocs:[{from:w,to:w}],snapshots:[{docName:w,content:q}],cleanupPaths:[s]}),J=[];return await withManagedRenameRecovery(ye??g,ee,async()=>{writeFileIfContentDiffers(E,q),registerWrite(E,contentHash(q)),await renameTrackedPathInGit(ye,E,O)||renamePathOnDisk(E,O),ce.deleteDocument(w),forgetDocExtension(w),D?.({kind:`delete`,path:E,docName:w});let t=statSync(O);D?.({kind:`file-create`,path:O,relativePath:s,size:t.size,modifiedTs:t.mtimeMs,inode:t.ino}),J=Yr(B,L),ce.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist document-to-file rename cache for ${e} -> ${s}:`,t)}),de?.(`files`),J.length>0&&(de?.(`backlinks`),de?.(`graph`))}),J.sort((e,t)=>e.docName.localeCompare(t.docName)),S.setAttribute(`rename.rewrite_count`,J.length),{renamedAssets:L,rewrittenDocs:J}}))}async function Ui(e,s,S,E){return Mr(async()=>withSpan(`rename.executeRewrites`,{attributes:{"rename.kind":S}},async O=>{if(!ce)throw new BacklinkIndexRequiredError;let k=resolveContentEntryPath(g,S,e),j=resolveContentEntryPath(g,S,s);if(k===j)return{renamed:[],renamedAssets:[],rewrittenDocs:[]};if(!existsSync(k))throw new ManagedRenameSourceNotFoundError(S);if(existsSync(j)&&!isCaseOnlySelfCollision(k,j))throw new ManagedRenameDestinationExistsError;let F=statSync(k);if(S===`file`&&!F.isFile()||S===`folder`&&!F.isDirectory())throw new ManagedRenameSourceTypeMismatchError(S);let L=S===`folder`?Qr(k,e,s):[];O.setAttribute(`rename.affected_assets`,L.length);let B=(S===`file`?[stripDocExtension(e)]:Zr(k)).map(t=>({from:t,to:S===`file`?stripDocExtension(s):remapDocNameForRename(t,S,e,s)}));if(O.setAttribute(`rename.affected_docs`,B.length),B.length===0){let t=qr(L);Jr(t.map(e=>e.docName));let g=[];return S===`folder`&&(await renameTrackedPathInGit(ye,k,j)||renamePathOnDisk(k,j),at(e,s),de?.(`files`)),g.push(...Yr(t,L)),g.length>0&&(ce.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist managed rename cache for ${e} -> ${s}:`,t)}),de?.(`backlinks`),de?.(`graph`)),g.sort((e,t)=>e.docName.localeCompare(t.docName)),{renamed:[],renamedAssets:L,rewrittenDocs:g}}let H=buildRenameMap(B),ee=B.map(({from:e,to:t})=>({fromDocName:e,toDocName:t})),J=new Set;for(let{from:e}of B)for(let t of ce.getBacklinks(e))H.has(t.source)||J.add(t.source);let Y=[...J].sort((e,t)=>e.localeCompare(t)),te=new Map,ne=new Set,oe=new Set,se=[];for(let e of[...H.keys(),...Y]){if(te.has(e))continue;if(!H.has(e)&&!existsSync(resolveContentEntryPath(g,`file`,e))){se.push(e);continue}reconcileDiskBeforeAgentWrite(t,e,g);let s=Vr(e);typeof s==`string`?(te.set(e,s),H.has(e)||ne.add(e)):H.has(e)||se.push(e)}if(L.length>0){let e=[...w().keys()].sort((e,t)=>e.localeCompare(t));for(let t of e){let e=te.get(t)??Vr(t);typeof e==`string`&&Gr(e,t,H.get(t)??t,H,L).rewrites!==0&&(te.has(t)||te.set(t,e),oe.add(t),H.has(t)||ne.add(t))}}Jr(oe);for(let{from:e}of B)if(typeof te.get(e)!=`string`)throw new ManagedRenameMissingDocumentError(e);let ue=createManagedRenameRecoveryJournal({fromPath:e,toPath:s,affectedDocs:[...B],snapshots:Br([...te.keys()],te)}),fe=[],me=[...ne].sort((e,t)=>e.localeCompare(t));return await withManagedRenameRecovery(ye??g,ue,async()=>{for(let e of se)ce.deleteDocument(e);for(let e of me){let s=t.documents.get(e)?Ur(e,H,L):Gr(te.get(e)??``,e,e,H,L);s.rewrites>0&&(Hr(e,s.markdown),fe.push({docName:e,rewrites:s.rewrites})),ce.updateDocumentFromMarkdown(e,s.markdown)}if(Pe)for(let{from:e,to:t}of B)isSystemDoc(e)||isConfigDoc(e)||(Pe.setRenamed(e,t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,from:e,to:t,kind:`renamed`,source:`spine`})));let w=resolveContentEntryPath(g,S,e),O=resolveContentEntryPath(g,S,s);await renameTrackedPathInGit(ye,w,O)||renamePathOnDisk(w,O),S===`folder`&&at(e,s);let k=await Lr([...H.keys()]);if(process.env.NODE_ENV===`test`&&process.env.OK_TEST_RENAME_FAULT===`pre-append`)throw Error(`OK_TEST_RENAME_FAULT=pre-append`);if(q?.current){let e=q.current,t=B.filter(({from:e,to:t})=>e!==t);t.length>0&&withSpanSync(`rename.appendLog`,{attributes:{"rename.kind":S}},s=>{let g=randomUUID$1(),w=new Date().toISOString(),D=ae?.()??`main`,O=getOrLoadRenameLogIndex(e.gitDir),k=E?.actor?{writerId:E.actor.writerId,displayName:E.actor.displayName}:{writerId:SERVICE_WRITER.id,displayName:SERVICE_WRITER.name},j=0;for(let{from:s,to:F}of t){let t={v:1,from:s,to:F,at:w,commitSha:``,branch:D,groupId:g,kind:S,actor:k};appendRenameLogEntry(e.gitDir,t,O,e),j+=1,E?.actor?recordContributor(F,E.actor.writerId,E.actor.displayName,E.actor.colorSeed,formatRenameSubject(s,F),E.actor.actorMetadata,void 0,[{from:s,to:F}]):recordContributor(F,SERVICE_WRITER.id,SERVICE_WRITER.name,SERVICE_WRITER.id,formatRenameSubject(s,F),void 0,void 0,[{from:s,to:F}])}s.setAttribute(`rename.entries_appended`,j)})}let j=S===`file`&&isSupportedDocFile(s)?extname(s):null;for(let{from:e,to:t}of B){let s=getDocExtension(e);forgetDocExtension(e),registerDocExtension(t,j??s)}let F=[...B].sort((e,t)=>e.from.localeCompare(t.from));for(let{from:e,to:t}of F){let s=resolveContentEntryPath(g,`file`,e),S=resolveContentEntryPath(g,`file`,t),w=Gr(k.get(e)??te.get(e)??readFileSync(S,`utf-8`),e,t,H,L);zr([{fromDocName:e,toDocName:t}],new Map([[e,w.markdown]])),setReconciledBase(t,w.markdown),D?.({kind:`rename`,oldPath:s,newPath:S,oldDocName:e,newDocName:t,content:w.markdown}),ce.renameDocument(e,t,w.markdown),w.rewrites>0&&fe.push({docName:t,rewrites:w.rewrites})}if(process.env.NODE_ENV===`test`&&process.env.OK_TEST_RENAME_FAULT===`pre-journal-clear`)throw Error(`OK_TEST_RENAME_FAULT=pre-journal-clear`)}),ce.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist managed rename cache for ${e} -> ${s}:`,t)}),de?.(`files`),de?.(`backlinks`),de?.(`graph`),fe.sort((e,t)=>e.docName.localeCompare(t.docName)),O.setAttribute(`rename.rewrite_count`,fe.length),{renamed:ee,renamedAssets:L,rewrittenDocs:fe}}))}function Gi(e){let t=parseAgentBodyFields(e),s=t.writerId??`claude-1`;return{rawAgentId:t.rawAgentId,agentId:s,agentName:t.displayName,colorSeed:t.colorSeed??t.rawAgentId??s,clientName:t.clientName,clientVersion:t.clientVersion,label:t.label}}function Ki(e){return{principalId:Ce?.()?.id,agentType:resolveAgentType(e.clientName),clientName:e.clientName,clientVersion:e.clientVersion,label:e.label}}function Yi(e){return e.kind===`value`?e.truncatedFrom===void 0?{response:{value:e.value},stored:e.value}:{response:{value:e.value,truncatedFrom:e.truncatedFrom,hint:`Summary truncated from ${e.truncatedFrom} chars to 80 (max 80).`},stored:e.value}:{stored:void 0}}function Xi(e){return{value:e.value}}function Zi(e,t=!1){e.kind===`value`&&(incrementSummariesProvided(),e.truncatedFrom!==void 0&&!t&&incrementSummariesTruncated())}function ka(e,t,s,g){if(s.length!==0)switch(e.kind){case`agent`:{let g=e.summary.kind===`value`,S=g?e.summary:normalizeSummary(t),w=Yi(S),E=g||!w.response?w.response:Xi(w.response);for(let t=0;t<s.length;t++){let{docName:g,subject:S}=s[t];recordContributor(g,e.writerId,e.displayName,e.colorSeed,S,e.actor,t===0?w.stored:void 0)}incrementAgentWriteCalls(),Zi(S,!g);for(let{docName:e}of s)Vt(e,`rename-path`);return E}case`principal`:{let t=Yi(e.summary);for(let g=0;g<s.length;g++){let{docName:S,subject:w}=s[g];recordContributor(S,e.writerId,e.displayName,e.colorSeed,w,e.actor,g===0?t.stored:void 0)}Zi(e.summary,!1);for(let{docName:e}of s)Vt(e,`rename-path`);return t.response}case`anonymous`:g.onAnonymous?.();return;default:{let t=e;throw Error(`Unhandled actor kind in ${g.context}: ${String(t.kind)}`)}}}function _s(e,t,s){let g=t.replace(/\/$/,``),S=g===``?``:`${g}/`;return e===`template`?`${S}.ok/templates/${s}`:e===`skill`?`${S}.ok/skills/${s}`:e===`folder-frontmatter`?`${S}.ok/frontmatter`:g===``?`.`:g}function xs(e,t,s,g){if(e.kind!==`agent`&&e.kind!==`principal`)return;let S=Yi(e.summary);recordContributor(t,e.writerId,e.displayName,e.colorSeed,s,e.actor,S.stored,g)}async function Cs(e){if(J)try{await J()}catch(t){console.warn(`[${e}] flushContributors failed; attribution stays queued for the next flush:`,t)}}let Ts=withValidation(AgentWriteRequestSchema,async(S,w,E)=>{try{let S=requireNonEmptyDocName(E.docName,w,`agent-write`);if(S===null)return;let D=Rt(S),{agentId:O,agentName:k,colorSeed:j,clientName:F,clientVersion:L,label:B}=Gi(E);if(isSystemDoc(D)||isConfigDoc(D)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${D}' is a reserved document name.`,{handler:`agent-write`});return}let H=normalizeSummary(E.summary),q=await s.getSession(D,O,{displayName:k,colorSeed:j,clientName:F}),ee=reconcileDiskBeforeAgentWrite(t,D,g,e.resolveEmbed),J=new Date().toISOString(),Y=typeof E.content==`string`?E.content:`Hello from the agent! ${J}`,{response:te,stored:ne}=Yi(H);try{let t=iconFromClientName(F),s=AGENT_ICON_COLORS[t]??colorFromSeed(j??O);me?.setPresence(O,{displayName:k,icon:t,color:s,currentDoc:D,mode:`writing`,ts:Date.now()}),captureEffect(q.dc.document.getText(`source`),O,j,F),q.dc.document.transact(()=>{applyAgentMarkdownWrite(q.dc.document,`${Y}\n`,`append`,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:D}:void 0),q.dc.document.getMap(`agent-flash`).set(O,{agentId:O,timestamp:Date.now(),type:`insert`,description:`Added (${k}): ${Y.slice(0,50)}`})},q.origin),recordContributor(D,O,k,j,void 0,Ki({clientName:F,clientVersion:L,label:B}),ne),incrementAgentWriteCalls(),Zi(H)}finally{me?.touchMode(O,`idle`)}let ae=await Ht(D);if(ae?.kind===`failure`){Ut(w,ae.failure,`agent-write`);return}if(ae?.kind===`divergence`){Wt(w,`agent-write`);return}Vt(D,`agent-write`),ge?.();let oe=Kt(ee);successResponse(w,200,AgentWriteSuccessSchema,{timestamp:J,...te?{summary:te}:{},...oe?{warning:oe,warnings:[oe]}:{}},{handler:`agent-write`})}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(w,e,`agent-write`);return}if(e instanceof FrontmatterMalformedError){respondFrontmatterMalformed(w,e,`agent-write`);return}if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-write`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$6.error({err:e},`[agent-write] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-write`,cause:e})}},{handler:`agent-write`,method:`POST`}),Ds=withValidation(AgentWriteMdRequestSchema,async(S,w,E)=>{try{let S=E.position??`append`,D=requireNonEmptyDocName(E.docName,w,`agent-write-md`);if(D===null)return;let O=Rt(D),{agentId:k,agentName:j,colorSeed:F,clientName:L,clientVersion:B,label:H}=Gi(E);if(isSystemDoc(O)||isConfigDoc(O)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${O}' is a reserved document name.`,{handler:`agent-write-md`});return}E.extension!==void 0&&!docNameExistsWithAnySupportedExtension(g,O)&&registerDocExtension(O,E.extension);let q=normalizeSummary(E.summary),{response:ee,stored:J}=Yi(q),Y=await s.getSession(O,k,{displayName:j,colorSeed:F,clientName:L}),te=reconcileDiskBeforeAgentWrite(t,O,g,e.resolveEmbed),ne=new Date().toISOString(),ae;try{let t=iconFromClientName(L),s=AGENT_ICON_COLORS[t]??colorFromSeed(F??k);me?.setPresence(k,{displayName:j,icon:t,color:s,currentDoc:O,mode:`writing`,ts:Date.now()}),captureEffect(Y.dc.document.getText(`source`),k,F,L),Y.dc.document.transact(()=>{ae=applyAgentMarkdownWrite(Y.dc.document,E.markdown,S,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:O}:void 0),Y.dc.document.getMap(`agent-flash`).set(k,{agentId:k,timestamp:Date.now(),type:`insert`,description:`Added (${j}): ${E.markdown.trim().slice(0,50)}`})},Y.origin),ae!==void 0&&console.warn(JSON.stringify({event:`agent-write-content-divergence`,"doc.name":O,position:S,intendedBytes:ae.intendedBytes,actualBytes:ae.actualBytes,byteDelta:ae.byteDelta,"agent.id":k,"agent.client_name":L})),recordContentDivergenceGate(`agent-write-md`,ae),recordContributor(O,k,j,F,void 0,Ki({clientName:L,clientVersion:B,label:H}),J),incrementAgentWriteCalls(),Zi(q)}finally{me?.touchMode(k,`idle`)}let oe=await Ht(O);if(oe?.kind===`failure`){Ut(w,oe.failure,`agent-write-md`);return}if(oe?.kind===`divergence`){Wt(w,`agent-write-md`);return}Vt(O,`agent-write-md`),fe?.setFocus(k,{agentName:j,currentDoc:O,writeKind:`write`,ts:Date.now()}),ge?.();let se=Lt(O),ce=Y.dc.document.getText(`source`).toString(),ue=await validateMermaidFences(ce,O),de=$t();de.add(O);let _e=computeBrokenOutboundLinks(ce,O,de,en),ve=zt(O),ye=Bt();ye===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(L)});let Ce=Kt(te),we=ae===void 0?void 0:toContentDivergenceWarning(ae),Te=[...we?[we]:[],...Ce?[Ce]:[],...ue??[]];successResponse(w,200,AgentWriteMdSuccessSchema,{timestamp:ne,subscriberCount:ve,systemSubscriberCount:ye,...se?{hints:se}:{},...ee?{summary:ee}:{},...we?{warning:we}:Ce?{warning:Ce}:{},...Te.length>0?{warnings:Te}:{},brokenLinks:_e},{handler:`agent-write-md`})}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(w,e,`agent-write-md`);return}if(e instanceof FrontmatterMalformedError){respondFrontmatterMalformed(w,e,`agent-write-md`);return}if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-write-md`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$6.error({err:e},`[agent-write-md] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-write-md`,cause:e})}},{handler:`agent-write-md`,method:`POST`}),Os=withValidation(FrontmatterPatchRequestSchema,async(S,w,E)=>{try{let S=requireNonEmptyDocName(E.docName,w,`frontmatter-patch`);if(S===null)return;let D=Rt(S),{agentId:O,agentName:k,colorSeed:j,clientName:F,clientVersion:L,label:B}=Gi(E);if(isSystemDoc(D)||isConfigDoc(D)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${D}' is a reserved document name.`,{handler:`frontmatter-patch`});return}let H=E.patch??{},q=Object.keys(H),ee=normalizeSummary(E.summary),{response:J,stored:Y}=Yi(ee),te=await s.getSession(D,O,{displayName:k,colorSeed:j,clientName:F}),ne=reconcileDiskBeforeAgentWrite(t,D,g,e.resolveEmbed),ae=new Date().toISOString(),oe,se=!1,ce=!1,ue=[];try{let e=iconFromClientName(F),t=AGENT_ICON_COLORS[e]??colorFromSeed(j??O);me?.setPresence(O,{displayName:k,icon:e,color:t,currentDoc:D,mode:`writing`,ts:Date.now()}),withSpanSync(`ok.frontmatter_patch`,{attributes:{"doc.name":D,"frontmatter_patch.keys":q.length}},()=>{te.dc.document.transact(()=>{let{fenced:e,body:t}=detectFmRegion(te.dc.document.getText(`source`).toString()),s=applyPatchToFm(e,H);if(!s.ok){oe=s.error;return}for(let e of Object.keys(H))ue.push(e);if(s.nextFenced!==e){let g=e===``&&t!==``&&!t.startsWith(`
1935
1939
  `),S=s.nextFenced+(g?`
1936
- `:``)+t;composeAndWriteRawBody(te.dc.document,S,`agent`),recordFrontmatterEditSurface(`mcp-write`),ce=!0}se=!0},te.origin)})}finally{me?.touchMode(O,`idle`)}if(oe){let e;switch(oe.kind){case`invalid_value`:e={[oe.key]:oe.reason};break;case`reserved_key`:e={[oe.key]:`'${oe.key}' is reserved`};break;case`unknown_key`:e={[oe.key]:`'${oe.key}' is not a recognized key`};break;case`duplicate_target`:e={[oe.key]:`'${oe.key}' appears more than once`};break;case`reorder_mismatch`:e={__region__:`frontmatter reorder mismatch (expected: ${oe.expected.join(`, `)}; got: ${oe.got.join(`, `)})`};break;case`region_too_large`:e={__region__:`frontmatter region too large (${oe.bytes} > ${oe.limit} bytes)`};break;case`parse_failed`:e={__region__:`frontmatter region unparseable: ${oe.reason}`};break;case`invalid_path`:e={[oe.path.map(String).join(`.`)||`__path__`]:oe.reason};break;default:e={__region__:`unhandled frontmatter edit error (${String(oe)})`}}errorResponse(w,400,`urn:ok:error:invalid-frontmatter-patch`,`Frontmatter patch rejected: schema validation failed.`,{handler:`frontmatter-patch`,extensions:{fieldErrors:e}});return}if(se&&ue.length>0){if(recordContributor(D,O,k,j,void 0,Gi({clientName:F,clientVersion:L,label:B}),Y),incrementAgentWriteCalls(),Xi(ee),ce){let e=await Ht(D);if(e?.kind===`failure`){Ut(w,e.failure,`frontmatter-patch`);return}if(e?.kind===`divergence`){Wt(w,`frontmatter-patch`);return}}Vt(D,`frontmatter-patch`)}fe?.setFocus(O,{agentName:k,currentDoc:D,writeKind:`write`,ts:Date.now()}),ge?.();let de=zt(D),_e=Bt();_e===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(F)});let ve=Kt(ne);successResponse(w,200,FrontmatterPatchSuccessSchema,{timestamp:ae,subscriberCount:de,systemSubscriberCount:_e,appliedKeys:ue,...J?{summary:J}:{},...ve?{warning:ve,warnings:[ve]}:{}},{handler:`frontmatter-patch`})}catch(e){if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`frontmatter-patch`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$6.error({err:e},`[frontmatter-patch] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`frontmatter-patch`,cause:e})}},{handler:`frontmatter-patch`,method:`POST`});function Os(e){let t=e.getMap(`lifecycle`),s=t.get(`status`);if(typeof s!=`string`||s.length===0)return null;let g=t.get(`reason`);return{status:s,reason:typeof g==`string`?g:``}}let ks=withValidation(EmptyRequestSchema,async(e,s)=>{try{let S=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`docName`)||`test-doc`;if(!isSafeDocName(S)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`document-read`});return}let w=Rt(S);if(isSystemDoc(w)||isConfigDoc(w)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`'${w}' is a reserved document name.`,{handler:`document-read`});return}let E=t.documents.get(w);if(E){successResponse(s,200,DocumentReadSuccessSchema,{docName:w,content:E.getText(`source`).toString(),lifecycle:Os(E)},{handler:`document-read`});return}if(!existsSync(resolveContentEntryPath(g,`file`,w))){errorResponse(s,404,`urn:ok:error:doc-not-found`,`Document not found: ${w}.`,{handler:`document-read`});return}let D=await t.openDirectConnection(w);try{let e=D.document;if(!e){errorResponse(s,500,`urn:ok:error:doc-not-available`,`Document is not available.`,{handler:`document-read`});return}successResponse(s,200,DocumentReadSuccessSchema,{docName:w,content:e.getText(`source`).toString(),lifecycle:Os(e)},{handler:`document-read`})}finally{await D.disconnect()}}catch(e){errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to read document.`,{handler:`document-read`,cause:e})}},{handler:`document-read`,method:`GET`,skipBodyParse:!0}),As=withValidation(EmptyRequestSchema,async(e,t)=>{try{Me&&await Me.catch(e=>{log$6.warn({err:e,handler:`document-list`},`[api] ready gate rejected — responding with partial index`)});let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=s.searchParams.get(`dir`),D=s.searchParams.get(`showAll`)===`true`,O=s.searchParams.get(`depth`)===`1`?1:1/0;if(S)try{safeSubdir(g,S)}catch{errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid directory parameter.`,{handler:`document-list`});return}if(D&&Te&&showAllWantsNdjson(e)){let e=new AbortController;t.on(`close`,()=>{t.writableEnded||e.abort()}),t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let s=createStreamingErrorWriter(t,`document-list`),w=async e=>{t.writableEnded||t.destroyed||t.write(e)||await new Promise(e=>{let s=()=>{t.off(`drain`,s),t.off(`close`,s),e()};t.once(`drain`,s),t.once(`close`,s)})};try{let t=getShowAllMaxEntries(),s=streamShowAllEntries({contentDir:g,contentFilter:Te,dirFilter:S,getDocExtension,maxEntries:t,maxDepth:O,signal:e.signal}),E=0,D=await s.next();for(;!D.done;)await w(`${JSON.stringify(D.value)}\n`),E+=1,D=await s.next();let{truncated:k}=D.value;k&&log$6.info({handler:`document-list`,maxEntries:t,count:E},`[document-list][showAll] stream truncated at entry cap`),await w(`${JSON.stringify({type:`complete`,truncated:k,count:E})}\n`)}catch(e){!t.writableEnded&&!t.destroyed?s(500,`urn:ok:error:internal-server-error`,`Failed to list documents (showAll stream).`,{cause:e}):log$6.error({err:e,handler:`document-list`},`[document-list][showAll] stream failed after response ended`)}finally{t.writableEnded||t.end()}return}if(D&&Te){let e=`showAll:${O===1?`d1:`:``}${S??``}`,s=Ge.get(e);if(!s){let t=new AbortController,w=(async()=>{let e=[],s=getShowAllMaxEntries(),{truncated:w}=await walkContentDirForShowAll({contentDir:g,contentFilter:Te,dirFilter:S,documents:e,getDocExtension,maxEntries:s,maxDepth:O,signal:t.signal});return e.sort((e,t)=>{let s=e.kind===`folder`?e.path??``:e.docName??e.path??``,g=t.kind===`folder`?t.path??``:t.docName??t.path??``;return s.localeCompare(g)}),w&&log$6.info({handler:`document-list`,maxEntries:s,count:e.length},`[document-list][showAll] walk truncated at entry cap`),{documents:e,truncated:w}})();s={promise:w,controller:t,waiters:0};let E=s;Ge.set(e,E),w.finally(()=>{Ge.get(e)===E&&Ge.delete(e)})}let w=s;w.waiters+=1;let E=!1,D=()=>{t.writableEnded||E||(E=!0,--w.waiters,w.waiters<=0&&(w.controller.abort(),Ge.get(e)===w&&Ge.delete(e)))};t.on(`close`,D);try{let{documents:e,truncated:s}=await w.promise;if(E)return;successResponse(t,200,DocumentListSuccessSchema,s?{documents:e,truncated:s}:{documents:e},{handler:`document-list`})}catch(e){if(E)return;errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list documents (showAll mode).`,{handler:`document-list`,cause:e})}finally{t.removeListener(`close`,D)}return}let j=w(),F=E(),B=k?.()??new Map,H=[];for(let[e,t]of B)S&&!e.startsWith(`${S}/`)&&e!==S||H.push({kind:`folder`,path:e,size:0,modified:t.modified,docExt:`.md`,isSymlink:!1,canonicalDocName:null,targetPath:null});let q=[];try{let e=st(j);Xe?.signature!==e&&(Xe={signature:e,assets:collectReferencedAssets({contentDir:g,fileIndex:j,readMarkdown:e=>{try{return readFileSync(e,`utf-8`)}catch{return null}},isExcluded:Te?e=>Te.isPathIgnored(e):void 0})}),q=Xe?.assets??[]}catch(e){Xe=null,console.warn(`[document-list] asset collection failed; returning documents only:`,e)}let ee=new Set;for(let e of q)S&&!e.path.startsWith(`${S}/`)&&e.path!==S||(ee.add(e.path),H.push({kind:`asset`,docName:e.path,docExt:e.assetExt,path:e.path,assetExt:e.assetExt,mediaKind:e.mediaKind,referencedBy:e.referencedBy,size:e.size,modified:e.modified,isSymlink:!1,canonicalDocName:null,targetPath:null}));for(let[e,t]of F){if(t.kind===`markdown`){if(S&&!e.startsWith(`${S}/`)&&e!==S)continue;let s=getDocExtension(e);H.push({kind:`document`,docName:e,docExt:s,size:t.size,modified:t.modified,isSymlink:!1,canonicalDocName:null,targetPath:null});for(let w of t.aliases){if(S&&!w.startsWith(`${S}/`)&&w!==S)continue;let E=toPosix(relative(g,t.canonicalPath));H.push({kind:`document`,docName:w,docExt:s,size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:E})}continue}if((!S||e===S||e.startsWith(`${S}/`))&&!ee.has(e)){let s=synthesizeShowAllAssetExt(e);H.push({kind:`file`,docName:e,path:e,docExt:`.${s}`,assetExt:s,size:t.size,modified:t.modified,isSymlink:!1,canonicalDocName:null,targetPath:null})}for(let s of t.aliases){if(!(!S||s===S||s.startsWith(`${S}/`))||ee.has(s))continue;let w=toPosix(relative(g,t.canonicalPath)),E=synthesizeShowAllAssetExt(s);H.push({kind:`file`,docName:s,path:s,docExt:`.${E}`,assetExt:E,size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:w})}}let J=L?.()??new Map;if(J.size>0){let e=e=>!S||e===S||e.startsWith(`${S}/`),t=new Map;for(let[e,s]of J){let g=t.get(s);g?g.push(e):t.set(s,[e])}for(let[s,S]of t){let t=B.get(s),w=t?toPosix(relative(g,t.canonicalPath)):s;for(let g of S)e(g)&&H.push({kind:`folder`,path:g,size:0,modified:t?.modified??`1970-01-01T00:00:00.000Z`,docExt:`.md`,isSymlink:!0,canonicalDocName:s,targetPath:w})}let s=(s,g)=>{for(let S=s.indexOf(`/`);S!==-1;S=s.indexOf(`/`,S+1)){let w=t.get(s.slice(0,S));if(!w)continue;let E=s.slice(S);for(let t of w){let s=`${t}${E}`;e(s)&&g(s)}}};for(let[e,t]of B)s(e,s=>{H.push({kind:`folder`,path:s,size:0,modified:t.modified,docExt:`.md`,isSymlink:!0,canonicalDocName:e,targetPath:toPosix(relative(g,t.canonicalPath))})});for(let[e,t]of F)s(e,s=>{let S=toPosix(relative(g,t.canonicalPath));if(t.kind===`markdown`)H.push({kind:`document`,docName:s,docExt:getDocExtension(e),size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:S});else{let g=synthesizeShowAllAssetExt(s);H.push({kind:`file`,docName:s,path:s,docExt:`.${g}`,assetExt:g,size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:S})}})}H.sort((e,t)=>{let s=e.kind===`folder`?e.path??``:e.docName??e.path??``,g=t.kind===`folder`?t.path??``:t.docName??t.path??``;return s.localeCompare(g)}),successResponse(t,200,DocumentListSuccessSchema,{documents:H},{handler:`document-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list documents.`,{handler:`document-list`,cause:e})}},{handler:`document-list`,method:`GET`,skipBodyParse:!0}),Ns=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`backlinks`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!s){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`backlinks`});return}if(!isSafeDocName(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`backlinks`});return}successResponse(t,200,BacklinksSuccessSchema,{docName:s,backlinks:ce.getBacklinks(s).map(e=>({source:e.source,anchor:e.anchor,title:Dt(e.source),snippet:e.snippet}))},{handler:`backlinks`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read backlinks.`,{handler:`backlinks`,cause:e})}},{handler:`backlinks`,method:`GET`,skipBodyParse:!0}),Ps=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`backlink-counts`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docNames`);if(!s){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docNames parameter.`,{handler:`backlink-counts`});return}let g={};for(let e of s.split(`,`)){let t=e.trim();!t||!isSafeDocName(t)||(g[t]=ce.getBacklinkCount(t))}successResponse(t,200,BacklinkCountsSuccessSchema,{counts:g},{handler:`backlink-counts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read backlink counts.`,{handler:`backlink-counts`,cause:e})}},{handler:`backlink-counts`,method:`GET`,skipBodyParse:!0}),Is=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`forward-links`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!s){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`forward-links`});return}if(!isSafeDocName(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`forward-links`});return}let g=$t();successResponse(t,200,ForwardLinksSuccessSchema,{docName:s,forwardLinks:ce.getForwardLinkEntries(s).map(e=>e.kind===`doc`?{kind:`doc`,docName:e.target,anchor:e.anchor,title:jt(e.target,g),snippet:e.snippet}:{kind:`external`,url:e.url,title:e.label??e.url,snippet:e.snippet})},{handler:`forward-links`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read forward links.`,{handler:`forward-links`,cause:e})}},{handler:`forward-links`,method:`GET`,skipBodyParse:!0}),Rs=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`link-graph`});return}try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`docName`);if(g&&!isSafeDocName(g)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`link-graph`});return}let S=s.searchParams.get(`degrees`);if(S&&!g){errorResponse(t,400,`urn:ok:error:invalid-request`,`docName is required when degrees is provided.`,{handler:`link-graph`});return}let w,E;if(S&&g){let e=Number.parseInt(S,10);if(!Number.isFinite(e)||e<0){errorResponse(t,400,`urn:ok:error:invalid-request`,`degrees must be a non-negative integer.`,{handler:`link-graph`});return}({nodes:w,links:E}=ce.getLinkGraphNeighborhood(g,e))}else ({nodes:w,links:E}=ce.getLinkGraph());let D=$t();successResponse(t,200,LinkGraphSuccessSchema,{nodes:w.map(e=>{if(e.kind===`doc`){let t=It(e.docName,D);return{id:e.id,kind:`doc`,docName:e.docName,anchor:e.anchor??null,label:jt(e.docName,D),cluster:t.cluster??null,category:t.category??null,tags:t.tags??null}}return{id:e.id,kind:`external`,url:e.url,label:e.label??e.url}}),links:E},{handler:`link-graph`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read link graph.`,{handler:`link-graph`,cause:e})}},{handler:`link-graph`,method:`GET`,skipBodyParse:!0}),$s=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`orphans`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`mode`)??`both`;if(!isOrphanMode(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid orphan mode. Allowed values: incoming, outgoing, both.`,{handler:`orphans`});return}successResponse(t,200,OrphansSuccessSchema,{orphans:ce.getOrphans([...w().keys()],s).map(e=>({docName:e,title:Dt(e)}))},{handler:`orphans`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read orphan pages.`,{handler:`orphans`,cause:e})}},{handler:`orphans`,method:`GET`,skipBodyParse:!0}),ec=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`hubs`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`limit`),g=s?Number.parseInt(s,10):20,S=Number.isFinite(g)&&g>0?g:20,w=$t();successResponse(t,200,HubsSuccessSchema,{hubs:ce.getHubs(S).map(e=>({docName:e.docName,title:jt(e.docName,w),count:e.count}))},{handler:`hubs`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read hub pages.`,{handler:`hubs`,cause:e})}},{handler:`hubs`,method:`GET`,skipBodyParse:!0}),tc=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`dead-links`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.getAll(`sourceDocName`);if(s.some(e=>e.length===0||!isSafeDocName(e))){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid sourceDocName.`,{handler:`dead-links`});return}let g=s.length?[...new Set(s.map(e=>Rt(e)))]:void 0;successResponse(t,200,DeadLinksSuccessSchema,{deadLinks:ce.getDeadLinks($t(),g).map(e=>({target:e.target,sources:e.sources.map(e=>({source:e.source,title:Dt(e.source),snippet:e.snippet}))}))},{handler:`dead-links`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read dead links.`,{handler:`dead-links`,cause:e})}},{handler:`dead-links`,method:`GET`,skipBodyParse:!0}),nc=withValidation(AgentPatchRequestSchema,async(S,w,E)=>{try{let{find:S,replace:D,offset:O}=E,k=requireNonEmptyDocName(E.docName,w,`agent-patch`);if(k===null)return;let j=Rt(k),{agentId:F,agentName:L,colorSeed:B,clientName:H,clientVersion:q,label:ee}=Ui(E);if(findLooksLikeFrontmatter(S)){agentPatchFmTouchCounter().add(1,{result:`rejected`}),errorResponse(w,400,`urn:ok:error:frontmatter-edit-not-supported`,`Frontmatter edits are not supported via a body find/replace. Use edit({ document: { path, frontmatter } }) to change frontmatter, or write({ document: { path, content, position: "replace" } }) to rewrite the whole document including its YAML block.`,{handler:`agent-patch`});return}if(isSystemDoc(j)||isConfigDoc(j)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${j}' is a reserved document name.`,{handler:`agent-patch`});return}let J=normalizeSummary(E.summary),Y=await s.getSession(j,F,{displayName:L,colorSeed:B,clientName:H}),te=reconcileDiskBeforeAgentWrite(t,j,g,e.resolveEmbed),ne=new Date().toISOString(),ae=!1,oe=!1,se=!1,ce;try{let t=iconFromClientName(H),s=AGENT_ICON_COLORS[t]??colorFromSeed(B??F);if(me?.setPresence(F,{displayName:L,icon:t,color:s,currentDoc:j,mode:`writing`,ts:Date.now()}),captureEffect(Y.dc.document.getText(`source`),F,B,H),Y.dc.document.transact(()=>{let{frontmatter:t,body:s}=stripFrontmatter(Y.dc.document.getText(`source`).toString()),g=prependFrontmatter(t,s),w=O==null?g.indexOf(S):g.slice(O,O+S.length)===S?O:-1;if(w===-1){O==null?ae=!0:oe=!0,console.warn(JSON.stringify({event:`agent-patch-find-mismatch`,"doc.name":j,findLength:S.length,replaceLength:D.length,hadOffset:O!=null})),incrementAgentPatchFindMismatches();return}if(w<t.length){se=!0;return}let{body:E}=stripFrontmatter(g.slice(0,w)+D+g.slice(w+S.length));ce=applyAgentMarkdownWrite(Y.dc.document,E,`patch`,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:j}:void 0),Y.dc.document.getMap(`agent-flash`).set(F,{agentId:F,timestamp:Date.now(),type:`insert`,description:`Patched (${L}): ${S.slice(0,50)}`})},Y.origin),ce!==void 0&&console.warn(JSON.stringify({event:`agent-write-content-divergence`,"doc.name":j,position:`patch`,intendedBytes:ce.intendedBytes,actualBytes:ce.actualBytes,byteDelta:ce.byteDelta,"agent.id":F,"agent.client_name":H})),!ae&&!oe&&!se){let{stored:e}=Ki(J);recordContributor(j,F,L,B,void 0,Gi({clientName:H,clientVersion:q,label:ee}),e),incrementAgentWriteCalls(),Xi(J),recordContentDivergenceGate(`agent-patch`,ce)}}finally{me?.touchMode(F,`idle`)}if(oe){errorResponse(w,409,`urn:ok:error:stale-target`,`Target text no longer matches at the requested offset.`,{handler:`agent-patch`});return}if(ae){errorResponse(w,404,`urn:ok:error:target-not-found`,`Text not found in document.`,{handler:`agent-patch`});return}if(se){agentPatchFmTouchCounter().add(1,{result:`rejected`}),errorResponse(w,400,`urn:ok:error:frontmatter-edit-not-supported`,`Frontmatter edits are not supported via a body find/replace. Use edit({ document: { path, frontmatter } }) to change frontmatter, or write({ document: { path, content, position: "replace" } }) to rewrite the whole document including its YAML block.`,{handler:`agent-patch`});return}let ue=await Ht(j);if(ue?.kind===`failure`){Ut(w,ue.failure,`agent-patch`);return}if(ue?.kind===`divergence`){Wt(w,`agent-patch`);return}Vt(j,`agent-patch`),fe?.setFocus(F,{agentName:L,currentDoc:j,writeKind:`edit`,ts:Date.now()}),ge?.();let de=zt(j),_e=Bt();_e===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(H)});let{response:ve}=Ki(J),ye=await validateMermaidFences(Y.dc.document.getText(`source`).toString(),j),Ce=Kt(te),we=ce===void 0?void 0:toContentDivergenceWarning(ce),Te=[...we?[we]:[],...Ce?[Ce]:[],...ye??[]];successResponse(w,200,AgentPatchSuccessSchema,{timestamp:ne,subscriberCount:de,systemSubscriberCount:_e,...ve?{summary:ve}:{},...we?{warning:we}:Ce?{warning:Ce}:{},...Te.length>0?{warnings:Te}:{}},{handler:`agent-patch`})}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(w,e,`agent-patch`);return}if(e instanceof FrontmatterMalformedError){respondFrontmatterMalformed(w,e,`agent-patch`);return}if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-patch`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$6.error({err:e},`[agent-patch] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-patch`,cause:e})}},{handler:`agent-patch`,method:`POST`}),rc=withValidation(AgentUndoRequestSchema,async(t,g,S)=>{try{let t=requireNonEmptyDocName(S.docName,g,`agent-undo`);if(t===null)return;let w=Rt(t),{agentId:E,agentName:D,colorSeed:O,clientName:k,clientVersion:j,label:F}=Ui(S);if(isSystemDoc(w)||isConfigDoc(w)){errorResponse(g,400,`urn:ok:error:reserved-doc-name`,`'${w}' is a reserved document name.`,{handler:`agent-undo`});return}let{connectionId:L}=S,B=S.scope===`session`||S.scope===`file`?`session`:`last`;if(!s.hasSession(w,L)){errorResponse(g,404,`urn:ok:error:no-active-session`,`No active session for this connectionId and docName.`,{handler:`agent-undo`});return}let H=await s.getSession(w,L),q=!1;try{let t=iconFromClientName(k),s=AGENT_ICON_COLORS[t]??colorFromSeed(O??E);me?.setPresence(E,{displayName:D,icon:t,color:s,currentDoc:w,mode:`writing`,ts:Date.now()}),q=applyAgentUndo(H,B,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:w}:void 0),q&&recordContributor(w,L,D,O,void 0,Gi({clientName:k,clientVersion:j,label:F}))}finally{me?.touchMode(E,`idle`)}if(q){let e=await Ht(w);if(e?.kind===`failure`){Ut(g,e.failure,`agent-undo`);return}if(e?.kind===`divergence`){Wt(g,`agent-undo`);return}Vt(w,`agent-undo`)}fe?.setFocus(L,{agentName:L,currentDoc:w,writeKind:`undo`,ts:Date.now()}),successResponse(g,200,AgentUndoSuccessSchema,{docName:w,scope:B,undone:q},{handler:`agent-undo`})}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(g,e,`agent-undo`);return}log$6.error({err:e},`[agent-undo] handler failed`),errorResponse(g,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-undo`,cause:e})}},{handler:`agent-undo`,method:`POST`}),ic=withValidation(EmptyRequestSchema,async(e,t)=>{try{let g=validateAgentId(new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`agentId`));if(g===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`agentId required (alphanumeric/_/- only).`,{handler:`agent-activity`});return}successResponse(t,200,AgentActivitySuccessSchema,listAgentActivity(s,g),{handler:`agent-activity`})}catch(e){log$6.error({err:e},`[agent-activity] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-activity`,cause:e})}},{handler:`agent-activity`,method:`GET`,skipBodyParse:!0}),ac=withValidation(EmptyRequestSchema,async(e,t)=>{try{let g=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=validateAgentId(g.searchParams.get(`agentId`)),w=g.searchParams.get(`docName`),E=g.searchParams.get(`stackIndex`);if(S===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`agentId required (alphanumeric/_/- only).`,{handler:`agent-burst-diff`});return}if(!w||w.trim()===``){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`agent-burst-diff`});return}if(!isSafeDocName(w)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`agent-burst-diff`});return}let D=Rt(w);if(isSystemDoc(D)||isConfigDoc(D)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${D}' is a reserved document name.`,{handler:`agent-burst-diff`});return}if(!E||Number.isNaN(Number(E))){errorResponse(t,400,`urn:ok:error:invalid-request`,`StackIndex must be a number.`,{handler:`agent-burst-diff`});return}let O=Number(E);if(!Number.isInteger(O)||O<0){errorResponse(t,400,`urn:ok:error:invalid-request`,`stackIndex must be a non-negative integer.`,{handler:`agent-burst-diff`});return}let k=s.getLiveSession(D,S);if(!k){errorResponse(t,404,`urn:ok:error:no-active-session`,`No active session for this agentId and docName.`,{handler:`agent-burst-diff`});return}let j=k.um;if(O>=j.undoStack.length){errorResponse(t,404,`urn:ok:error:not-found`,`stackIndex ${O} out of range (stack has ${j.undoStack.length} items).`,{handler:`agent-burst-diff`});return}let F=j.undoStack[O];successResponse(t,200,AgentBurstDiffSuccessSchema,{diff:synthesizeStackItemDiffText(F,k.dc.document.getText(`source`),D),generatedAt:Date.now()},{handler:`agent-burst-diff`})}catch(e){log$6.error({err:e},`[agent-burst-diff] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-burst-diff`,cause:e})}},{handler:`agent-burst-diff`,method:`GET`,skipBodyParse:!0}),oc=withValidation(EmptyRequestSchema,async(e,t)=>{try{await ee?.(),successResponse(t,200,TestFlushGitSuccessSchema,{},{handler:`test-flush-git`})}catch(e){log$6.error({err:e},`[test-flush-git] flush failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-flush-git`,cause:e})}},{handler:`test-flush-git`,method:`POST`,skipBodyParse:!0}),sc=withValidation(EmptyRequestSchema,async(e,S)=>{try{let w=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),E=Rt(w.searchParams.get(`docName`)??`test-doc`),D;try{D=safeContentPath(E,g)}catch(e){log$6.error({err:e,docName:E},`[test-reset] safeContentPath rejected docName`),errorResponse(S,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`test-reset`,cause:e});return}await s.closeAll(E),t.closeConnections(E);let O=`onStoreDocument-${E}`;t.debouncer.isDebounced(O)&&await t.debouncer.executeNow(O);let k=t.documents.get(E);if(k&&await(je??t.unloadDocument.bind(t))(k),writeFileSync(D,``,`utf-8`),ce&&(ce.deleteDocument(E),ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist cache after test-reset for ${E}:`,e)}),de?.(`backlinks`),de?.(`graph`)),w.searchParams.get(`reset-okignore`)!==`false`)try{let e=resolve(g,`.okignore`),s=t.documents.get(CONFIG_DOC_NAME_OKIGNORE);if(s){let e=s.getText(`source`);e.length>0&&s.transact(()=>{e.delete(0,e.length)},CONFIG_VALIDATION_REVERT_ORIGIN)}existsSync(e)&&writeFileSync(e,``,`utf-8`),Te&&await Te.rebuildIgnorePatterns()}catch(e){console.warn(`[test-reset] okignore reset partial failure:`,e)}de?.(`files`),successResponse(S,200,TestResetSuccessSchema,{},{handler:`test-reset`})}catch(e){errorResponse(S,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-reset`,cause:e})}},{handler:`test-reset`,method:`POST`,skipBodyParse:!0}),cc=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`test-rescan-backlinks`});return}await ce.rebuildFromDisk(),await ce.ingestGlobalSkillBundles([resolve(Ql,`.ok`,`skills`)]),ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist cache after test-rescan-backlinks:`,e)}),de?.(`backlinks`),de?.(`graph`),successResponse(t,200,TestRescanBacklinksSuccessSchema,{},{handler:`test-rescan-backlinks`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-rescan-backlinks`,cause:e})}},{handler:`test-rescan-backlinks`,method:`POST`,skipBodyParse:!0}),lc=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!B){errorResponse(t,503,`urn:ok:error:file-rescan-not-configured`,`Watcher rescan capability is not configured.`,{handler:`test-rescan-files`});return}await B(),de?.(`files`),successResponse(t,200,TestRescanFilesSuccessSchema,{},{handler:`test-rescan-files`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-rescan-files`,cause:e})}},{handler:`test-rescan-files`,method:`POST`,skipBodyParse:!0}),uc=withValidation(SaveVersionRequestSchema,async(e,t,s)=>{try{let{rawAgentId:e,agentId:g,agentName:S,clientName:w}=Ui(s),E=q?.current;if(!E){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`save-version`});return}let D=/^[a-zA-Z0-9_-]+$/,O=[],k=!1;if(Array.isArray(s.writers))try{O=s.writers.map(e=>{let t=e.id??`unknown`;if(!D.test(t))throw Error(`Invalid writer id: ${t}`);return{id:t,name:(e.name??`unknown`).replace(/[\r\n]/g,``),email:(e.email??`noreply@openknowledge.local`).replace(/[\r\n]/g,``)}})}catch(e){errorResponse(t,400,`urn:ok:error:invalid-request`,e instanceof Error?e.message:`Invalid writer id.`,{handler:`save-version`,cause:e});return}let j=ae?.()??`main`;if(O.length===0)if(e!==void 0)O=[{id:g,name:w?`${S} (${w})`:S,email:`${g}@openknowledge.local`}];else{let e=(await enumerateWipChains(E,j)).filter(e=>!e.isPark);O=e.length>0?e.map(e=>({id:e.writerId,name:e.writerId,email:`${e.writerId}@openknowledge.local`})):[SERVICE_WRITER],k=!0}let F=se??`.`,L=normalizeSummary(typeof s.summary==`string`?s.summary:void 0),B=await saveVersion(E,F,O,j,L.kind===`value`?L.value:void 0,k?{includeUpstream:!1}:void 0);getLogger(`history`).info({checkpointRef:B.checkpointRef},`checkpoint`);try{await gcRenameLog(E,getOrLoadRenameLogIndex(E.gitDir))}catch(e){console.warn(`[rename-log] post-saveVersion GC failed:`,e)}successResponse(t,200,SaveVersionSuccessSchema,{checkpointRef:B.checkpointRef},{handler:`save-version`})}catch(e){log$6.error({err:e},`[save-version] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`save-version`,cause:e})}},{handler:`save-version`,method:`POST`}),dc=withValidation(EmptyRequestSchema,async(e,t)=>{let s=q?.current;if(!s){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`history`});return}let g=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=g.searchParams.get(`docName`)??``,w=g.searchParams.get(`folder`),E=g.searchParams.get(`branch`)??ae?.()??`main`;if(!S&&w===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`A docName or folder query parameter is required.`,{handler:`history`});return}if(E.includes(`..`)||!/^[a-zA-Z0-9][a-zA-Z0-9._/-]*$/.test(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid branch name.`,{handler:`history`});return}if(w!==null&&!S){let e=jl(w,t,`folder`,`history`);if(!e)return;let S=Number(g.searchParams.get(`limit`)??`50`),D=Math.min(200,Number.isFinite(S)?S:50),O=Number(g.searchParams.get(`offset`)??`0`),k=Math.max(0,Number.isFinite(O)?O:0),j=`folder\0${E}\0${e.folderRel}\0${D}\0${k}`,{promise:F,coalesced:L}=Ke.run(j,()=>getFolderTimeline(s,e.folderRel,se??`.`,{branch:E,limit:D,offset:k}));L&&recordTimelineCoalesced(`folder`),successResponse(t,200,HistorySuccessSchema,{...await F},{handler:`history`});return}let D=se??`.`,O=safeDocPath(S,D);if(`error`in O){errorResponse(t,400,`urn:ok:error:invalid-request`,O.error,{handler:`history`});return}let k=Number(g.searchParams.get(`limit`)??`50`),j=Number(g.searchParams.get(`offset`)??`0`),F=Math.min(200,Number.isFinite(k)?k:50),L=Number.isFinite(j)?j:0,B=g.searchParams.get(`type`)??void 0,H=g.searchParams.get(`author`)??void 0,ee=g.searchParams.get(`excludeAuthor`)??void 0,J=g.searchParams.get(`includeAutoCheckpoints`)===`true`,Y=`doc\0${E}\0${S}\0${F}\0${L}\0${B??``}\0${H??``}\0${ee??``}\0${J?`1`:`0`}`,te=Date.now();try{let{promise:e,coalesced:g}=Ke.run(Y,()=>getDocumentHistory(s,{docName:S,branch:E,limit:F,offset:L,type:B,author:H,excludeAuthor:ee,includeAutoCheckpoints:J},D));g&&recordTimelineCoalesced(`doc`);let w=await e,O=Date.now()-te;getLogger(`timeline`).info({docName:S,entries:w.entries.length,durationMs:O},`query`),successResponse(t,200,HistorySuccessSchema,{...w},{handler:`history`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read history.`,{handler:`history`,cause:e})}},{handler:`history`,method:`GET`,skipBodyParse:!0});async function fc(e,t,s){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`history-version`,extraHeaders:{Allow:`GET`}});return}let g=q?.current;if(!g){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`history-version`});return}let S=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`docName`)??``,w=se??`.`,E=safeDocPath(S,w);if(`error`in E){errorResponse(t,400,`urn:ok:error:invalid-request`,E.error,{handler:`history-version`});return}let D=shadowGit(g),O=ae?.()??`main`;if(!/^[0-9a-f]{40}$/i.test(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid commit SHA.`,{handler:`history-version`});return}try{let e=await resolveDocPathAtCommit(g,S,s,O,getOrLoadRenameLogIndex(g.gitDir),e=>{let t=safeDocPath(e,w);return`error`in t?`${e}.md`:t.path},createAncestorShaSetCache());if(e===null){errorResponse(t,404,`urn:ok:error:doc-not-found`,`Document did not exist at this version.`,{handler:`history-version`});return}let E=await D.raw(`show`,`${s}:${e}`),[k=``,j=``]=(await D.raw(`log`,`-1`,`--format=%aI%x00%an`,s)).trim().split(`\0`);successResponse(t,200,HistoryVersionSuccessSchema,{sha:s,content:E,timestamp:k,author:j},{handler:`history-version`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`history-version`,cause:e})}}let pc=withValidation(RollbackRequestSchema,async(s,g,S)=>{let w=extractActorIdentity(S,Ce);if(w.kind===`invalid-summary`){errorResponse(g,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`rollback`});return}let E=t.documents.get(S.docName);if(E&&isDocInConflict(E)){respondDocInConflict(g,new DocInConflictError({file:`${S.docName}${getDocExtension(S.docName)}`}),`rollback`);return}let D=q?.current;if(!D){errorResponse(g,503,`urn:ok:error:rollback-not-configured`,`Shadow repo not configured.`,{handler:`rollback`});return}let{docName:O,commitSha:k}=S,j=se??`.`,F=safeDocPath(O,j);if(`error`in F){errorResponse(g,400,`urn:ok:error:invalid-request`,F.error,{handler:`rollback`});return}let L=shadowGit(D),B=Date.now();try{let s=getOrLoadRenameLogIndex(D.gitDir),S=createAncestorShaSetCache(),E=await resolveDocPathAtCommit(D,O,k,ae?.()??`main`,s,e=>{let t=safeDocPath(e,j);return`error`in t?`${e}.md`:t.path},S);if(E===null){errorResponse(g,404,`urn:ok:error:doc-not-found`,`Commit ${k.slice(0,7)} does not contain document ${O} at any known historical path.`,{handler:`rollback`});return}let F=await L.raw(`show`,`${k}:${E}`),H=new Date().toISOString();await safetyCheckpoint(D,j,{action:`rollback`,context:{docName:O,targetSha:k}});let q=t.documents.get(O);if(!q){errorResponse(g,409,`urn:ok:error:doc-not-open`,`Document is not currently open — open it in the editor first.`,{handler:`rollback`});return}let ee=e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:O}:void 0,J;q.transact(()=>{replaceRawBody(q,F,ee),J=evaluateContentDivergence(q.getText(`source`).toString(),F,`rollback`)},ROLLBACK_ORIGIN),J!==void 0&&console.warn(JSON.stringify({event:`agent-write-content-divergence`,"doc.name":O,position:`rollback`,intendedBytes:J.intendedBytes,actualBytes:J.actualBytes,byteDelta:J.byteDelta,"actor.kind":w.kind,...w.kind===`agent`||w.kind===`principal`?{"actor.writer_id":w.writerId}:{}})),recordContentDivergenceGate(`rollback`,J);let Y;switch(w.kind){case`agent`:{let e=k.slice(0,8),t=w.summary.kind===`value`,s=t?w.summary:normalizeSummary(`Restored to ${e}`),g=Ki(s);Y=t||!g.response?g.response:Yi(g.response),recordContributor(O,w.writerId,w.displayName,w.colorSeed,formatRollbackSubject(O,k),w.actor,g.stored),incrementAgentWriteCalls(),Xi(s,!t);break}case`principal`:{let e=Ki(w.summary);Y=e.response,recordContributor(O,w.writerId,w.displayName,w.colorSeed,formatRollbackSubject(O,k),w.actor,e.stored),Xi(w.summary,!1);break}case`anonymous`:log$6.debug({docName:O,commitSha:k.slice(0,8)},`[rollback] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`);break;default:throw Error(`Unhandled actor kind in handleRollback: ${String(w.kind)}`)}renameAttributionCounter().add(1,{kind:`rollback`,attribution_kind:w.kind});let te=await Ht(O);if(te?.kind===`failure`){Ut(g,te.failure,`rollback`);return}if(te?.kind===`divergence`){Wt(g,`rollback`);return}Vt(O,`rollback`);let ne=Date.now()-B;getLogger(`rollback`).info({docName:O,from:k.slice(0,8),durationMs:ne},`rollback`),w.kind===`agent`&&fe?.setFocus(w.writerId,{agentName:w.displayName,currentDoc:O,writeKind:`rollback-apply`,ts:Date.now()});let oe=J===void 0?void 0:toContentDivergenceWarning(J);successResponse(g,200,RollbackSuccessSchema,{restoredFrom:k,timestamp:H,...Y?{summary:Y}:{},...oe?{warning:oe,warnings:[oe]}:{}},{handler:`rollback`})}catch(e){errorResponse(g,500,`urn:ok:error:internal-server-error`,`Failed to roll back.`,{handler:`rollback`,cause:e})}},{handler:`rollback`,method:`POST`}),mc=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,MetricsReconciliationSuccessSchema,getMetrics(),{handler:`metrics-reconciliation`})}catch(e){log$6.error({err:e},`[metrics-reconciliation] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-reconciliation`,cause:e})}},{handler:`metrics-reconciliation`,method:`GET`,skipBodyParse:!0}),hc=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,MetricsParseHealthSuccessSchema,getParseHealth(),{handler:`metrics-parse-health`})}catch(e){log$6.error({err:e},`[metrics-parse-health] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-parse-health`,cause:e})}},{handler:`metrics-parse-health`,method:`GET`,skipBodyParse:!0}),gc=withValidation(EmptyRequestSchema,async(e,t)=>{try{Me&&await Me.catch(e=>{log$6.warn({err:e,handler:`server-info`},`[api] ready gate rejected — responding with current state`)});let e=getActiveBranch(),s=oe?.();successResponse(t,200,ServerInfoSuccessSchema,{serverInstanceId:S,currentBranch:e,...s===void 0?{}:{currentDiskAckSVs:s}},{handler:`server-info`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`server-info`,cause:e})}},{handler:`server-info`,method:`GET`,skipBodyParse:!0});async function _c(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`principal`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`principal`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`principal`,extraHeaders:{Allow:`GET`}});return}let s=Ce?.()??null;if(!s){errorResponse(t,404,`urn:ok:error:principal-not-available`,`Principal not available.`,{handler:`principal`});return}successResponse(t,200,PrincipalSuccessSchema,s,{handler:`principal`})}async function vc(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`metrics-agent-presence`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`metrics-agent-presence`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`metrics-agent-presence`,extraHeaders:{Allow:`GET`}});return}try{let e=me?.getPresenceMap()??{},s=Date.now(),g={};for(let[t,S]of Object.entries(e))s-S.ts<2e4&&(g[t]=S);successResponse(t,200,MetricsAgentPresenceSuccessSchema,{presence:g},{handler:`metrics-agent-presence`})}catch(e){log$6.error({err:e},`[metrics-agent-presence] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-agent-presence`,cause:e})}}async function yc(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`embed-detect`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`embed-detect`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`embed-detect`,extraHeaders:{Allow:`GET`}});return}let s=embedProbeRing.read();successResponse(t,200,EmbedDetectSuccessSchema,{entries:s,count:s.length,detection:deriveDetection(s[0])},{handler:`embed-detect`})}async function bc(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`workspace`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`workspace`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`workspace`,extraHeaders:{Allow:`GET`}});return}let s=resolve(g),S=s,w=!0;try{S=realpathSync(s)}catch(e){let g=e?.code;if(g===`ENOENT`)console.warn(`[workspace] contentDir does not exist; returning unresolved path`,{path:s}),w=!1;else{console.warn(`[workspace] realpath failed for contentDir`,{path:s,err:e}),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Workspace realpath failed.`,{handler:`workspace`,detail:g??void 0,cause:e});return}}successResponse(t,200,WorkspaceSuccessSchema,{contentDir:S,pathSeparator:sep,symlinkResolved:w},{handler:`workspace`})}let xc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`path`);if(!s||s.includes(`\0`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing asset path.`,{handler:`asset`});return}let S=assetContentTypeForPath(s),w=extname(s).slice(1).toLowerCase();if(!S||!ASSET_EXTENSIONS.has(w)){errorResponse(t,415,`urn:ok:error:unsupported-asset-type`,`Unsupported asset type.`,{handler:`asset`});return}let E=realpathSync(g),D=resolve(E,s),O;try{O=realpathSync(D)}catch{errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}if(!isWithinContentDir(O,E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset`});return}let k;try{k=statSync(O)}catch{errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}if(!k.isFile()){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}let j=toContentRelativePath(E,O);if(j!==s.split(`\\`).join(`/`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset`});return}if(Te?.isPathIgnored(j)){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}let F=SANDBOXED_HTML_EXTENSIONS.has(w),L={"Content-Type":S,"Content-Length":String(k.size),"X-Content-Type-Options":`nosniff`,"Content-Disposition":INLINE_RENDERABLE_EXTENSIONS.has(w)||F?`inline`:`attachment`,"Cache-Control":`no-store`};w===`svg`?L[`Content-Security-Policy`]=`sandbox; default-src 'none'; style-src 'unsafe-inline'`:F&&(L[`Content-Security-Policy`]=SANDBOXED_HTML_CSP),t.writeHead(200,L);try{await pipeline(createReadStream(O),t)}catch(e){log$6.error({event:`api.asset.pipeline-failed`,handler:`asset`,assetPath:s,err:e},`[asset] pipeline failed mid-stream`),t.destroyed||t.destroy(e instanceof Error?e:void 0)}}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`asset`,cause:e})}},{handler:`asset`,method:`GET`,skipBodyParse:!0}),Sc=1048576,Cc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`path`);if(!s||s.includes(`\0`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing asset path.`,{handler:`asset-text`});return}let S=realpathSync(g),w=resolve(S,s),E;try{E=realpathSync(w)}catch(e){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset-text`,cause:e});return}if(!isWithinContentDir(E,S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset-text`});return}let D;try{D=statSync(E)}catch(e){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset-text`,cause:e});return}if(!D.isFile()){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset-text`});return}if(toContentRelativePath(S,E)!==s.split(`\\`).join(`/`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset-text`});return}if(D.size>Sc){errorResponse(t,413,`urn:ok:error:payload-too-large`,`File exceeds the ${Sc}-byte text-viewer cap.`,{handler:`asset-text`});return}let O=(await readFile$1(E)).toString(`utf-8`);t.writeHead(200,{"Content-Type":`text/plain; charset=utf-8`,"X-Content-Type-Options":`nosniff`,"Content-Disposition":`inline`,"Cache-Control":`no-store`}),t.end(O)}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`asset-text`,cause:e})}},{handler:`asset-text`,method:`GET`,skipBodyParse:!0}),wc=1440*60*1e3,Tc=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!q?.current){successResponse(t,200,RescueListSuccessSchema,[],{handler:`rescue-list`});return}let e=Date.now(),s=[],g=resolve(q.current.gitDir,`rescue`);if(existsSync(g))try{let t=readdirSync(g).filter(e=>isSupportedDocFile(e));for(let S of t){let t=resolve(g,S),w=statSync(t);if(e-w.mtimeMs>864e5){try{unlinkSync(t)}catch(e){console.debug(`[rescue] cleanup failed (non-critical):`,e)}continue}s.push({docName:stripDocExtension(S),timestamp:w.mtime.toISOString(),size:w.size,source:`flat`})}}catch(e){log$6.error({err:e},`[rescue] Failed to list flat-file rescue buffers`)}try{let e=ae?.()??`main`,t=await listRescueCheckpoints(q.current,e);for(let e of t)s.push({...e,source:`timeline`})}catch(e){log$6.error({err:e},`[rescue] Failed to list timeline-ref rescue checkpoints`)}successResponse(t,200,RescueListSuccessSchema,s,{handler:`rescue-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`rescue-list`,cause:e})}},{handler:`rescue-list`,method:`GET`,skipBodyParse:!0}),Ec=withValidation(CreatePageRequestSchema,async(e,t,s)=>{try{let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`create-page`});return}let S=s.path;if(!isSupportedDocFile(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must end with .md or .mdx.`,{handler:`create-page`});return}if(S.includes(`..`)||S.startsWith(`/`)||S.includes(`\0`)||S.includes(`\\`)){errorResponse(t,400,`urn:ok:error:path-escape`,`Invalid path.`,{handler:`create-page`,detail:`path must not contain .. or start with /`});return}let w=resolve(g),E=resolve(w,S);if(!isWithinDir(E,w)){errorResponse(t,400,`urn:ok:error:path-escape`,`path must not escape content directory.`,{handler:`create-page`});return}let O=stripDocExtension(S);if(isSystemDoc(O)||isConfigDoc(O)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${O}' is a reserved document name.`,{handler:`create-page`});return}if(S.split(`/`)[0]===`.ok`||isManagedArtifactDocName(O)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${O}' is a reserved document name.`,{handler:`create-page`,detail:`Cannot create a page under .ok/ — skills and templates are authored through their own validating flows.`});return}let k=typeof s.template==`string`?s.template.trim():``,j=``,F;if(k.length>0){if(!/^[A-Za-z0-9_-]+$/.test(k)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Template name must match [A-Za-z0-9_-]+.`,{handler:`create-page`});return}let s=S.includes(`/`)?S.slice(0,S.lastIndexOf(`/`)):``,g=resolveTemplatesAvailable(w,s),E=g.find(e=>e.name===k);if(!E){let e=g.length===0?`(none)`:g.map(e=>`"${e.name}" (${e.scope})`).join(`, `);errorResponse(t,400,`urn:ok:error:invalid-request`,`Template "${k}" does not resolve for folder "${s||`(root)`}". Available: ${e}`,{handler:`create-page`});return}let D=resolve(w,E.path),O;try{O=readFileSync(D,`utf-8`)}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template at ${E.path}.`,{handler:`create-page`,cause:e});return}let L=instantiateDoc(O),B=e.kind===`agent`||e.kind===`principal`?e.displayName??``:``;j=applySubstitution(L,{date:todayIsoUtc(),user:B}),F=E.scope}mkdirSync(dirname(E),{recursive:!0});try{writeFileSync(E,j,{encoding:`utf-8`,flag:`wx`})}catch(e){if(isAlreadyExistsError(e)){errorResponse(t,409,`urn:ok:error:doc-already-exists`,`File already exists.`,{handler:`create-page`,cause:e});return}throw e}let L=stripDocExtension(S);switch(Pe?.delete(L),Te&&Te.incrementMdDir(dirname(L)),registerWrite(E,contentHash(j)),e.kind){case`agent`:case`principal`:recordContributor(L,e.writerId,e.displayName,e.colorSeed,void 0,e.actor);break;case`anonymous`:break;default:throw Error(`Unhandled actor kind in handleCreatePage: ${String(e.kind)}`)}D?.({kind:`create`,path:E,docName:L,content:j}),ce&&(ce.updateDocumentFromMarkdown(L,j),ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist create-page cache for ${L}:`,e)}),de?.(`backlinks`),de?.(`graph`)),de?.(`files`),F!==void 0&&console.warn(JSON.stringify({event:`template-instantiate`,templateName:k,templateScope:F,docName:L})),successResponse(t,200,CreatePageSuccessSchema,{docName:L},{handler:`create-page`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to create page.`,{handler:`create-page`,cause:e})}},{handler:`create-page`,method:`POST`}),Dc=withValidation(CreateFolderRequestSchema,async(e,t,s)=>{try{if(extractActorIdentity(s,Ce).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`create-folder`});return}let e=s.path;if(!isValidRelativeContentPath(e)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`create-folder`});return}if(e===`.ok`||e.startsWith(`.ok/`)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'.ok' is a reserved directory.`,{handler:`create-folder`});return}if(Te?.isDirExcluded(e)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Destination folder is excluded by the workspace content config.`,{handler:`create-folder`});return}let S=resolveContentEntryPath(g,`folder`,e);if(existsSync(S)){errorResponse(t,409,`urn:ok:error:doc-already-exists`,`Folder already exists.`,{handler:`create-folder`});return}tracedMkdirSync(S,{recursive:!0}),rt(e),de?.(`files`),successResponse(t,200,CreateFolderSuccessSchema,{path:e},{handler:`create-folder`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to create folder.`,{handler:`create-folder`,cause:e})}},{handler:`create-folder`,method:`POST`}),Oc=withValidation(DuplicatePathRequestSchema,async(e,s,S)=>{try{let e=extractActorIdentity(S,Ce);if(e.kind===`invalid-summary`){errorResponse(s,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`duplicate-path`});return}let{kind:w}=S,E=w===`file`?stripDocExtension(S.path):S.path;if(!isValidRelativeContentPath(E)){errorResponse(s,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`duplicate-path`});return}if(E===`.ok`||E.startsWith(`.ok/`)||w===`file`&&(isSystemDoc(E)||isConfigDoc(E))||w===`folder`&&isReservedSyntheticFolderPath(E)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`Reserved paths cannot be duplicated.`,{handler:`duplicate-path`});return}w===`file`&&probeAndRegisterSourceFileExtension(g,E);let O=resolveContentEntryPath(g,w,E);if(!existsSync(O)){if(w===`file`){let e=resolveContentEntryPath(g,`folder`,E);if(existsSync(e)&&statSync(e).isDirectory()){errorResponse(s,400,`urn:ok:error:invalid-request`,`Target path is not a ${w}.`,{handler:`duplicate-path`});return}}errorResponse(s,404,`urn:ok:error:doc-not-found`,`${w} does not exist.`,{handler:`duplicate-path`});return}let k=statSync(O);if(w===`file`&&!k.isFile()||w===`folder`&&!k.isDirectory()){errorResponse(s,400,`urn:ok:error:invalid-request`,`Target path is not a ${w}.`,{handler:`duplicate-path`});return}let j=w===`file`?[E]:Xr(resolveContentEntryPath(g,`folder`,E)),F=_e?.(),L=new Set(F?F.getConflicts().map(e=>e.file):[]);for(let e of j){let g=stripDocExtension(e),S=t.documents.get(g),w=`${g}${getDocExtension(g)}`,E=S!==void 0&&isDocInConflict(S),D=L.has(w);if(E||D){respondDocInConflict(s,new DocInConflictError({file:w}),`duplicate-path`);return}}let B,H=[];if(w===`file`){let e=extname(O);if(B=nextAvailableDuplicateDocName(g,E).docName,isSystemDoc(B)||isConfigDoc(B)||Te?.isExcluded(`${B}${e}`)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Duplicated document destination is excluded by the project content config.`,{handler:`duplicate-path`});return}let t=resolveDuplicateDocPath(g,B,e),S=readFileSync(O,`utf-8`),w=dirname(t),k=existsSync(w);try{tracedMkdirSync(w,{recursive:!0}),tracedWriteFileSync(t,S,{encoding:`utf-8`,flag:`wx`})}catch(e){if(isAlreadyExistsError(e)){errorResponse(s,409,`urn:ok:error:doc-already-exists`,`A file at the duplicate destination already exists.`,{handler:`duplicate-path`,cause:e});return}if(!k)try{tracedRmdirSync(w)}catch(e){let t=e.code;t!==`ENOENT`&&t!==`ENOTEMPTY`&&console.warn(`[duplicate-path] failed to clean duplicate parent directory:`,{destinationDir:w,err:e})}throw e}let j=!1;try{registerDocExtension(B,e),Pe?.delete(B),Te&&(Te.incrementMdDir(dirname(B)),j=!0),registerWrite(t,contentHash(S)),D?.({kind:`create`,path:t,docName:B,content:S}),ce?.updateDocumentFromMarkdown(B,S),H=[B]}catch(e){try{tracedRmSync(t,{force:!0})}catch(e){console.warn(`[duplicate-path] failed to clean partial file duplicate:`,{destinationPath:t,err:e})}throw forgetDocExtension(B),Te&&j&&Te.decrementMdDir(dirname(B)),D?.({kind:`delete`,path:t,docName:B}),e}}else{if(B=nextAvailableDuplicateFolderPath(g,E).folderPath,Te?.isDirExcluded(B)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Duplicated folder destination is excluded by the project content config.`,{handler:`duplicate-path`});return}let e=resolveContentEntryPath(g,`folder`,B);try{tracedCpSync(O,e,{recursive:!0,errorOnExist:!0,force:!1})}catch(e){if(isAlreadyExistsError(e)){errorResponse(s,409,`urn:ok:error:doc-already-exists`,`A folder at the duplicate destination already exists.`,{handler:`duplicate-path`,cause:e});return}throw e}try{for(let e of collectFolderPaths(g,B))rt(e);let e=collectMarkdownCopies(g,B);H=e.map(e=>e.docName);for(let t of e){let e=extname(t.fullPath);registerDocExtension(t.docName,e),Pe?.delete(t.docName),Te&&Te.incrementMdDir(dirname(t.docName)),registerWrite(t.fullPath,contentHash(t.content)),D?.({kind:`create`,path:t.fullPath,docName:t.docName,content:t.content}),ce?.updateDocumentFromMarkdown(t.docName,t.content)}}catch(t){try{tracedRmSync(e,{recursive:!0,force:!0})}catch(t){console.warn(`[duplicate-path] failed to clean partial folder duplicate:`,{destinationPath:e,err:t})}throw t}}switch(e.kind){case`agent`:case`principal`:for(let t of H)recordContributor(t,e.writerId,e.displayName,e.colorSeed,void 0,e.actor);break;case`anonymous`:break;default:throw Error(`Unhandled actor kind in handleDuplicatePath: ${String(e.kind)}`)}ce&&H.length>0&&(ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist duplicate-path cache:`,e)}),de?.(`backlinks`),de?.(`graph`)),de?.(`files`),successResponse(s,200,DuplicatePathSuccessSchema,{kind:w,path:B,duplicatedDocNames:H},{handler:`duplicate-path`})}catch(e){if(e instanceof DuplicateNameExhaustedError){errorResponse(s,409,`urn:ok:error:doc-already-exists`,`All available duplicate name slots are occupied for this path.`,{handler:`duplicate-path`,cause:e});return}let t=classifyDuplicatePathFilesystemProblem(e);if(t){errorResponse(s,t.status,t.type,t.title,{handler:`duplicate-path`,cause:e});return}errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to duplicate path.`,{handler:`duplicate-path`,cause:e})}},{handler:`duplicate-path`,method:`POST`}),kc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!s||s.length===0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName query parameter.`,{handler:`page-headings`});return}if(!isSafeDocName(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`page-headings`});return}let g=Et(s);if(!g){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`page-headings`});return}if(!existsSync(g)){errorResponse(t,404,`urn:ok:error:doc-not-found`,`Page not found.`,{handler:`page-headings`});return}successResponse(t,200,PageHeadingsSuccessSchema,{docName:s,headings:extractHeadings(readFileSync(g,`utf-8`))},{handler:`page-headings`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read headings.`,{handler:`page-headings`,cause:e})}},{handler:`page-headings`,method:`GET`,skipBodyParse:!0}),Ac=withValidation(RenamePathRequestSchema,async(e,s,S)=>{try{let e=extractActorIdentity(S,Ce);if(e.kind===`invalid-summary`){errorResponse(s,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`rename-path`});return}let{kind:w,fromPath:E,toPath:D}=S;if(!isValidRelativeContentPath(E)||!isValidRelativeContentPath(D)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Paths must be relative content paths.`,{handler:`rename-path`});return}if(w===`file`&&(isSystemDoc(E)||isSystemDoc(D)||isConfigDoc(E)||isConfigDoc(D))){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`Reserved document names cannot be renamed.`,{handler:`rename-path`});return}if(E===`.ok`||E.startsWith(`.ok/`)||D===`.ok`||D.startsWith(`.ok/`)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`.ok is a reserved directory.`,{handler:`rename-path`});return}if(E===D){successResponse(s,200,RenamePathSuccessSchema,{renamed:[],renamedAssets:[],rewrittenDocs:[]},{handler:`rename-path`});return}let O=w===`asset`&&isSupportedDocFile(E)&&isSupportedDocFile(D)?`file`:w;if(O===`asset`){let t;try{t=isSupportedDocFile(E)&&!isSupportedDocFile(D)?await ji(E,D):await Qr(E,D)}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(s,e,`rename-path`);return}let{status:t,type:g,error:S}=Fr(e);errorResponse(s,t,g,S,{handler:`rename-path`,cause:e});return}t.renamedAssets.length>0&&vt();let g;if(t.renamedAssets.length>0&&t.rewrittenDocs.length>0){let s=`Renamed asset ${E} → ${D}`;g=Zi(e,s,t.rewrittenDocs.map(({docName:e})=>({docName:e,subject:s})),{context:`handleRenamePath asset branch`,onAnonymous:()=>{log$6.debug({kind:`asset`,fromPath:E,toPath:D,affectedDocs:t.rewrittenDocs.length,affectedAssets:t.renamedAssets.length},`[rename-path] anonymous actor; no contributor recorded (no agentId in body and getPrincipal() returned null)`)}})}if(renameAttributionCounter().add(1,{kind:`rename-asset`,attribution_kind:e.kind}),J)try{await J()}catch(e){console.warn(`[rename-path] flushContributors failed after asset rename (commitSha backfill may be deferred):`,e)}successResponse(s,200,RenamePathSuccessSchema,{renamed:[],renamedAssets:t.renamedAssets,rewrittenDocs:t.rewrittenDocs,...g?{summary:g}:{}},{handler:`rename-path`});return}let k=O===`file`?[stripDocExtension(E)]:Xr(resolveContentEntryPath(g,`folder`,E)),j=_e?.(),F=new Set(j?j.getConflicts().map(e=>e.file):[]);for(let e of k){let g=stripDocExtension(e),S=t.documents.get(g),w=O===`file`?E:`${g}${getDocExtension(e)}`,D=S!==void 0&&isDocInConflict(S),k=F.has(w);if(D||k){respondDocInConflict(s,new DocInConflictError({file:w}),`rename-path`);return}}if(O===`file`&&probeAndRegisterSourceFileExtension(g,E),Te&&(O===`file`?Te.isExcluded(isSupportedDocFile(D)?D:`${D}${getDocExtension(E)}`):Te.isDirExcluded(D))){errorResponse(s,400,`urn:ok:error:invalid-request`,`Destination ${O===`file`?`document`:`folder`} is excluded by the project content config.`,{handler:`rename-path`});return}let L=e.kind===`agent`||e.kind===`principal`?{writerId:e.writerId,displayName:e.displayName,colorSeed:e.colorSeed,actorMetadata:e.actor}:void 0,B;try{B=await Hi(E,D,O,L?{actor:L}:{})}catch(e){if(e instanceof ManagedRenameCollisionError){errorResponse(s,409,`urn:ok:error:doc-already-exists`,Mr(e.message),{handler:`rename-path`,extensions:{colliding:e.colliding},cause:e});return}throw e}if(B.renamed.length===0&&B.renamedAssets.length===0){successResponse(s,200,RenamePathSuccessSchema,{renamed:[],renamedAssets:[],rewrittenDocs:[]},{handler:`rename-path`});return}B.renamedAssets.length>0&&vt();let H,q=B.renamed.filter(({fromDocName:e,toDocName:t})=>e!==t);if(q.length>0&&(H=Zi(e,`Renamed ${E} → ${D}`,q.map(({fromDocName:e,toDocName:t})=>({docName:t,subject:formatRenameSubject(e,t)})),{context:`handleRenamePath`,onAnonymous:()=>{log$6.debug({kind:w,fromPath:E,toPath:D,affectedDocs:B.renamed.length},`[rename-path] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`)}})),renameAttributionCounter().add(1,{kind:`rename-${O}`,attribution_kind:e.kind}),J)try{await J()}catch(e){console.warn(`[rename-path] flushContributors failed (commitSha backfill may be deferred):`,e)}successResponse(s,200,RenamePathSuccessSchema,{renamed:B.renamed,renamedAssets:B.renamedAssets,rewrittenDocs:B.rewrittenDocs,...H?{summary:H}:{}},{handler:`rename-path`})}catch(e){let{status:t,type:g,error:S}=Fr(e);errorResponse(s,t,g,S,{handler:`rename-path`,cause:e})}},{handler:`rename-path`,method:`POST`}),jc=withValidation(DeletePathRequestSchema,async(e,s,S)=>{try{Ui(S);let{kind:e,path:w}=S;if(!isValidRelativeContentPath(w)){errorResponse(s,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`delete-path`});return}let E=e===`asset`?Yr(w):{path:w,ambiguous:!1};if(E.ambiguous){errorResponse(s,400,`urn:ok:error:invalid-request`,`Asset path without an extension matches multiple files.`,{handler:`delete-path`});return}let O=E.path,k=e===`asset`&&isSupportedDocFile(O)?`file`:e;if(k===`file`&&probeAndRegisterSourceFileExtension(g,O),k===`asset`&&isReservedProjectStatePath(O)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`.ok and .git are reserved directories.`,{handler:`delete-path`});return}let j=k===`asset`?resolveContentEntryPath(g,`folder`,O):resolveContentEntryPath(g,k,O);if(!existsSync(j)){errorResponse(s,404,`urn:ok:error:doc-not-found`,`${k} does not exist.`,{handler:`delete-path`});return}let F=statSync(j);if(k===`file`&&!F.isFile()||k===`asset`&&!F.isFile()||k===`folder`&&!F.isDirectory()){errorResponse(s,400,`urn:ok:error:invalid-request`,`Target path is not a ${k}.`,{handler:`delete-path`});return}let L=k===`asset`?[]:k===`file`?[stripDocExtension(O)]:Xr(resolveContentEntryPath(g,`folder`,O)),B=_e?.(),H=new Set(B?B.getConflicts().map(e=>e.file):[]);for(let e of L){let g=stripDocExtension(e),S=t.documents.get(g),w=k===`file`&&isSupportedDocFile(O)?O:`${g}${getDocExtension(g)}`,E=S!==void 0&&isDocInConflict(S),D=H.has(w);if(E||D){respondDocInConflict(s,new DocInConflictError({file:w}),`delete-path`);return}}if(await Ir(L),Pe)for(let e of L)isSystemDoc(e)||isConfigDoc(e)||(Pe.setDeleted(e),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:e,kind:`deleted`,source:`handleDeletePath`})));k===`file`||k===`asset`?tracedUnlinkSync(j):(tracedRmSync(j,{recursive:!0,force:!1}),it(O)),vt();for(let e of L)D?.({kind:`delete`,path:resolve(g,`${e}${getDocExtension(e)}`),docName:e});de?.(`files`),successResponse(s,200,DeletePathSuccessSchema,{deletedDocNames:L},{handler:`delete-path`})}catch(e){errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to delete path.`,{handler:`delete-path`,cause:e})}},{handler:`delete-path`,method:`POST`}),Mc=withValidation(TrashCleanupRequestSchema,async(e,t,s)=>withSpan(`ok.fs.trash_cleanup`,{attributes:{"ok.cleanup.kind":s.kind,"ok.cleanup.path":normalizeFsPath(s.path),"ok.cleanup.path.role":classifyFsPath(s.path)}},async()=>{try{if(extractActorIdentity(s,Ce).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`trash-cleanup`});return}let{kind:e,path:S}=s;if(!isValidRelativeContentPath(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`trash-cleanup`});return}let E=e===`asset`&&isSupportedDocFile(S)?`file`:e,O=stripDocExtension(S);E===`file`&&probeAndRegisterSourceFileExtension(g,S);let k=E===`folder`&&isReservedSyntheticFolderPath(S),j=E===`asset`&&isReservedProjectStatePath(S);if(E===`file`&&(isSystemDoc(O)||isConfigDoc(O))||k||j){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${S}' is a reserved document name.`,{handler:`trash-cleanup`});return}if(E===`asset`){vt(),de?.(`files`),successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:[]},{handler:`trash-cleanup`});return}let F=w(),L=E===`file`?F.has(O)?[O]:[]:listAffectedDocNames(F,E,S);if(vt(),L.length===0){successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:[]},{handler:`trash-cleanup`});return}if(await Ir(L),Pe)for(let e of L)isSystemDoc(e)||isConfigDoc(e)||(Pe.setDeleted(e),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:e,kind:`deleted`,source:`handleTrashCleanup`})));for(let e of L)D?.({kind:`delete`,path:resolve(g,`${e}${getDocExtension(e)}`),docName:e});E===`folder`&&it(S),de?.(`files`),successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:L},{handler:`trash-cleanup`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to clean up after trash.`,{handler:`trash-cleanup`,cause:e})}}),{handler:`trash-cleanup`,method:`POST`}),Nc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=w(),s=[];for(let[t,S]of e){let e=t,w,E=getDocExtension(t);try{let s=readFileSync(resolve(g,`${t}${E}`),`utf-8`);e=extractPageTitle(s,t),w=extractPageIcon(s)}catch(e){console.warn(`[pages] Failed to read title for ${t}:`,e)}s.push({docName:t,title:e,docExt:E,size:S.size,modified:S.modified,icon:w})}s.sort((e,t)=>e.docName.localeCompare(t.docName)),successResponse(t,200,PagesSuccessSchema,{pages:s},{handler:`pages`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list pages.`,{handler:`pages`,cause:e})}},{handler:`pages`,method:`GET`,skipBodyParse:!0}),Pc=withValidation(EmptyRequestSchema,async(e,s)=>{try{let g=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!g){errorResponse(s,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`suggest-links`});return}if(!isSafeDocName(g)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`suggest-links`});return}if(isSystemDoc(g)||isConfigDoc(g)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`'${g}' is a reserved document name.`,{handler:`suggest-links`});return}successResponse(s,200,SuggestLinksSuccessSchema,await suggestLinks({hocuspocus:t,fileIndex:w(),docName:g}),{handler:`suggest-links`})}catch(e){if(e instanceof SuggestLinksTargetNotFoundError){errorResponse(s,404,`urn:ok:error:doc-not-found`,`Page not found.`,{handler:`suggest-links`,cause:e});return}errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to suggest links.`,{handler:`suggest-links`,cause:e})}},{handler:`suggest-links`,method:`GET`,skipBodyParse:!0});async function Fc(e,t){if(e.method!==`POST`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`upload-asset`,extraHeaders:{Allow:`POST`}});return}let s;try{s=await readUploadBody(e,ye??g)}catch(e){if(e instanceof UploadWriteError){errorResponse(t,uploadStatusFor(e.reason),e.reason,uploadTitleFor(e.reason),{handler:`upload-asset`,cause:e});return}errorResponse(t,400,`urn:ok:error:malformed-upload`,`Failed to parse upload.`,{handler:`upload-asset`,cause:e});return}let{filename:S,tempPath:w,sha:E,byteLength:D,parentDocName:O}=s,k=()=>{if(existsSync(w))try{unlinkSync(w)}catch{}},j=validateBody(UploadRequestSchema,{parentDocName:O},t,{handler:`upload-asset`});if(!j.ok){k();return}let{parentDocName:F}=j.value,{agentId:L,agentName:B}=Ui(Object.fromEntries(new URL(e.url??``,`http://localhost`).searchParams.entries()));if(D===0){k(),errorResponse(t,400,`urn:ok:error:no-file-received`,`No file received.`,{handler:`upload-asset`});return}if(F.includes(`\0`)||F.includes(`..`)||F.startsWith(`/`)){k(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}let H=resolve(g),q=resolveUploadDestDir(F,`./`,H);if(!isWithinContentDir(q,H)){k(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}try{assertNoSymlinkEscape(q,H)}catch(e){if(k(),(e instanceof Error?e.message:String(e)).startsWith(`symlink-escape:`)){errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}log$6.error({err:e,destDir:q},`[upload] failed to validate destination directory`),errorResponse(t,500,`urn:ok:error:storage-error`,`Storage error.`,{handler:`upload-asset`,cause:e});return}try{mkdirSync(q,{recursive:!0})}catch(e){if(!isAlreadyExistsError(e)){k();let s=classifyUploadErrno(e);errorResponse(t,uploadStatusFor(s),s,uploadTitleFor(s),{handler:`upload-asset`,cause:e,detail:`failed to create attachment directory`});return}}try{let e=realpathSync(q),s;try{s=realpathSync(H)}catch{s=H}if(!isWithinContentDir(e,s)){k(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}}catch(e){if(e.code!==`ENOENT`){k(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`,cause:e});return}}let ee=await fileTypeFromFile(w),J=ee?.mime,Y=ee?.ext;if(!J){let e=readTempFileHead(w,256).toString(`utf-8`).replace(/^/,``).trimStart();(e.startsWith(`<svg`)||e.startsWith(`<?xml`)&&e.includes(`<svg`))&&(J=`image/svg+xml`,Y=`svg`)}{let s=await findDuplicateAsset(q,E,D);if(s){k();let S=toPosix(relative(g,resolve(q,s)));log$6.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:L,agentName:B,dedup:!0,mime:J??null,size:D,destPath:S,httpStatus:200},`[upload] dedup hit`),successResponse(t,200,UploadAssetSuccessSchema,{src:s,path:S,deduped:!0},{handler:`upload-asset`});return}}let te;if(!S||S===`upload`||GENERIC_PASTE_NAMES.test(S)){let e=new Date().toISOString().replace(/[-:T]/g,``).slice(0,14).replace(/(\d{8})(\d{6})/,`$1-$2`),t=S?extname(S).slice(1):``,s=Y??t??``;te=s===``?`pasted-${e}`:`pasted-${e}.${s}`}else te=sanitizeFilename(S);try{let s=linkTempToFinalWithCollisionRetry(w,q,te),S=toPosix(relative(g,resolve(q,s)));log$6.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:L,agentName:B,dedup:!1,mime:J??null,size:D,destPath:S,httpStatus:200},`[upload] write ok`),successResponse(t,200,UploadAssetSuccessSchema,{src:s,path:S,deduped:!1},{handler:`upload-asset`})}catch(s){let g=s instanceof UploadWriteError?s.reason:`urn:ok:error:storage-error`;log$6.error({event:`upload`,endpoint:e.url??`/api/upload`,agentId:L,agentName:B,filename:te,size:D,reason:g,httpStatus:uploadStatusFor(g),err:s},`[upload] write failed`),errorResponse(t,uploadStatusFor(g),g,uploadTitleFor(g),{handler:`upload-asset`,cause:s})}}let Ic=`/api/local-op/clone`,Lc=`/api/local-op/ok-init`,Rc=600*1e3,zc=45e3,Bc=`local-op-clone`,Vc=withValidation(LocalOpCloneRequestSchema,Hc,{handler:Bc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Bc})});async function Hc(e,t,s){let{url:g,dir:S,branch:w}=s;if(!isAllowedGitUrl(g)){errorResponse(t,400,`urn:ok:error:url-not-allowed`,`URL protocol is not allowed for clone.`,{handler:Bc,cause:Error(`url=${g}`)});return}if(!isSafeLocalPath(S)){errorResponse(t,400,`urn:ok:error:dir-outside-home`,`Clone destination must be within the user home directory.`,{handler:Bc,cause:Error(`dir=${S}`)});return}if(!We.tryAcquire(Ic)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A clone operation is already in progress.`,{handler:Bc,extraHeaders:{"Retry-After":`30`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let E=createStreamingErrorWriter(t,Bc),D=null,O=runCloneSubprocess({cliArgs:ve,url:g,dir:S,branch:w,timeoutMs:Rc,onEvent:e=>{if(e.type===`complete`){D=e.dir;return}if(e.type===`error`){e.message&&log$6.warn({stderr:redactShareSubprocessStderr(e.message),url:g,dir:S},`[local-op/clone] clone failed`);let t=classifyCloneError(e.message??``);E(500,`urn:ok:error:clone-failed`,t.title,{detail:t.detail||void 0,cause:e.message?Error(redactShareSubprocessStderr(e.message)):void 0});return}if(!t.writableEnded&&!t.destroyed)try{t.write(`${JSON.stringify(e)}\n`)}catch{}}});(async()=>{try{if(await O.done,D&&!t.writableEnded&&!t.destroyed){let e=await Uc(D);!t.writableEnded&&!t.destroyed&&(`port`in e?t.write(`${JSON.stringify({type:`complete`,port:e.port,dir:D})}\n`):E(500,`urn:ok:error:server-start-failed`,`Cloned successfully but failed to start the project server.`,{cause:Error(e.error)}))}}catch(e){!t.writableEnded&&!t.destroyed?E(500,`urn:ok:error:internal-server-error`,`Unexpected error during clone post-processing.`,{cause:e}):log$6.error({err:e,handler:Bc},`clone IIFE rejected after stream ended`)}finally{t.writableEnded||t.end(),We.release(Ic)}})(),t.on(`close`,()=>{O.cancel()})}async function Uc(e,t){let s=resolve(expandTilde(e)),g=getLocalDir(s),S=readUiLock(g);if(S&&S.port>0)return{port:S.port};let[w,...E]=ve,D=e=>{let s=t===void 0?[]:e===`ui`?[`--port`,String(t)]:[`--ui-port`,String(t)];return[...E,e,...s]},O=async e=>{let t=spawn(w,D(e),{cwd:s,detached:!0,stdio:[`ignore`,`ignore`,`pipe`],env:{...process.env,OK_LOCK_KIND:`interactive`}}),S=[];t.stderr?.on(`data`,t=>{S.push(t),log$6.warn({cwd:s,cliCmd:e,msg:t.toString(`utf-8`).trim()},`[local-op/clone] child stderr`)});let E=null,O=null,k=null;t.on(`exit`,(e,t)=>{E=e??-1,O=t??null}),t.on(`error`,t=>{k=t.message,E=-1,log$6.error({cwd:s,cliCmd:e,err:t.message},`[local-op/clone] failed to spawn child`)}),t.unref();let j=Date.now()+45e3;for(;Date.now()<j;){await setTimeout$1(500);let t=readUiLock(g);if(t&&t.port>0)return{port:t.port};if(E!==null){let t=Buffer.concat(S).toString(`utf-8`).trim();return{error:`\`ok ${e}\` exited (${k?`spawn failed: ${k}`:O?`killed by ${O}`:`code ${E}`})${t?` — ${t}`:``}`,exited:!0}}}let F=Buffer.concat(S).toString(`utf-8`).trim();return{error:`UI did not start within the expected time${F?` — ${F}`:``}`,exited:!1}},k=readServerLock(g),j=k&&k.port>0?`ui`:`start`,F=await O(j);if(j===`start`&&`error`in F&&F.exited){let e=readServerLock(g);if(e&&e.port>0){let e=await O(`ui`);return`port`in e?e:{error:`${F.error}; connect fallback failed: ${e.error}`}}}return`port`in F?F:{error:F.error}}let Wc=`local-op-ok-init`,Gc=withValidation(LocalOpOkInitRequestSchema,async(e,t,s)=>{let{projectPath:g}=s;if(!isAbsolute(g)){errorResponse(t,400,`urn:ok:error:invalid-request`,`projectPath must be an absolute path.`,{handler:Wc,cause:Error(`projectPath=${g}`)});return}let S;try{S=realpathSync(g)}catch(e){successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!1,reason:`not-a-git-worktree`,message:`projectPath does not exist or is not accessible: ${e.message}`},{handler:Wc});return}if(!isSafeLocalPath(S)){errorResponse(t,400,`urn:ok:error:dir-outside-home`,`projectPath must be within the user home directory.`,{handler:Wc,cause:Error(`projectPath=${g}`)});return}let w=resolveGitDirDetailed(S).kind;if(w!==`directory`&&w!==`linked`){console.warn(`[ok-init] action=init project=${basename(S)} result=not-a-git-worktree kind=${w}`),successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!1,reason:`not-a-git-worktree`,message:`projectPath is not a git working tree (.git is ${w}).`},{handler:Wc});return}if(isProjectRoot(S)){console.warn(`[ok-init] action=init project=${basename(S)} result=already-initialized`),successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!0,projectPath:S},{handler:Wc});return}if(!We.tryAcquire(Lc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An ok-init operation is already in progress.`,{handler:Wc,extraHeaders:{"Retry-After":`2`}});return}try{await withParentLock(async()=>{initContent(S)}),console.warn(`[ok-init] action=init project=${basename(S)} result=success`),successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!0,projectPath:S},{handler:Wc})}catch(e){let s=e instanceof Error?e.message:String(e);console.warn(`[ok-init] action=init project=${basename(S)} result=failed reason=${s}`),successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!1,reason:`init-failed`,message:s},{handler:Wc})}finally{We.release(Lc)}},{handler:Wc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Wc})}),Kc=`/api/local-op/auth/login`,qc=`/api/local-op/auth/status`,Jc=`/api/local-op/auth/repos`,Yc=`/api/local-op/auth/signout`,Xc=null,Zc=`local-op-auth-login`,Qc=withValidation(LocalOpAuthHostRequestSchema,$c,{handler:Zc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Zc})});async function $c(e,t,s){let g=s.host??`github.com`;if(!We.tryAcquire(Kc)){let e=Xc;if(!e){console.error(JSON.stringify({event:`ok-local-op:auth-login-slot-no-controller`,channel:`auth`,transport:`http`})),errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth login operation is already in progress.`,{handler:Zc,extraHeaders:{"Retry-After":`5`}});return}e.cancel(),Xc=null,console.warn(JSON.stringify({event:`ok-local-op:idempotent-start-replaced-stale-slot`,channel:`auth`,transport:`http`}))}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let S=createStreamingErrorWriter(t,Zc),w=runDeviceFlowSubprocess({cliArgs:ve,host:g,timeoutMs:Rc,onEvent:e=>{if(e.type===`error`){S(500,`urn:ok:error:auth-failed`,`Auth subprocess reported an error.`,{cause:e.message?Error(e.message):void 0});return}if(resumeSyncOnAuthEvent(e,_e),!t.writableEnded&&!t.destroyed)try{t.write(`${JSON.stringify(e)}\n`)}catch{}}});Xc=w;let E=()=>{w.cancel(),Xc===w&&(Xc=null,We.release(Kc))};t.on(`close`,E),w.done.finally(()=>{if(t.off(`close`,E),!t.writableEnded&&!t.destroyed)try{t.end()}catch{}Xc===w&&(Xc=null,We.release(Kc))})}let nl=`local-op-auth-status`,il=withValidation(LocalOpAuthHostRequestSchema,async(e,t,s)=>{let g=s.host??`github.com`;if(!We.tryAcquire(qc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth status operation is already in progress.`,{handler:nl,extraHeaders:{"Retry-After":`5`}});return}try{let[e,...s]=ve,S=[...s,`auth`,`status`,`--json`,`--host`,g],w=(await new Promise((t,s)=>{let g=spawn(e,S,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),w=!1,E=setTimeout(()=>{w=!0,g.kill(`SIGTERM`)},3e4),D=[];g.stdout.on(`data`,e=>D.push(e)),g.on(`close`,()=>{if(clearTimeout(E),w){s(Error(`auth status subprocess timed out after 30s`));return}t(Buffer.concat(D).toString(`utf-8`))}),g.on(`error`,e=>{clearTimeout(E),s(e)})})).split(`
1937
- `).map(e=>e.trim()).filter(Boolean),E=null;for(let e=w.length-1;e>=0;e--)try{E=JSON.parse(w[e]);break}catch{}E===null?successResponse(t,200,LocalOpAuthStatusSuccessSchema,{authenticated:!1},{handler:nl}):successResponse(t,200,LocalOpAuthStatusSuccessSchema,E,{handler:nl})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth status check failed.`,{handler:nl,cause:e})}finally{We.release(qc)}},{handler:nl,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:nl})}),al=`local-op-auth-repos`,cl=withValidation(LocalOpAuthHostRequestSchema,ll,{handler:al,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:al})});async function ll(e,t,s){let g=s.host??`github.com`;if(!We.tryAcquire(Jc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth repos operation is already in progress.`,{handler:al,extraHeaders:{"Retry-After":`5`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let S=createStreamingErrorWriter(t,al),[w,...E]=ve,D=[...E,`auth`,`repos`,`--json`,`--host`,g],O=!1,k=``,j=spawn(w,D,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),F=setTimeout(()=>{j.kill(`SIGTERM`)},Rc);j.stdout.on(`data`,e=>{k+=e.toString(`utf-8`);let s=k.split(`
1938
- `);k=s.pop()??``;for(let e of s){if(!e.trim())continue;let s=null;try{s=JSON.parse(e)}catch{}if(s&&s.type===`error`){S(500,`urn:ok:error:auth-failed`,`Auth repos subprocess reported an error.`,{detail:typeof s.message==`string`?s.message:void 0});continue}if(!t.writableEnded&&!t.destroyed)try{t.write(`${e}\n`)}catch{}}}),j.stderr.on(`data`,e=>{log$6.debug({msg:e.toString(`utf-8`).trim()},`[local-op/auth/repos] stderr`)}),j.on(`close`,e=>{clearTimeout(F),O||(O=!0,e!==0&&!t.writableEnded&&S(500,`urn:ok:error:auth-failed`,`Auth repos subprocess exited with code ${e}.`),t.end(),We.release(Jc))}),j.on(`error`,e=>{clearTimeout(F),O||(O=!0,t.writableEnded||(S(500,`urn:ok:error:auth-failed`,`Failed to spawn the auth repos subprocess.`,{cause:e}),t.end()),We.release(Jc))}),t.on(`close`,()=>{O||(O=!0,clearTimeout(F),j.kill(`SIGTERM`),We.release(Jc))})}let ul=`local-op-auth-signout`,dl=withValidation(LocalOpAuthHostRequestSchema,async(e,t,s)=>{let g=s.host??`github.com`;if(!We.tryAcquire(Yc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth signout operation is already in progress.`,{handler:ul,extraHeaders:{"Retry-After":`5`}});return}try{let[e,...s]=ve,S=[...s,`auth`,`signout`,`--host`,g];await new Promise((t,s)=>{let g=spawn(e,S,{stdio:`ignore`,env:{...process.env}}),w=setTimeout(()=>{g.kill(`SIGTERM`)},3e4);g.on(`close`,()=>{clearTimeout(w),t()}),g.on(`error`,e=>{clearTimeout(w),s(e)})}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:ul})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth signout failed.`,{handler:ul,cause:e})}finally{We.release(Yc)}},{handler:ul,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:ul})}),fl=`/api/local-op/auth/set-identity`,pl=`local-op-auth-set-identity`,ml=withValidation(LocalOpAuthSetIdentityRequestSchema,async(e,t,s)=>{let g=s.name.trim(),S=s.email.trim();if(!ye){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:pl});return}if(!We.tryAcquire(fl)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A set-identity operation is already in progress.`,{handler:pl,extraHeaders:{"Retry-After":`5`}});return}try{writeGitIdentity(ye,g,S),_e?.()?.refreshIdentity().catch(()=>{}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:pl})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Set-identity failed.`,{handler:pl,cause:e})}finally{We.release(fl)}},{handler:pl,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:pl})});async function hl(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-status`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-status`,extraHeaders:{Allow:`GET`}});return}try{let e=_e?.();if(!e){successResponse(t,200,SyncStatusSchema,{state:`dormant`,lastSyncUtc:null,lastFetchUtc:null,lastPushedSha:null,ahead:0,behind:0,consecutiveFailures:0,conflictCount:0,hasRemote:!1,syncEnabled:!1,identityUnresolved:!1,remote:null},{handler:`sync-status`});return}await e.refreshRemote(),successResponse(t,200,SyncStatusSchema,e.getStatus(),{handler:`sync-status`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-status`,cause:e})}}}let gl=withValidation(SyncTriggerRequestSchema,async(e,t,s)=>{let g=_e?.();if(!g){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`});return}let S=s.op??`sync`;successResponse(t,202,SyncTriggerSuccessSchema,{op:S},{handler:`sync-trigger`}),g.trigger(S)},{handler:`sync-trigger`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-trigger`})?_e?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`}),!1):!1});async function _l(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-conflicts`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflicts`,extraHeaders:{Allow:`GET`}});return}try{let e=_e?.();successResponse(t,200,SyncConflictsSuccessSchema,{conflicts:e?e.getConflicts():[]},{handler:`sync-conflicts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-conflicts`,cause:e})}}}let vl=withValidation(SyncResolveConflictRequestSchema,async(e,t,s)=>{let g=_e?.();if(!g){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`});return}let{file:S,strategy:w,content:E}=s;try{await g.resolveConflict(S,w,E),successResponse(t,200,SyncResolveConflictSuccessSchema,{},{handler:`sync-resolve-conflict`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to resolve conflict.`,{handler:`sync-resolve-conflict`,cause:e,detail:e instanceof Error?e.message:void 0})}},{handler:`sync-resolve-conflict`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-resolve-conflict`})?_e?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`}),!1):!1});async function yl(e,s){if(!checkLocalOpSecurity(e,s,{handler:`sync-conflict-content`}))return;if(e.method!==`GET`){errorResponse(s,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflict-content`,extraHeaders:{Allow:`GET`}});return}if(!ye){errorResponse(s,503,`urn:ok:error:project-repo-not-configured`,`Project repo not configured.`,{handler:`sync-conflict-content`});return}let g=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=g.searchParams.get(`file`);if(!S){errorResponse(s,400,`urn:ok:error:invalid-request`,`Missing required query param: file.`,{handler:`sync-conflict-content`});return}if(S.includes(`..`)||S.startsWith(`/`)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Invalid file path.`,{handler:`sync-conflict-content`});return}let w=stripDocExtension(S),E=t.documents.get(w)?.getMap(`lifecycle`).get(`status`)===`conflict`,D=_e?.(),O=D?D.getConflicts().some(e=>e.file===S):!1;if(!E&&!O){errorResponse(s,404,`urn:ok:error:no-conflict-tracked`,`No conflict is tracked for this path.`,{handler:`sync-conflict-content`,extensions:{file:S}});return}let k=g.searchParams.get(`source`),j=esm_default({baseDir:ye,timeout:{block:15e3}});async function F(e){try{return{present:!0,content:await j.raw([`show`,`:${e}:${S}`])}}catch(t){let s=t instanceof Error?t.message:String(t);if(!/pathspec|did not match|exists on disk, but not in|is in the index, but not at stage/i.test(s))throw console.warn(JSON.stringify({event:`showstage-unexpected-error`,stage:e,file:S,detail:s,handler:`sync-conflict-content`})),t;return{present:!1}}}try{let[e,g,w]=await Promise.all([F(1),F(2),F(3)]),E=e.present?e.content:``,D=w.present?w.content:``,O=g.present&&w.present?`both-modified`:!g.present&&w.present?`delete-modify`:g.present&&!w.present?`modify-delete`:`both-modified`,j=g.present?g.content:``,L=null;if(k===`ytext`){let e=stripDocExtension(S),s=t.documents.get(e);if(s){let t=s.getMap(`lifecycle`).get(`status`);if(L=typeof t==`string`&&t.length>0?t:null,O!==`delete-modify`){let t=Ie?Ie(e):null;t!==null&&!ytextHasConflictMarkers(t)?j=t:t!==null&&console.warn(JSON.stringify({event:`ytext-conflict-marker-detected`,"doc.name":e,handler:`sync-conflict-content`}))}}else console.warn(`[conflict-content] doc ${e} not loaded; lifecycleStatus unavailable`)}successResponse(s,200,SyncConflictContentSuccessSchema,{file:S,base:E,ours:j,theirs:D,kind:O,lifecycleStatus:L},{handler:`sync-conflict-content`})}catch(e){errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to read conflict content.`,{handler:`sync-conflict-content`,cause:e})}}async function xl(e,t){if(!checkLocalOpSecurity(e,t,{handler:`seed-plan`}))return;if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-plan`,extraHeaders:{Allow:`GET`}});return}let s=new URL(e.url??`/`,`http://localhost`),S=s.searchParams.get(`rootDir`)??void 0,w=s.searchParams.get(`packId`),E=coercePackId(w);if(w!==null&&w!==``&&E===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-plan`,detail:`Pack id "${w}" is not registered.`});return}try{successResponse(t,200,SeedPlanSuccessSchema,{plan:await planSeed({projectDir:g,rootDir:S,packId:E})},{handler:`seed-plan`})}catch(e){if(e instanceof SeedPrerequisiteError){errorResponse(t,422,`urn:ok:error:seed-prerequisite-missing`,`Seed prerequisite missing.`,{handler:`seed-plan`,cause:e});return}if(e instanceof SeedRootDirError){errorResponse(t,400,`urn:ok:error:seed-invalid-root`,`Invalid seed root directory.`,{handler:`seed-plan`,detail:`The provided root directory is not within the workspace content directory.`,cause:e});return}errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`seed-plan`,cause:e})}}let Cl=withValidation(SeedApplyRequestSchema,async(e,t,s)=>{let S=s.plan;if(!S||typeof S!=`object`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid plan payload.`,{handler:`seed-apply`});return}let w=S,E=s.packId,D=coercePackId(E);if(typeof E==`string`&&E.length>0&&D===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-apply`,detail:`Pack id "${E}" is not registered.`});return}try{successResponse(t,200,SeedApplySuccessSchema,{result:await applySeed(w,{projectDir:g,packId:D})},{handler:`seed-apply`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to apply seed plan.`,{handler:`seed-apply`,cause:e})}},{handler:`seed-apply`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`seed-apply`})});async function Tl(e,t){if(checkLocalOpSecurity(e,t,{handler:`seed-packs`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-packs`,extraHeaders:{Allow:`GET`}});return}successResponse(t,200,SeedListPacksSuccessSchema,{packs:listStarterPacks()},{handler:`seed-packs`})}}let El=withValidation(InstallSkillRequestSchema,async(e,t,s)=>{if(s.out!==void 0&&!isSafeLocalPath(s.out)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Output path must be within home directory.`,{handler:`install-skill`});return}try{successResponse(t,200,InstallSkillSuccessSchema,await buildAndOpenSkill({...s.noOpen===void 0?{}:{noOpen:s.noOpen},...s.out===void 0?{}:{out:s.out}}),{handler:`install-skill`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to install skill.`,{handler:`install-skill`,cause:e})}},{handler:`install-skill`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`install-skill`})});async function Dl(e,t){if(checkLocalOpSecurity(e,t,{handler:`installed-agents`}))try{await handleInstalledAgents(e,t,Tt.probeAll)}catch(e){t.headersSent||(log$6.error({err:e},`[installed-agents] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`installed-agents`,cause:e}))}}let Ol=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ue){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-list`});return}try{successResponse(t,200,TagsListSuccessSchema,{tags:ue.getAllTags()},{handler:`tags-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tags.`,{handler:`tags-list`,cause:e})}},{handler:`tags-list`,method:`GET`,skipBodyParse:!0});async function kl(e,t,s){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`tags-for-name`,extraHeaders:{Allow:`GET`}});return}if(!ue){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-for-name`});return}let g;try{g=decodeURIComponent(s)}catch{errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid tag name encoding.`,{handler:`tags-for-name`});return}if(!g){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing tag name.`,{handler:`tags-for-name`});return}try{let e=ue.getDocsForTagWithMatches(g).map(({docName:e,matchingTags:t})=>({docName:e,title:Dt(e),matchingTags:t,snippet:null}));successResponse(t,200,TagsForNameSuccessSchema,{name:g,docs:e},{handler:`tags-for-name`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tag membership.`,{handler:`tags-for-name`,cause:e})}}function jl(e,t,s=`path`,S=`folder-config`){let w=e.replace(/^\.\//,``).replace(/^\/+/,``).replace(/\/+$/,``);if(w.split(`/`).some(e=>e===`..`)||e.startsWith(`/`))return errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid ${s}: must be project-root-relative.`,{handler:S}),null;let E=resolve(g),D=w===``?E:resolve(E,w);return D!==E&&!D.startsWith(`${E}${sep}`)?(errorResponse(t,400,`urn:ok:error:invalid-request`,`Path escapes content directory.`,{handler:S}),null):{folderRel:w,resolvedContentDir:E}}let Ml=/^[A-Za-z0-9_-]+$/;function Pl(e,t,s=`template`){return!e||!Ml.test(e)?(errorResponse(t,400,`urn:ok:error:invalid-request`,"Invalid name: must be letters / digits / `_` / `-` only (no `.md` extension).",{handler:s}),!1):!0}function Fl(e,t,s){let g=t===``?[]:t.split(`/`);for(let t=g.length;t>=0;t--){let S=t===0?``:g.slice(0,t).join(`/`),w=S===``?e:resolve(e,S);if(w!==e&&!w.startsWith(`${e}${sep}`))continue;let E=resolve(w,`.ok`,`templates`,`${s}.md`);if(existsSync(E))return{abs:E,folder:S,scope:t===g.length?`local`:`inherited`}}return null}function Il(e){let t={};if(!e||typeof e!=`object`||Array.isArray(e))return t;for(let[s,g]of Object.entries(e))g!==void 0&&(t[s]=g);return t}async function Ll(e,t){if(e.method===`GET`)return Rl(e,t);if(e.method===`PUT`)return zl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`folder-config`,extraHeaders:{Allow:`GET, PUT`}})}let Rl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=jl(new URL(e.url??``,`http://localhost`).searchParams.get(`path`)??``,t,`path`,`folder-config-get`);if(!s)return;let g=await enrichDirectory(s.folderRel,{projectDir:s.resolvedContentDir}),S=resolve(resolve(s.resolvedContentDir,s.folderRel,`.ok`),`frontmatter.yml`),w=null;if(existsSync(S))try{let e=(0,import_dist$1.parse)(await readFile$1(S,`utf-8`));w=e&&typeof e==`object`&&!Array.isArray(e)?e:{}}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[folder-config:get] malformed YAML in ${S}: ${t}`),w=null}successResponse(t,200,FolderConfigGetSuccessSchema,{folder:g,frontmatter_local:w},{handler:`folder-config-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read folder config.`,{handler:`folder-config-get`,cause:e})}},{handler:`folder-config-get`,method:`GET`,skipBodyParse:!0}),zl=withValidation(FolderConfigPutRequestSchema,async(e,t,s)=>{try{if(Ue){errorResponse(t,403,`urn:ok:error:single-file-mode`,`Folder configuration is not available in single-file mode.`,{handler:`folder-config-put`});return}let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`folder-config-put`});return}let g=jl(s.path,t,`path`,`folder-config-put`);if(!g)return;let S=[];if(s.frontmatter!==void 0){let w=applyFolderFrontmatterPatch({anchorDir:g.resolvedContentDir,folderRel:g.folderRel,patch:s.frontmatter});if(!w.ok){let e=w.error.code===`WRITE_ERROR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to write folder config.`:w.error.message,{handler:`folder-config-put`,detail:w.error.code,cause:Error(w.error.message)});return}S.push({path:w.path,action:w.action}),w.action!==`noop`&&(_s(e,ka(`folder-frontmatter`,g.folderRel),`folder-frontmatter-${w.action===`deleted`?`delete`:`edit`}: ${w.path}`),await xs(`folder-config-put`))}successResponse(t,200,FolderConfigPutSuccessSchema,{applied:S},{handler:`folder-config-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write folder config.`,{handler:`folder-config-put`,cause:e})}},{handler:`folder-config-put`,method:`PUT`});function Bl(e,s,g,S){if(!s)return!1;let w=e===``?`.ok/templates/${s}`:`${e.replace(/\/$/,``)}/.ok/templates/${s}`,E=t.documents.get(w);return E&&isDocInConflict(E)?(respondDocInConflict(S,new DocInConflictError({file:`${w}.md`}),g),!0):!1}function Vl(e,s,g){let S=t.documents.get(e);return S&&isDocInConflict(S)?(respondDocInConflict(g,new DocInConflictError({file:`${e}.md`}),s),!0):!1}let Hl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=resolveProjectTemplates(resolve(g));successResponse(t,200,TemplatesListSuccessSchema,{templates:e.templates.map(e=>{let{scope:t,...s}=e;return s}),truncated:e.truncated},{handler:`templates-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list templates.`,{handler:`templates-list`,cause:e})}},{handler:`templates-list`,method:`GET`,skipBodyParse:!0});async function Ul(e,t){if(e.method===`GET`)return Gl(e,t);if(e.method===`PUT`)return Kl(e,t);if(e.method===`POST`)return Jl(e,t);if(e.method===`DELETE`)return ql(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`template`,extraHeaders:{Allow:`GET, PUT, POST, DELETE`}})}let Wl=e=>{let{frontmatter:t,body:s}=stripFrontmatter(e),g={};if(t!==``)try{let e=(0,import_dist$1.parse)(unwrapFrontmatterFences(t));e&&typeof e==`object`&&!Array.isArray(e)&&(g=e)}catch{}return{frontmatter:g,body:s}},Gl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Pl(g,t,`template-get`))return;let S=jl(s.searchParams.get(`folder`)??``,t,`folder`,`template-get`);if(!S)return;let{folderRel:w,resolvedContentDir:E}=S,D=Fl(E,w,g);if(!D){errorResponse(t,404,`urn:ok:error:template-not-found`,`Template not found.`,{handler:`template-get`,detail:`Template "${g}" not found for folder "${w||`.`}". Walked leaf → root.`});return}let{abs:O,folder:k,scope:j}=D,F=parseTemplateFile(await readFile$1(O,`utf-8`)),L=F.identity,B=F.starterContent;successResponse(t,200,TemplateGetSuccessSchema,{template:{name:g,folder:k,scope:j,path:relative(E,O).split(/[\\/]/).filter(Boolean).join(`/`),frontmatter:L,body:B}},{handler:`template-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template.`,{handler:`template-get`,cause:e})}},{handler:`template-get`,method:`GET`,skipBodyParse:!0}),Kl=withValidation(TemplatePutRequestSchema,async(e,t,g)=>{try{if(Ue){errorResponse(t,403,`urn:ok:error:single-file-mode`,`Templates are not available in single-file mode.`,{handler:`template-put`});return}let e=extractActorIdentity(g,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`template-put`});return}let S=g.name;if(!Pl(S,t,`template-put`))return;let w=jl(g.folder,t,`folder`,`template-put`);if(!w||Bl(w.folderRel,S,`template-put`,t))return;let E=composeTemplateContent({name:S,body:typeof g.body==`string`?g.body:``,frontmatter:Il(g.frontmatter)});if(!E.ok){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid template request.`,{handler:`template-put`,detail:E.error.code,cause:Error(E.error.message)});return}let D=resolve(w.resolvedContentDir,w.folderRel,`.ok`,`templates`,`${S}.md`),O=!existsSync(D),k=relative(w.resolvedContentDir,D).split(/[\\/]/).filter(Boolean).join(`/`),j=eu(w.folderRel,S),{agentId:F,agentName:L,colorSeed:B,clientName:H}=Ui(g),q=await s.getSession(j,F,{displayName:L,colorSeed:B,clientName:H});q.dc.document.transact(()=>{composeAndWriteRawBody(q.dc.document,E.content,`agent`)},q.origin);let ee=await Ht(j);if(ee?.kind===`failure`){Ut(t,ee.failure,`template-put`);return}if(ee?.kind===`divergence`){Wt(t,`template-put`);return}_s(e,ka(`template`,w.folderRel,S),`${O?`template-create`:`template-edit`}: ${k}`),await xs(`template-put`),successResponse(t,200,TemplatePutSuccessSchema,{path:k,created:O,warnings:E.warnings},{handler:`template-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write template.`,{handler:`template-put`,cause:e})}},{handler:`template-put`,method:`PUT`}),ql=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Pl(g,t,`template-delete`))return;let S=jl(s.searchParams.get(`folder`)??``,t,`folder`,`template-delete`);if(!S)return;let w=s.searchParams,E=extractActorIdentity({agentId:w.get(`agentId`)??void 0,agentName:w.get(`agentName`)??void 0,colorSeed:w.get(`colorSeed`)??void 0,clientName:w.get(`clientName`)??void 0,clientVersion:w.get(`clientVersion`)??void 0,label:w.get(`label`)??void 0,summary:w.get(`summary`)??void 0},Ce);if(E.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`template-delete`});return}if(Bl(S.folderRel,g,`template-delete`,t))return;await Ir([eu(S.folderRel,g)]);let D=applyTemplateDelete({projectDir:S.resolvedContentDir,folder:S.folderRel,name:g});if(!D.ok){let e=D.error.code===`WRITE_ERROR`||D.error.code===`UNLINK_FAILED`||D.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete template.`:`Invalid template request.`,{handler:`template-delete`,detail:D.error.code,cause:Error(D.error.message)});return}D.existed&&(_s(E,ka(`template`,S.folderRel,g),`template-delete: ${D.path}`),await xs(`template-delete`)),successResponse(t,200,TemplateDeleteSuccessSchema,{existed:D.existed,path:D.path},{handler:`template-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete template.`,{handler:`template-delete`,cause:e})}},{handler:`template-delete`,method:`DELETE`,skipBodyParse:!0}),Jl=withValidation(TemplateMoveRequestSchema,async(e,t,s)=>{try{let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`template-move`});return}if(!Pl(s.fromName,t,`template-move`)||!Pl(s.toName,t,`template-move`))return;let g=jl(s.fromFolder,t,`folder`,`template-move`);if(!g)return;let S=jl(s.toFolder,t,`folder`,`template-move`);if(!S||Bl(g.folderRel,s.fromName,`template-move`,t))return;await Ir([eu(g.folderRel,s.fromName)]);let w=await applyTemplateMove({projectDir:g.resolvedContentDir,fromFolder:g.folderRel,fromName:s.fromName,toFolder:S.folderRel,toName:s.toName,relocate:async(e,t)=>{let s=await renameTrackedPathInGit(ye,e,t);return s||renamePathOnDisk(e,t),s}});if(!w.ok){if(w.error.code===`TEMPLATE_NOT_FOUND`){let e=Fl(g.resolvedContentDir,g.folderRel,s.fromName);if(e?.scope===`inherited`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Template "${s.fromName}" is inherited from "${e.folder||`(root)`}", not local to "${g.folderRel||`(root)`}". Move it from the folder that owns it, or create a local copy here first (then move that).`,{handler:`template-move`,detail:`TEMPLATE_INHERITED`});return}errorResponse(t,404,`urn:ok:error:template-not-found`,`Template not found.`,{handler:`template-move`,detail:w.error.message});return}if(w.error.code===`TEMPLATE_EXISTS`){errorResponse(t,409,`urn:ok:error:doc-already-exists`,w.error.message,{handler:`template-move`,detail:w.error.code});return}let e=w.error.code===`WRITE_ERROR`||w.error.code===`MOVE_FAILED`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to move template.`:`Invalid template move request.`,{handler:`template-move`,detail:w.error.code,cause:Error(w.error.message)});return}let E=null;if(s.body!==void 0||s.frontmatter!==void 0){let e;if(typeof s.body==`string`)e=s.body;else try{e=instantiateDoc(readFileSync(resolve(S.resolvedContentDir,w.toPath),`utf-8`))}catch{e=null}if(e===null)E={code:`READ_FAILED`,message:`could not read the moved template to apply the metadata change; the move succeeded with the original content intact — retry the edit`};else{let t=applyTemplateWrite({projectDir:S.resolvedContentDir,folder:S.folderRel,name:s.toName,body:e,frontmatter:Il(s.frontmatter)});t.ok||(E=t.error)}}if(_s(e,ka(`template`,S.folderRel,s.toName),`template-rename: ${w.fromPath} -> ${w.toPath}`,[{from:w.fromPath,to:w.toPath}]),await xs(`template-move`),de?.(`files`),E){let e=E.code===`WRITE_ERROR`||E.code===`READ_FAILED`;errorResponse(t,e?500:400,e?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,`Template moved to "${w.toPath}", but updating its content failed.`,{handler:`template-move`,detail:E.code,cause:Error(E.message)});return}successResponse(t,200,TemplateMoveSuccessSchema,{from:w.fromPath,to:w.toPath,committed:w.committed},{handler:`template-move`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to move template.`,{handler:`template-move`,cause:e})}},{handler:`template-move`,method:`POST`}),Yl=500;function Xl(e,t,s){return!e||e.length>64||!SKILL_NAME_REGEX.test(e)?(errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill name: lowercase letters, digits, and hyphens only (≤64 chars; no slashes, dots, spaces, or uppercase).`,{handler:s}),!1):!0}function Zl(e,t,s){let g=SkillScopeSchema.safeParse(e??`project`);return g.success?g.data:(errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill scope (expected "project" or "global").`,{handler:s}),null)}let Ql=we??homedir();function $l(e){return resolve(e===`global`?Ql:g,`.ok`,`skills`)}function eu(e,t){return`${MANAGED_ARTIFACT_PREFIX_TEMPLATE}${[...e?e.split(`/`).filter(Boolean).map(encodeURIComponent):[],encodeURIComponent(t)].join(`/`)}`}function tu(e){return e===`navigation`||e===`relevance`?e:void 0}function nu(e,t){return relative(t===`global`?Ql:g,e).split(/[\\/]/).filter(Boolean).join(`/`)}function ru(e){return e===`global`?Ql:ye}async function iu(e,t){let s=await removeSkillInstall(e,t);return reverseProjectSkill(t,e,PROJECT_SKILL_EDITOR_IDS),s!==null}function au(e,t){let s=[];if(!existsSync(e))return{skills:s,truncated:!1};let g;try{g=readdirSync(e,{withFileTypes:!0})}catch(g){return getLogger(`skills`).warn({err:g,skillsRoot:e,scope:t},`failed to read skills root — returning empty skills list`),{skills:s,truncated:!1}}let S=!1;for(let w of g.sort((e,t)=>e.name.localeCompare(t.name))){if(!w.isDirectory()||!SKILL_NAME_REGEX.test(w.name))continue;if(s.length>=500){S=!0;break}let g=resolve(e,w.name,`SKILL.md`);if(!existsSync(g))continue;let E,D;try{let{frontmatter:e}=Wl(readFileSync(g,`utf-8`));typeof e.description==`string`&&(E=e.description),typeof e.version==`string`&&e.version.trim()!==``&&(D=e.version)}catch{}s.push({name:w.name,...E===void 0?{}:{description:E},scope:t,path:nu(g,t),absolutePath:g,...D===void 0?{}:{installedVersion:D}})}return{skills:s,truncated:S}}let ou=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=au($l(`project`),`project`),s=au($l(`global`),`global`),g=ye?readInstalledSkills(ye).skills:{},S=readInstalledSkills(Ql).skills,w=(e,t)=>e.skills.map(e=>{let s=t[e.name]?.hosts??[],g=computePackUpdateStatus(e.name,e.installedVersion);return{...e,installed:s.length>0,hosts:s,...g}});successResponse(t,200,SkillsListSuccessSchema,{skills:[...w(e,g),...w(s,S)],truncated:e.truncated||s.truncated},{handler:`skills-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list skills.`,{handler:`skills-list`,cause:e})}},{handler:`skills-list`,method:`GET`,skipBodyParse:!0});async function su(e,t){if(e.method===`GET`)return pu(e,t);if(e.method===`PUT`)return mu(e,t);if(e.method===`POST`)return gu(e,t);if(e.method===`DELETE`)return hu(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`skill`,extraHeaders:{Allow:`GET, PUT, POST, DELETE`}})}let cu=object$1({managed:boolean().nullable(),importable:number().int().nonnegative()}),lu=()=>({managed:ye?readSkillManagement(ye)?.manageEditorSkills??null:null,importable:ye?countImportableEditorSkills({projectDir:ye,skillsRoot:$l(`project`)}):0}),uu=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ye){errorResponse(t,400,`urn:ok:error:invalid-request`,`No project root resolved.`,{handler:`skills-management-get`,detail:`NO_PROJECT_ROOT`});return}successResponse(t,200,cu,lu(),{handler:`skills-management-get`})},{handler:`skills-management-get`,method:`GET`,skipBodyParse:!0}),du=withValidation(object$1({manageEditorSkills:boolean()}),async(e,t,s)=>{if(!ye){errorResponse(t,400,`urn:ok:error:invalid-request`,`No project root resolved.`,{handler:`skills-management-put`,detail:`NO_PROJECT_ROOT`});return}if(await writeSkillManagement(ye,{manageEditorSkills:s.manageEditorSkills,surface:`ui`}),s.manageEditorSkills){let e=await reconcileSkillInstalls({projectDir:ye,skillsRoot:$l(`project`)});e.adopted.length+e.collided.length>0&&de?.(`files`)}successResponse(t,200,cu,lu(),{handler:`skills-management-put`})},{handler:`skills-management-put`,method:`PUT`});async function fu(e,t){if(e.method===`GET`)return uu(e,t);if(e.method===`PUT`)return du(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`skills-management`,extraHeaders:{Allow:`GET, PUT`}})}let pu=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Xl(g,t,`skill-get`))return;let S=Zl(s.searchParams.get(`scope`),t,`skill-get`);if(S===null)return;let w=$l(S),E=resolve(w,g,`SKILL.md`);if(!existsSync(E)){errorResponse(t,404,`urn:ok:error:not-found`,`Skill not found.`,{handler:`skill-get`,detail:`Skill "${g}" not found in ${S} scope.`});return}let{frontmatter:D,body:O}=Wl(await readFile$1(E,`utf-8`));successResponse(t,200,SkillGetSuccessSchema,{skill:{name:g,scope:S,path:nu(E,S),frontmatter:{name:typeof D.name==`string`?D.name:g,description:typeof D.description==`string`?D.description:``},body:O,files:readSkillBundledFiles(resolve(w,g))}},{handler:`skill-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill.`,{handler:`skill-get`,cause:e})}},{handler:`skill-get`,method:`GET`,skipBodyParse:!0}),mu=withValidation(SkillPutRequestSchema,async(e,t,g)=>{try{let e=extractActorIdentity(g,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-put`});return}if(!Xl(g.name,t,`skill-put`))return;let S=composeSkillContent({name:g.name,body:typeof g.body==`string`?g.body:``,frontmatter:{name:g.frontmatter.name,description:g.frontmatter.description}});if(!S.ok){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill request.`,{handler:`skill-put`,detail:S.error.code,cause:Error(S.error.message)});return}let w=$l(g.scope),E=resolve(w,g.name,`SKILL.md`),D=!existsSync(E),O=relative(w,E).split(/[\\/]/).filter(Boolean).join(`/`),k=skillLiveDocName(g.scope,g.name);if(Vl(k,`skill-put`,t))return;let{agentId:j,agentName:F,colorSeed:L,clientName:B}=Ui(g),H=await s.getSession(k,j,{displayName:F,colorSeed:L,clientName:B});H.dc.document.transact(()=>{composeAndWriteRawBody(H.dc.document,S.content,`agent`)},H.origin);let q=await Ht(k);if(q?.kind===`failure`){Ut(t,q.failure,`skill-put`);return}if(q?.kind===`divergence`){Wt(t,`skill-put`);return}g.scope===`project`&&(_s(e,ka(`skill`,``,g.name),`${D?`skill-create`:`skill-edit`}: ${O}`),await xs(`skill-put`)),de?.(`files`),successResponse(t,200,SkillPutSuccessSchema,{path:O,created:D,warnings:S.warnings},{handler:`skill-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write skill.`,{handler:`skill-put`,cause:e})}},{handler:`skill-put`,method:`PUT`}),hu=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Xl(g,t,`skill-delete`))return;let S=Zl(s.searchParams.get(`scope`),t,`skill-delete`);if(S===null)return;let w=$l(S),E=s.searchParams,D=extractActorIdentity({agentId:E.get(`agentId`)??void 0,agentName:E.get(`agentName`)??void 0,colorSeed:E.get(`colorSeed`)??void 0,clientName:E.get(`clientName`)??void 0,clientVersion:E.get(`clientVersion`)??void 0,label:E.get(`label`)??void 0,summary:E.get(`summary`)??void 0},Ce);if(D.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-delete`});return}await Ir([skillLiveDocName(S,g)]);let O=applySkillDelete({skillsRoot:w,name:g});if(!O.ok){let e=O.error.code===`UNLINK_FAILED`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete skill.`:`Invalid skill request.`,{handler:`skill-delete`,detail:O.error.code,cause:Error(O.error.message)});return}O.existed&&(S===`project`&&(_s(D,ka(`skill`,``,g),`skill-delete: ${O.path}`),await xs(`skill-delete`)),de?.(`files`));let k=ru(S);k&&await iu(k,g),successResponse(t,200,SkillDeleteSuccessSchema,{existed:O.existed,path:O.path},{handler:`skill-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete skill.`,{handler:`skill-delete`,cause:e})}},{handler:`skill-delete`,method:`DELETE`,skipBodyParse:!0}),gu=withValidation(SkillMoveRequestSchema,async(e,t,s)=>{try{let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-move`});return}if(!Xl(s.fromName,t,`skill-move`)||!Xl(s.toName,t,`skill-move`))return;let g=$l(s.scope);await Ir([skillLiveDocName(s.scope,s.fromName)]);let S=await applySkillMove({skillsRoot:g,fromName:s.fromName,toName:s.toName,relocate:async(e,t)=>{let s=await renameTrackedPathInGit(ye,e,t);return s||renamePathOnDisk(e,t),s}});if(!S.ok){if(S.error.code===`SKILL_NOT_FOUND`){errorResponse(t,404,`urn:ok:error:not-found`,`Skill not found.`,{handler:`skill-move`,detail:S.error.message});return}if(S.error.code===`SKILL_EXISTS`){errorResponse(t,409,`urn:ok:error:doc-already-exists`,S.error.message,{handler:`skill-move`,detail:S.error.code});return}let e=S.error.code===`MOVE_FAILED`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to move skill.`:`Invalid skill move request.`,{handler:`skill-move`,detail:S.error.code,cause:Error(S.error.message)});return}let w=null,E=resolve(g,s.toName,`SKILL.md`),D=``,O=``;try{let e=Wl(readFileSync(E,`utf-8`));D=e.body,typeof e.frontmatter.description==`string`&&(O=e.frontmatter.description)}catch{}let k=typeof s.body==`string`?s.body:D,j=s.frontmatter===void 0?O:s.frontmatter.description,F=applySkillWrite({skillsRoot:g,name:s.toName,body:k,frontmatter:{name:s.toName,description:j}});if(F.ok||(w=F.error),s.scope===`project`&&!w)try{xu(g,s.fromName,s.toName)}catch(e){getLogger(`skill-move`).warn({err:e,fromName:s.fromName,toName:s.toName},`reindex of moved project skill docs failed — rename succeeded, deferring to next rescan`)}let L=nu(resolve(g,s.fromName),s.scope),B=nu(resolve(g,s.toName),s.scope);s.scope===`project`&&(_s(e,ka(`skill`,``,s.toName),`skill-rename: ${L} -> ${B}`,[{from:L,to:B}]),await xs(`skill-move`));let H=ru(s.scope);if(H){let e=await removeSkillInstall(H,s.fromName);if(e){let t=resolvedHosts(e.hosts);reverseProjectSkill(s.fromName,H,t);let S=projectSkill(resolve(g,s.toName),s.toName,H,t);await recordSkillInstall(H,s.toName,{...e,hosts:S})}}if(de?.(`files`),w){let e=w.code===`WRITE_ERROR`;errorResponse(t,e?500:400,e?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,`Skill renamed to "${s.toName}", but updating its SKILL.md failed — its name frontmatter may not match the new directory.`,{handler:`skill-move`,detail:w.code,cause:Error(w.message)});return}successResponse(t,200,SkillMoveSuccessSchema,{from:L,to:B,committed:S.committed},{handler:`skill-move`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to move skill.`,{handler:`skill-move`,cause:e})}},{handler:`skill-move`,method:`POST`});function _u(e){if(e.includes(`\0`))return null;let t=e.replace(/\\/g,`/`).split(`/`).filter(e=>e!==``&&e!==`.`);return t.length<2||t.some(e=>e===`..`)?null:t[0]===`references`?`reference`:t[0]===`scripts`?`script`:null}function vu(e,t,s){return e===`project`&&t===`reference`&&s.toLowerCase().endsWith(`.md`)}function yu(e,t){let s=t.replace(/\.md$/i,``);return`${projectSkillContentDocName(e).replace(/\/SKILL$/,``)}/${s}`}function bu(e,t){let s=resolve(e,t,`references`);if(!existsSync(s))return[];let g=[],S=(e,t)=>{for(let s of readdirSync(e,{withFileTypes:!0})){let w=t?`${t}/${s.name}`:s.name;s.isDirectory()?S(resolve(e,s.name),w):s.isFile()&&s.name.toLowerCase().endsWith(`.md`)&&g.push(`references/${w}`)}};return S(s,``),g}function xu(e,t,s){if(!ce)return;let g=(e,t,s)=>{let g;try{g=readFileSync(s,`utf-8`)}catch{ce.deleteDocument(e),ue?.deleteDocument(e);return}ce.renameDocument(e,t,g),ue?.renameDocument(e,t,g)};g(projectSkillContentDocName(t),projectSkillContentDocName(s),resolve(e,s,`SKILL.md`));for(let S of bu(e,s))g(yu(t,S),yu(s,S),resolve(e,s,S));de?.(`backlinks`),de?.(`graph`)}let Su=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Xl(g,t,`skill-file-get`))return;let S=Zl(s.searchParams.get(`scope`),t,`skill-file-get`);if(S===null)return;let w=s.searchParams.get(`path`)??``,E=_u(w);if(E===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill file path (must be a file under references/ or scripts/).`,{handler:`skill-file-get`});return}let D=resolve($l(S),g),O=resolve(D,w);if(O!==D&&!O.startsWith(`${D}${sep}`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Skill file path escapes the skill dir.`,{handler:`skill-file-get`});return}let k=O,j=w;if(!existsSync(k)){let e=w.match(/^(.*)\.(?:md|mdx)$/),s=e?SUPPORTED_DOC_EXTENSIONS.map(t=>`${e[1]}${t}`).find(e=>e!==w&&existsSync(resolve(D,e))):void 0;if(s===void 0){errorResponse(t,404,`urn:ok:error:not-found`,`Skill file not found.`,{handler:`skill-file-get`,detail:`${w} not found in skill "${g}" (${S}).`});return}j=s,k=resolve(D,s)}let F=await readFile$1(k);if(F.includes(0)){errorResponse(t,415,`urn:ok:error:invalid-request`,`Skill file is binary — only text bundle files are readable via MCP.`,{handler:`skill-file-get`});return}successResponse(t,200,SkillFileGetSuccessSchema,{path:j.replace(/\\/g,`/`),kind:E,text:F.toString(`utf-8`)},{handler:`skill-file-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill file.`,{handler:`skill-file-get`,cause:e})}},{handler:`skill-file-get`,method:`GET`,skipBodyParse:!0}),Cu=withValidation(SkillFilePutRequestSchema,async(e,t,g)=>{try{let e=extractActorIdentity(g,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-file-put`});return}if(!Xl(g.name,t,`skill-file-put`))return;let S=_u(g.path);if(S===null){errorResponse(t,400,`urn:ok:error:invalid-request`,"Invalid skill file path (must be a file under references/ or scripts/, no `..`).",{handler:`skill-file-put`});return}if(Buffer.byteLength(g.content,`utf-8`)>262144){errorResponse(t,400,`urn:ok:error:invalid-request`,`Skill file exceeds the 256 KB per-file cap.`,{handler:`skill-file-put`});return}let w=$l(g.scope);if(!existsSync(resolve(w,g.name,`SKILL.md`))){errorResponse(t,404,`urn:ok:error:not-found`,`Skill not found.`,{handler:`skill-file-put`,detail:`Create skill "${g.name}" before adding bundle files.`});return}let E=g.path.replace(/\\/g,`/`),D=vu(g.scope,S,E),O;if(D){let e=yu(g.name,E);if(Vl(e,`skill-file-put`,t))return;if(O=!existsSync(resolve(w,g.name,E)),O&&countBundleFiles(resolve(w,g.name))>=50){errorResponse(t,400,`urn:ok:error:invalid-request`,`Skill "${g.name}" already holds 50 bundle files (the cap) — delete one before adding another.`,{handler:`skill-file-put`});return}let{agentId:S,agentName:D,colorSeed:k,clientName:j}=Ui(g),F=await s.getSession(e,S,{displayName:D,colorSeed:k,clientName:j});F.dc.document.transact(()=>{composeAndWriteRawBody(F.dc.document,g.content,`agent`)},F.origin);let L=await Ht(e);if(L?.kind===`failure`){Ut(t,L.failure,`skill-file-put`);return}if(L?.kind===`divergence`){Wt(t,`skill-file-put`);return}}else{let e=applySkillBundleFileWrite({skillsRoot:w,name:g.name,relPath:E,content:g.content});if(!e.ok){let s=e.error.code===`WRITE_ERROR`?500:e.error.code===`SKILL_NOT_FOUND`?404:400;errorResponse(t,s,s===500?`urn:ok:error:internal-server-error`:s===404?`urn:ok:error:not-found`:`urn:ok:error:invalid-request`,s===500?`Failed to write skill file.`:`Invalid skill file request.`,{handler:`skill-file-put`,detail:e.error.code,cause:Error(e.error.message)});return}O=e.created}g.scope===`project`&&(_s(e,ka(`skill`,``,g.name),`${O?`skill-file-create`:`skill-file-edit`}: .ok/skills/${g.name}/${E}`),await xs(`skill-file-put`)),de?.(`files`),successResponse(t,200,SkillFilePutSuccessSchema,{path:E,created:O,kind:S,content:D},{handler:`skill-file-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write skill file.`,{handler:`skill-file-put`,cause:e})}},{handler:`skill-file-put`,method:`PUT`}),wu=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`).searchParams,g=s.get(`name`)??``;if(!Xl(g,t,`skill-file-delete`))return;let S=Zl(s.get(`scope`),t,`skill-file-delete`);if(S===null)return;let w=(s.get(`path`)??``).replace(/\\/g,`/`),E=_u(w);if(E===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill file path (must be a file under references/ or scripts/).`,{handler:`skill-file-delete`});return}let D=extractActorIdentity({agentId:s.get(`agentId`)??void 0,agentName:s.get(`agentName`)??void 0,colorSeed:s.get(`colorSeed`)??void 0,clientName:s.get(`clientName`)??void 0,clientVersion:s.get(`clientVersion`)??void 0,label:s.get(`label`)??void 0,summary:s.get(`summary`)??void 0},Ce);if(D.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-file-delete`});return}let O=$l(S);vu(S,E,w)&&await Ir([yu(g,w)]);let k=applySkillBundleFileDelete({skillsRoot:O,name:g,relPath:w});if(!k.ok){let e=k.error.code===`UNLINK_FAILED`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete skill file.`:`Invalid skill file request.`,{handler:`skill-file-delete`,detail:k.error.code,cause:Error(k.error.message)});return}k.existed&&S===`project`&&(_s(D,ka(`skill`,``,g),`skill-file-delete: .ok/skills/${g}/${w}`),await xs(`skill-file-delete`)),k.existed&&de?.(`files`),successResponse(t,200,SkillFileDeleteSuccessSchema,{path:w,existed:k.existed,kind:E},{handler:`skill-file-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete skill file.`,{handler:`skill-file-delete`,cause:e})}},{handler:`skill-file-delete`,method:`DELETE`,skipBodyParse:!0});async function Tu(e,t){if(e.method===`GET`)return Su(e,t);if(e.method===`PUT`)return Cu(e,t);if(e.method===`DELETE`)return wu(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`skill-file`,extraHeaders:{Allow:`GET, PUT, DELETE`}})}let Eu=withValidation(SkillInstallRequestSchema,async(e,t,s)=>{try{let e=$l(s.scope);if(!Xl(s.name,t,`skill-install`))return;if(s.scope===`project`&&!ye){errorResponse(t,400,`urn:ok:error:invalid-request`,`Cannot install — no project root is resolved for this server. Skills project into editor host dirs at the project root.`,{handler:`skill-install`,detail:`NO_PROJECT_ROOT`});return}let g=ru(s.scope),S=resolve(e,s.name);if(!existsSync(S)){errorResponse(t,404,`urn:ok:error:not-found`,`Skill not found.`,{handler:`skill-install`,detail:`Skill "${s.name}" not found in ${s.scope} scope — create it with write({ skill }) first.`});return}let w=validateSkillForInstall(S,s.name);if(!w.ok){errorResponse(t,400,`urn:ok:error:invalid-request`,`Skill "${s.name}" cannot be installed: ${w.errors.join(` `)}`,{handler:`skill-install`,detail:`INVALID_SKILL_SOURCE`});return}let E=s.scope===`global`?s.targets?PROJECT_SKILL_EDITOR_IDS.filter(e=>s.targets?.some(t=>t===e)):[...PROJECT_SKILL_EDITOR_IDS]:s.targets===void 0?resolveSkillTargets(g,readSkillTargets(g)??void 0):PROJECT_SKILL_EDITOR_IDS.filter(e=>s.targets?.some(t=>t===e)),D=[],O=[];E.length===0&&s.targets===void 0&&(D.push(s.scope===`global`?`No editor skill folders are configured to install into.`:"No project-configured editors detected — nothing was projected. Set up an editor for this project (add .mcp.json / .cursor/mcp.json / .codex/config.toml) or pass explicit `targets`."),O.push(`no-targets`)),w.hasScripts&&(D.push("This skill includes executable `scripts/`. After you install it, the AI agent in your editor (Claude, Cursor, Codex) can run them — Open Knowledge itself never runs anything. Review the scripts before sharing."),O.push(`scripts-present`));let k=resolvedHosts(readInstalledSkills(g).skills[s.name]?.hosts??[]).filter(e=>!E.includes(e));k.length>0&&reverseProjectSkill(s.name,g,k);let j=projectSkill(S,s.name,g,E);j.length===0?await removeSkillInstall(g,s.name):await recordSkillInstall(g,s.name,{hosts:j,scope:s.scope,scripts:w.hasScripts,installedAt:new Date().toISOString()}),de?.(`files`),successResponse(t,200,SkillInstallSuccessSchema,{name:s.name,hosts:j,scripts:w.hasScripts,warnings:D,warningCodes:O},{handler:`skill-install`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to install skill.`,{handler:`skill-install`,cause:e})}},{handler:`skill-install`,method:`POST`}),Du=withValidation(SkillUninstallRequestSchema,async(e,t,s)=>{try{if(!Xl(s.name,t,`skill-uninstall`))return;let e=ru(s.scope);if(!e){errorResponse(t,400,`urn:ok:error:invalid-request`,`Cannot uninstall — no project root is resolved for this server.`,{handler:`skill-uninstall`,detail:`NO_PROJECT_ROOT`});return}let g=await iu(e,s.name);de?.(`files`),successResponse(t,200,SkillUninstallSuccessSchema,{name:s.name,uninstalled:g},{handler:`skill-uninstall`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to uninstall skill.`,{handler:`skill-uninstall`,cause:e})}},{handler:`skill-uninstall`,method:`POST`});async function Ou(e,t){if(e.method===`GET`)return ku(e,t);if(e.method===`PUT`)return Au(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`skill-targets`,extraHeaders:{Allow:`GET, PUT`}})}let ku=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=ye?readSkillTargets(ye):null;successResponse(t,200,SkillTargetsGetSuccessSchema,{targets:resolveSkillTargets(ye??``,e??void 0),configured:e!==null},{handler:`skill-targets-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill targets.`,{handler:`skill-targets-get`,cause:e})}},{handler:`skill-targets-get`,method:`GET`,skipBodyParse:!0}),Au=withValidation(SkillTargetsPutRequestSchema,async(e,t,s)=>{try{if(!ye){errorResponse(t,400,`urn:ok:error:invalid-request`,`Cannot set skill targets — no project root is resolved for this server.`,{handler:`skill-targets-put`,detail:`NO_PROJECT_ROOT`});return}let e=s.targets,g=new Set(e),S=resolveSkillTargets(ye,readSkillTargets(ye)??void 0),w=$l(`project`);await writeSkillTargets(ye,e);let{reprojected:E,bundleHosts:D}=await reprojectAllManagedSkills({projectDir:ye,skillsRoot:w,targets:e});de?.(`files`),successResponse(t,200,SkillTargetsPutSuccessSchema,{targets:e,reprojected:E,bundleHosts:D,removedFrom:S.filter(e=>!g.has(e))},{handler:`skill-targets-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to set skill targets.`,{handler:`skill-targets-put`,cause:e})}},{handler:`skill-targets-put`,method:`PUT`}),ju=withValidation(SkillRestoreRequestSchema,async(e,t,s)=>{try{let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-restore`});return}if(!Xl(s.name,t,`skill-restore`))return;if(s.scope===`global`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Global skills are unversioned — there is no version history to restore from.`,{handler:`skill-restore`,detail:`GLOBAL_SCOPE_UNVERSIONED`});return}let S=q?.current;if(!S){errorResponse(t,409,`urn:ok:error:shadow-not-configured`,`No version history available to restore from.`,{handler:`skill-restore`,detail:`NO_SHADOW_REPO`});return}let w=await restoreSkillVersion({shadow:S,contentDir:g,contentRoot:se??`.`,name:s.name,version:s.version});if(!w.ok){let[e,s]={"no-shadow":[409,`urn:ok:error:shadow-not-configured`],"version-not-found":[404,`urn:ok:error:not-found`],"skill-absent":[404,`urn:ok:error:not-found`],"io-error":[500,`urn:ok:error:storage-error`],"path-escape":[500,`urn:ok:error:path-escape`]}[w.code];errorResponse(t,e,s,w.error,{handler:`skill-restore`,detail:w.code});return}let E=[],D=validateSkillForInstall(resolve(g,`.ok`,`skills`,s.name),s.name);D.ok||E.push(`Restored, but the skill no longer validates: ${D.errors.join(` `)}`),E.push("Run `install` to push the restored version to your editors."),_s(e,ka(`skill`,``,s.name),`skill-restore: ${s.name} @ ${s.version.slice(0,8)}`),await xs(`skill-restore`),de?.(`files`),successResponse(t,200,SkillRestoreSuccessSchema,{name:s.name,version:s.version,restoredFiles:w.restoredFiles,warnings:E},{handler:`skill-restore`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to restore skill.`,{handler:`skill-restore`,cause:e})}},{handler:`skill-restore`,method:`POST`}),Mu=withValidation(SkillUpdateRequestSchema,async(e,t,g)=>{try{let e=extractActorIdentity(g,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-update`});return}if(!Xl(g.name,t,`skill-update`))return;if(!isPackSkillName(g.name)){errorResponse(t,400,`urn:ok:error:invalid-request`,"Only starter-pack skills (`open-knowledge-pack-*`) can be updated from the bundle.",{handler:`skill-update`,detail:`NOT_A_PACK_SKILL`});return}if(g.scope===`global`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Pack skills are project-scope — there is no global-scope pack to update.`,{handler:`skill-update`,detail:`GLOBAL_SCOPE`});return}let S=readBundledPackSkill(g.name);if(S===null||S.version===void 0){errorResponse(t,404,`urn:ok:error:not-found`,`No bundled version is available for this pack skill.`,{handler:`skill-update`,detail:`NO_BUNDLED_VERSION`});return}let w=resolve($l(`project`),g.name,`SKILL.md`);if(!existsSync(w)){errorResponse(t,404,`urn:ok:error:not-found`,`Skill is not installed.`,{handler:`skill-update`,detail:`SKILL_ABSENT`});return}let E;try{E=readSkillVersion(readFileSync(w,`utf-8`))}catch{}let D,O=q?.current;if(O)try{let e=ae?.()??`main`;D=(await saveVersion(O,se??`.`,[SERVICE_WRITER],e,`Before updating ${g.name} (${E??`unversioned`} → ${S.version})`)).checkpointRef}catch(e){getLogger(`skills`).warn({err:e,skill:g.name},`pre-update checkpoint failed — proceeding with overwrite`)}let k=skillLiveDocName(`project`,g.name);if(Vl(k,`skill-update`,t))return;let{agentId:j,agentName:F,colorSeed:L,clientName:B}=Ui(g),H=await s.getSession(k,j,{displayName:F,colorSeed:L,clientName:B});H.dc.document.transact(()=>{composeAndWriteRawBody(H.dc.document,S.content,`agent`)},H.origin);let ee=await Ht(k);if(ee?.kind===`failure`){Ut(t,ee.failure,`skill-update`);return}if(ee?.kind===`divergence`){Wt(t,`skill-update`);return}_s(e,ka(`skill`,``,g.name),`skill-pack-update: ${g.name} (${E??`unversioned`} → ${S.version})`),await xs(`skill-update`),de?.(`files`),successResponse(t,200,SkillUpdateSuccessSchema,{name:g.name,version:S.version,...E===void 0?{}:{previousVersion:E},...D===void 0?{}:{checkpointRef:D}},{handler:`skill-update`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to update skill.`,{handler:`skill-update`,cause:e})}},{handler:`skill-update`,method:`POST`});function Nu(e){let t=new Map;for(let s of e){let e=s.path.split(`/`).filter(Boolean);e.pop();for(let g=1;g<=e.length;g++){let S=e.slice(0,g).join(`/`);t.set(S,Math.max(t.get(S)??0,s.modifiedTs))}}return[...t.entries()].map(([e,t])=>createWorkspaceSearchDocument({kind:`folder`,path:e,modifiedTs:t}))}function Pu(e,t){let s=t.trim().toLowerCase();if(!s||!e)return;let g=e.toLowerCase().indexOf(s);if(g<0)return;let S=Math.max(0,g-80),w=Math.min(e.length,g+s.length+120),E=S>0?`…`:``,D=w<e.length?`…`:``;return`${E}${e.slice(S,w).replace(/\s+/g,` `).trim()}${D}`}function Fu(e){return e===`autocomplete`||e===`full_text`||e===`omnibar`?e:`omnibar`}function Iu(e){let t=typeof e==`string`?e.split(`,`):Array.isArray(e)?e:void 0;if(!t)return;let s=t.filter(e=>e===`page`||e===`folder`||e===`content`||e===`file`);return s.length>0?s:void 0}function Lu(e){if(typeof e==`boolean`)return e;if(e===`true`)return!0;if(e===`false`)return!1}function Ru(e){return e===`omnibar`||e===`mcp`||e===`http`?e:`http`}async function zu(e,t,s,g){let S=g.documents.filter(e=>!isHiddenDocName(e.path)),w=S.reduce((e,t)=>e+(t.kind===`page`?1:0),0);if(!ze?.isEnabled()||s!==!0)return{queryEmbedMs:null,pageTotal:w,capable:!1};ze.embedCorpus(S);let E,D=null;if(t===`full_text`&&e.trim().length>=3){let t=performance.now(),s=await ze.queryScores(e,S);if(D=performance.now()-t,s&&s.size>0){let e=Be?.();E=e===void 0?{scores:s}:{scores:s,similarityFloor:e}}}let O=ze.getStatus();return{input:E,status:{capable:O.capable,applied:!1,coverage:{embedded:O.embeddedCount,total:w}},queryEmbedMs:D,pageTotal:w,capable:O.capable}}function Bu(e,t){return{kind:e.document.kind,path:e.document.path,title:e.document.title,score:e.score,signals:e.signals,snippet:e.document.kind===`page`?Pu(e.document.content,t):void 0}}async function Vu(e){let t=performance.now();if(Xu())return{query:e.query,intent:e.intent,results:[],elapsedMs:Math.max(0,performance.now()-t),ready:!1};let{corpus:s,truncated:g}=await Zu(),S=await zu(e.query,e.intent,e.semanticParam,s),w=searchWorkspaceCorpus(s,e.query,{intent:e.intent,ranking:e.ranking,scopes:e.scopes,limit:e.limit,semantic:S.input}).map(t=>Bu(t,e.query)),E;if(S.status){let t=w.reduce((e,t)=>e+(t.signals.vector===void 0?0:1),0),s=t>0;E={...S.status,applied:s},recordSemanticQuery({outcome:S.capable?s?`applied`:S.status.coverage.embedded===0?`warming`:`no_match`:`incapable`,source:e.source,capable:S.capable,embedded:S.status.coverage.embedded,total:S.pageTotal,queryEmbedMs:S.queryEmbedMs,vectorContributors:t})}return{query:e.query,intent:e.intent,results:w,elapsedMs:Math.max(0,performance.now()-t),ready:!0,...E?{semantic:E}:{},...g?{truncated:!0}:{}}}function Hu(){let e=$l(`project`);if(!existsSync(e))return[];let t;try{t=readdirSync(e,{withFileTypes:!0})}catch{return[]}let s=[];for(let g of t.sort((e,t)=>e.name.localeCompare(t.name))){if(!g.isDirectory()||!SKILL_NAME_REGEX.test(g.name))continue;let t=resolve(e,g.name,`SKILL.md`);try{let e=statSync(t);s.push({name:g.name,absolutePath:t,mtimeMs:e.mtimeMs,size:e.size})}catch{}}return s}function Uu(){let e=[];for(let t of Hu()){let s=t.name,g=``;try{let{frontmatter:e,body:S}=Wl(readFileSync(t.absolutePath,`utf-8`));typeof e.name==`string`&&e.name&&(s=e.name),g=`${typeof e.description==`string`?e.description:``}\n\n${S}`.trim()}catch{}e.push(createWorkspaceSearchDocument({kind:`page`,path:skillLiveDocName(`project`,t.name),title:s,content:g,modifiedTs:t.mtimeMs}))}return e}function Wu(e){return`${e.modified}\0${e.size}\0${e.canonicalPath}\0${e.inode}\0${e.aliases.join(`\0`)}`}let Gu=new Map;async function Ku(){let e=[],t=[],s=new Set;for(let[g,S]of E()){if(isSystemDoc(g)||isConfigDoc(g)||g.startsWith(`.ok/skills/`))continue;if(S.kind===`file`){t.push(createWorkspaceSearchDocument({kind:`file`,path:g,modifiedTs:Date.parse(S.modified),aliases:S.aliases}));continue}s.add(g);let w=Wu(S),E=Gu.get(g);if(E&&E.key===w){e.push(E.doc);continue}let D=``,O=g,k=!1;try{D=await readFile$1(S.canonicalPath,`utf-8`)}catch(e){k=!0,console.warn(`[search] Failed to read ${g}:`,e)}if(!k)try{O=extractPageTitle(D,g)}catch(e){console.warn(`[search] Failed to extract title for ${g}:`,e)}let j=createWorkspaceSearchDocument({kind:`page`,path:g,title:O,content:D,modifiedTs:Date.parse(S.modified),aliases:S.aliases});k||Gu.set(g,{key:w,doc:j}),e.push(j)}for(let e of Gu.keys())s.has(e)||Gu.delete(e);let g=getSearchMaxEntries(),S=t,w=!1;return t.length>g&&(w=!0,S=[...t].sort((e,t)=>e.path.split(`/`).length-t.path.split(`/`).length||e.path.localeCompare(t.path)).slice(0,g),getLogger(`search`).warn({dropped:t.length-S.length,retained:S.length,limit:g},`[search] corpus name-only file tier truncated at OK_SEARCH_MAX_ENTRIES`),searchCorpusTruncatedCounter().add(1)),{documents:[...e,...Uu(),...S,...Nu([...e,...S])],truncated:w}}function qu(){return Hu().map(e=>`${e.name} ${e.mtimeMs} ${e.size}`).join(``)}function Ju(){return O?`gen:${O()}|skills${qu()}`:`${[...E()].filter(([e])=>!isSystemDoc(e)&&!isConfigDoc(e)).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}\0${Wu(t)}`).join(``)}|skills${qu()}`}let Yu=Me===void 0;Me?.then(()=>{Yu=!0},e=>{Yu=!0,log$6.warn({err:e,handler:`search`},`[api] ready gate rejected — search serves the partial index`)});function Xu(){return!Yu}async function Zu(){let e=`${g}${ye??``}`,t=Ju(),s=workspaceSearchCaches.get(e);if(s?.fingerprint===t&&s.corpus)return{corpus:s.corpus,truncated:s.truncated??!1};if(s?.fingerprint===t&&s.pending)return s.pending;let S=Ku().then(({documents:e,truncated:t})=>({corpus:createWorkspaceSearchCorpus(e),truncated:t}));workspaceSearchCaches.set(e,{fingerprint:t,pending:S});try{let s=await S;return workspaceSearchCaches.get(e)?.pending===S&&workspaceSearchCaches.set(e,{fingerprint:t,corpus:s.corpus,truncated:s.truncated}),s}catch(t){throw workspaceSearchCaches.get(e)?.pending===S&&workspaceSearchCaches.delete(e),t}}function Qu(){if(process.env.NODE_ENV!==`test`)for(let e of[0,1e3,3e3])setTimeout(()=>{Zu().catch(e=>{console.warn(`[search] Failed to prewarm workspace search cache:`,e)})},e)}Qu();async function $u(e,t){if(e.method===`GET`)return ed(e,t);if(e.method===`POST`)return td(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`search`,extraHeaders:{Allow:`GET, POST`}})}let ed=withValidation(EmptyRequestSchema,async(e,t)=>{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`limit`),S=s.searchParams.get(`query`)??``,w=Fu(s.searchParams.get(`intent`)),E=tu(s.searchParams.get(`ranking`)),D=Iu(s.searchParams.get(`scope`)??s.searchParams.get(`scopes`)),O=Lu(s.searchParams.get(`semantic`)),k=Ru(s.searchParams.get(`source`)),j=g===null?void 0:Number(g);if(S.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-get`});return}try{successResponse(t,200,SearchSuccessSchema,await Vu({query:S,intent:w,ranking:E,scopes:D,limit:j,semanticParam:O,source:k}),{handler:`search-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-get`,cause:e})}},{handler:`search-get`,method:`GET`,skipBodyParse:!0}),td=withValidation(SearchRequestSchema,async(e,t,s)=>{let g=typeof s.query==`string`?s.query:``,S=Fu(s.intent),w=tu(s.ranking),E=Iu(s.scopes??s.scope),D=typeof s.limit==`number`?s.limit:void 0,O=Lu(s.semantic),k=Ru(s.source);if(g.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-post`});return}try{successResponse(t,200,SearchSuccessSchema,await Vu({query:g,intent:S,ranking:w,scopes:E,limit:D,semanticParam:O,source:k}),{handler:`search-post`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-post`,cause:e})}},{handler:`search-post`,method:`POST`}),nd=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,SkillInstallStateSuccessSchema,{...await readSkillInstallStateSnapshot(homedir())},{handler:`skill-install-state`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill install state.`,{handler:`skill-install-state`,cause:e})}},{handler:`skill-install-state`,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`skill-install-state`})});async function rd(e,t){if(checkLocalOpSecurity(e,t,{handler:`handoff`}))try{await handleHandoffDispatch(e,t,{contentDir:g,platform:process.platform})}catch(e){t.headersSent||(log$6.error({err:e},`[handoff] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`handoff`,cause:e}))}}async function ad(e,t){if(checkLocalOpSecurity(e,t,{handler:`spawn-cursor`}))try{await handleSpawnCursor(e,t,{contentDir:g,platform:process.platform})}catch(e){t.headersSent||(log$6.error({err:e},`[spawn-cursor] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`spawn-cursor`,cause:e}))}}let od=withValidation(ShareConstructUrlRequestSchema,async(e,t,s)=>{try{if(!ye){emitShareConstructUrlLog(`no-remote`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!isValidSharePath(s.kind===`doc`?s.docPath:s.folderPath,s.kind)){emitShareConstructUrlLog(`invalid-path`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`invalid-path`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let e=readGitHeadBranch(ye);if(e===null){if(readOriginGitHubRepo(ye).kind===`no-remote`){emitShareConstructUrlLog(`no-remote`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}emitShareConstructUrlLog(`detached-head`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`detached-head`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let S=readOriginGitHubRepo(ye);if(S.kind===`no-remote`){emitShareConstructUrlLog(`no-remote`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(S.kind===`non-github`){emitShareConstructUrlLog(`non-github-remote`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`non-github-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!branchExistsOnOrigin(ye,e)){emitShareConstructUrlLog(`branch-not-on-origin`,{branchExists:!1,kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`branch-not-on-origin`,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let w=toGitRelativePath(ye,g);if(w===null)throw Error(`content dir is not contained within the project dir`);let E=s.kind===`doc`?s.docPath!==``:s.folderPath!==``;w!==``&&E&&getLogger(`share`).warn({action:`construct-url`,kind:s.kind},`[share] content.dir != "." — non-root share URL omits the content.dir prefix; the github.com link may point at the wrong subtree. In-app receive navigation is content-relative and lands correctly.`);let D;if(s.kind===`doc`)D=buildGitHubBlobUrl(S.owner,S.repo,e,s.docPath);else{let t=s.folderPath===``?w:s.folderPath;D=buildGitHubTreeUrl(S.owner,S.repo,e,t)}let O=`${SHARE_BASE_URL}${encodeShareUrl(D)}`;emitShareConstructUrlLog(`ok`,{branchExists:!0,kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!0,shareUrl:O,sharedUrl:D,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,cause:e})}},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})}),sd=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!ye){errorResponse(t,500,`urn:ok:error:internal-server-error`,`projectDir is not configured for this server.`,{handler:BRANCH_INFO_HANDLER_TAG});return}let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`branch`),S=s.searchParams.get(`path`),w=s.searchParams.get(`kind`)===`folder`?`folder`:`doc`;if(!isValidBranchName(g)){errorResponse(t,400,`urn:ok:error:invalid-request`,`branch query param missing or malformed.`,{handler:BRANCH_INFO_HANDLER_TAG});return}if(!isValidBranchInfoPath(S,w)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path query param missing or malformed.`,{handler:BRANCH_INFO_HANDLER_TAG});return}successResponse(t,200,BranchInfoResponseSchema,await computeBranchInfo(ye,g,S,w),{handler:BRANCH_INFO_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:BRANCH_INFO_HANDLER_TAG,cause:e})}},{handler:BRANCH_INFO_HANDLER_TAG,method:`GET`,skipBodyParse:!0}),cd=withValidation(CheckoutRequestSchema,async(e,t,s)=>{if(extractActorIdentity(s,Ce).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:CHECKOUT_HANDLER_TAG});return}if(!ye){errorResponse(t,500,`urn:ok:error:internal-server-error`,`projectDir is not configured for this server.`,{handler:CHECKOUT_HANDLER_TAG});return}try{successResponse(t,200,CheckoutResponseSchema,await withParentLock(()=>runCheckoutFlow(ye,s.branch)),{handler:CHECKOUT_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:CHECKOUT_HANDLER_TAG,cause:e})}},{handler:CHECKOUT_HANDLER_TAG,method:`POST`});async function ld(e){let[t,...s]=ve,g=[...s,...e];return await new Promise((e,s)=>{let S=spawn(t,g,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),w=!1,E=setTimeout(()=>{w=!0,S.kill(`SIGTERM`)},SHARE_PUBLISH_TIMEOUT_MS),D=[],O=[];S.stdout.on(`data`,e=>D.push(e)),S.stderr.on(`data`,e=>O.push(e)),S.on(`close`,t=>{if(clearTimeout(E),w){s(Error(`share subprocess timed out after ${SHARE_PUBLISH_TIMEOUT_MS}ms`));return}let g=Buffer.concat(D).toString(`utf-8`);if(t!==0){let e=redactShareSubprocessStderr(Buffer.concat(O).toString(`utf-8`)).slice(0,500);console.warn(`[share] subprocess exited code=${t} stderr=${e}`)}e({stdout:g,code:t})}),S.on(`error`,e=>{clearTimeout(E),s(e)})})}let ud=withValidation(EmptyRequestSchema,async(e,t)=>{if(!We.tryAcquire(`/api/share/publish/owners`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share owners operation is already in progress.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await ld([`share`,`owners`,`--json`]),s=parseOwnersEvent(pickTerminalJsonLine(e));emitSharePublishLog(`owners-list`,s.ok?`ok`:s.error,s.ok?{count:s.owners.length}:void 0),successResponse(t,200,SharePublishOwnersResponseSchema,s,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,cause:e})}finally{We.release(SHARE_PUBLISH_OWNERS_KEY)}},{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}),dd=withValidation(EmptyRequestSchema,async(e,t)=>{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`owner`)??``,S=s.searchParams.get(`name`)??``;if(!isValidShareOwnerName(g)||!isValidShareRepoName(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name query params must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG});return}if(!We.tryAcquire(`/api/share/publish/name-check`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share name-check operation is already in progress.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await ld([`share`,`name-check`,`--owner`,g,`--name`,S,`--json`]),s=parseNameCheckEvent(pickTerminalJsonLine(e));emitSharePublishLog(`name-check`,s.ok?`ok`:s.error,s.ok?{available:s.available}:void 0),successResponse(t,200,SharePublishNameCheckResponseSchema,s,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,cause:e})}finally{We.release(SHARE_PUBLISH_NAME_CHECK_KEY)}},{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}),fd=withValidation(SharePublishRequestSchema,async(e,t,s)=>{if(!ye){emitSharePublishLog(`publish-create`,`no-project`),successResponse(t,200,SharePublishResponseSchema,{ok:!1,error:`no-project`},{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!isValidShareOwnerName(s.owner)||!isValidShareRepoName(s.name)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!We.tryAcquire(`/api/share/publish`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share publish operation is already in progress.`,{handler:SHARE_PUBLISH_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let e=[`share`,`publish`,`--owner`,s.owner,`--name`,s.name,`--visibility`,s.visibility,`--project-dir`,ye,`--json`];s.description!==void 0&&s.description.length>0&&e.push(`--description`,s.description);let{stdout:g}=await ld(e),S=parsePublishEvent(pickTerminalJsonLine(g));emitSharePublishLog(`publish-create`,S.ok?`ok`:S.error),S.ok&&_e?.()?.refreshRemote().catch(()=>{}),successResponse(t,200,SharePublishResponseSchema,S,{handler:SHARE_PUBLISH_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_HANDLER_TAG,cause:e})}finally{We.release(SHARE_PUBLISH_KEY)}},{handler:SHARE_PUBLISH_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_HANDLER_TAG})}),pd=withValidation(ClientLogsRequestSchema,async(e,t,s)=>{try{let e=getLogger(`renderer`);for(let t of s.entries)try{e[t.level]({...t.fields,source:`renderer-console`,transport:`web`,...t.sourceId?{sourceId:t.sourceId}:{},...t.lineNumber===void 0?{}:{lineNumber:t.lineNumber},...t.ts===void 0?{}:{clientTs:t.ts}},t.event??t.message)}catch{}successResponse(t,200,ClientLogsSuccessSchema,{accepted:s.entries.length},{handler:`client-logs`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`client-logs`,cause:e})}},{handler:`client-logs`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`client-logs`})}),md=ye?getLocalDir(ye):null;async function hd(e,t){if(e.method===`DELETE`){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-config`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-config`});return}md&&clearArmedPaneTarget(md),t.setHeader(`Cache-Control`,`no-store`),t.statusCode=204,t.end();return}if(e.method===`GET`||e.method===`HEAD`){try{let s=e.headers.host,g={collabUrl:s?`ws://${s}/collab`:null,previewUrl:null,port:md?readServerLock(md)?.port??0:0,paneTarget:md?readArmedPaneTarget(md):null,singleFile:Ue};if(e.method===`HEAD`){t.setHeader(`Content-Type`,`application/json`),t.setHeader(`Cache-Control`,`no-store`),t.setHeader(`X-Content-Type-Options`,`nosniff`),t.statusCode=200,t.end();return}successResponse(t,200,ApiConfigSuccessSchema,g,{handler:`api-config`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`api-config`,cause:e})}return}errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`api-config`,extraHeaders:{Allow:`GET, HEAD, DELETE`}})}let gd=`local-op-embeddings-set-key`,_d=`local-op-embeddings-clear-key`,vd=`/api/local-op/embeddings`,yd=withValidation(LocalOpEmbeddingsSetKeyRequestSchema,async(e,t,s)=>{if(!We.tryAcquire(vd)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An embeddings key operation is already in progress.`,{handler:gd,extraHeaders:{"Retry-After":`5`}});return}try{await new FileEmbeddingsBackend(Ve).set(s.key),successResponse(t,200,LocalOpEmbeddingsMutationSuccessSchema,{keyPresent:!0},{handler:gd,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to store the key.`,{handler:gd,cause:e})}finally{We.release(vd)}},{handler:gd,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:gd})}),bd=withValidation(EmptyRequestSchema,async(e,t)=>{if(!We.tryAcquire(vd)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An embeddings key operation is already in progress.`,{handler:_d,extraHeaders:{"Retry-After":`5`}});return}try{await clearEmbeddingsKeyFromAllBackends(Ve),successResponse(t,200,LocalOpEmbeddingsMutationSuccessSchema,{keyPresent:!1},{handler:_d,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to clear the key.`,{handler:_d,cause:e})}finally{We.release(vd)}},{handler:_d,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:_d})}),xd=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=!1,s=!1,g=!1,S=0;if(ze){let t=ze.getStatus();e=t.enabled,s=t.ready,g=t.capable,S=t.embeddedCount}let E=await new FileEmbeddingsBackend(Ve).get(),D=process.env.OK_EMBEDDINGS_API_KEY??null,O=E?`file`:D?`env`:null,k=O!==null,j=E??D,F=j&&j.length>=8?j.slice(-4):null,L=0;for(let[e]of w())!isSystemDoc(e)&&!isConfigDoc(e)&&!isHiddenDocName(e)&&(L+=1);successResponse(t,200,SemanticIndexStatusSchema,{enabled:e,keyPresent:k,keySource:O,keyHint:F,ready:s,capable:g,embedded:S,total:L},{handler:`semantic-status`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`semantic-status`,cause:e})}},{handler:`semantic-status`,method:`GET`,skipBodyParse:!0}),Sd={"/api/config":hd,"/api/asset":xc,"/api/asset-text":Cc,"/api/document":ks,"/api/documents":As,"/api/backlinks":Ns,"/api/backlink-counts":Ps,"/api/forward-links":Is,"/api/link-graph":Rs,"/api/dead-links":tc,"/api/orphans":$s,"/api/hubs":ec,"/api/tags":Ol,"/api/pages":Nc,"/api/folder-config":Ll,"/api/template":Ul,"/api/templates":Hl,"/api/skill":su,"/api/skill-file":Tu,"/api/skills":ou,"/api/skills/management":fu,"/api/skill/install":Eu,"/api/skill/uninstall":Du,"/api/skill/restore":ju,"/api/skill/update":Mu,"/api/skill-targets":Ou,"/api/search":$u,"/api/semantic-status":xd,"/api/suggest-links":Pc,"/api/page-headings":kc,"/api/create-page":Ec,"/api/create-folder":Dc,"/api/duplicate-path":Oc,"/api/rename-path":Ac,"/api/delete-path":jc,"/api/trash/cleanup":Mc,"/api/upload":Fc,"/api/agent-write":Cs,"/api/agent-write-md":Ts,"/api/frontmatter-patch":Ds,"/api/agent-patch":nc,"/api/agent-undo":rc,"/api/agent-activity":ic,"/api/agent-burst-diff":ac,"/api/save-version":uc,"/api/history":dc,"/api/rollback":pc,"/api/metrics/reconciliation":mc,"/api/metrics/parse-health":hc,"/api/metrics/agent-presence":vc,"/api/__embed-detect":yc,"/api/server-info":gc,"/api/share/construct-url":od,"/api/git/branch-info":sd,"/api/git/checkout":cd,"/api/share/publish/owners":ud,"/api/share/publish/name-check":dd,"/api/share/publish":fd,"/api/principal":_c,"/api/rescue":Tc,"/api/workspace":bc,"/api/sync/status":hl,"/api/sync/trigger":gl,"/api/sync/conflicts":_l,"/api/sync/conflict-content":yl,"/api/sync/resolve-conflict":vl,"/api/local-op/clone":Vc,"/api/local-op/ok-init":Gc,"/api/local-op/auth/login":Qc,"/api/local-op/auth/status":il,"/api/local-op/auth/repos":cl,"/api/local-op/auth/signout":dl,"/api/local-op/auth/set-identity":ml,"/api/local-op/embeddings/set-key":yd,"/api/local-op/embeddings/clear-key":bd,"/api/installed-agents":Dl,"/api/spawn-cursor":ad,"/api/handoff":rd,"/api/install-skill":El,"/api/skill/install-state":nd,"/api/seed/plan":xl,"/api/seed/apply":Cl,"/api/seed/packs":Tl,"/api/client-logs":pd};H&&(Sd[`/api/test-reset`]=sc,Sd[`/api/test-flush-git`]=oc,Sd[`/api/test-rescan-backlinks`]=cc,Sd[`/api/test-rescan-files`]=lc);let Cd=new Set(`/api/upload./api/create-page./api/create-folder./api/duplicate-path./api/rename-path./api/delete-path./api/trash/cleanup./api/agent-write./api/agent-write-md./api/frontmatter-patch./api/agent-patch./api/agent-undo./api/save-version./api/rollback./api/sync/trigger./api/sync/resolve-conflict./api/git/checkout./api/test-reset./api/test-flush-git./api/test-rescan-backlinks./api/test-rescan-files./api/install-skill./api/folder-config./api/template./api/skill./api/skill-file./api/skill/install./api/skill/uninstall./api/skill/restore./api/skill/update./api/skills/management./api/skill-targets./api/seed/apply./api/client-logs`.split(`.`)),wd=[`/api/local-op/`];return{priority:100,async onRequest({request:e,response:t}){let s=e.url?.split(`?`)[0];if(!s)return;let g=t=>{let s=e.headers[t];if(s!==void 0)return Array.isArray(s)?s.join(`, `):s};if(recordEmbedProbe({ts:Date.now(),url:s,method:e.method??``,ua:g(`user-agent`),origin:g(`origin`),referer:g(`referer`),host:g(`host`),remote:e.socket?.remoteAddress,secChUa:g(`sec-ch-ua`),secChUaMobile:g(`sec-ch-ua-mobile`),secChUaPlatform:g(`sec-ch-ua-platform`),secFetchSite:g(`sec-fetch-site`),secFetchDest:g(`sec-fetch-dest`),secFetchMode:g(`sec-fetch-mode`),secFetchUser:g(`sec-fetch-user`)}),s.startsWith(`/api/`)){let s=e.headers.origin;if(s!==void 0&&!isAllowedApiOrigin(s)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`api-origin-gate`});return}if(typeof t.setHeader==`function`&&(s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`)),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, traceparent, tracestate, baggage, ${CLIENT_VERSION_HEADER.protocol}, ${CLIENT_VERSION_HEADER.runtime}, ${CLIENT_VERSION_HEADER.kind}`)),e.method===`OPTIONS`){t.writeHead(204),t.end();return}}if(Cd.has(s)||wd.some(e=>s.startsWith(e))){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-mutating-gate`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-mutating-gate`});return}}if(Ue&&s.startsWith(`/api/`)){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-ephemeral-gate`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-ephemeral-gate`});return}}if(!s.startsWith(`/api/`))return;let S=propagation.extract(context.active(),e.headers),w=e.method??`GET`,E=s;s.startsWith(`/api/history/`)?E=`/api/history/:sha`:s.startsWith(`/api/tags/`)?E=`/api/tags/:name`:Sd[s]||(E=`/api/*`);let D=getTracer(),O=Date.now();await context.with(S,()=>D.startActiveSpan(`HTTP ${w} ${E}`,{kind:SpanKind.SERVER,attributes:{[ATTR_HTTP_REQUEST_METHOD]:w,[ATTR_HTTP_ROUTE]:E,[ATTR_URL_PATH]:s,[ATTR_URL_SCHEME]:`http`,[ATTR_USER_AGENT_ORIGINAL]:e.headers[`user-agent`]??``}},async g=>{try{let S=Sd[s],E=!1;if(S)E=!0,await S(e,t);else if(s.startsWith(`/api/history/`)){let g=decodeURIComponent(s.slice(13));g&&(E=!0,await fc(e,t,g))}else if(s.startsWith(`/api/tags/`)){let g=s.slice(10);g&&(E=!0,await kl(e,t,g))}E||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`api-dispatch`,detail:`No handler for ${w} ${s}`});let D=t.statusCode;g.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE,D),D>=500&&g.setStatus({code:SpanStatusCode.ERROR,message:`status ${D}`})}catch(e){throw g.recordException(e),g.setStatus({code:SpanStatusCode.ERROR,message:e instanceof Error?e.message:String(e)}),!t.headersSent&&!t.writableEnded&&!t.destroyed&&errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:E,cause:e}),e}finally{g.end();let e=(Date.now()-O)/1e3;httpDurationHist().record(e,{[ATTR_HTTP_REQUEST_METHOD]:w,[ATTR_HTTP_ROUTE]:E,[ATTR_HTTP_RESPONSE_STATUS_CODE]:t.statusCode})}}))}}}function errnoCode(e){let t=e?.code;return typeof t==`string`?t:void 0}function seedSingleDirBasenameIndex(e){let t;try{t=readdirSync(e.contentDir,{withFileTypes:!0})}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`read-failed`,s,e.contentDir);return}for(let s of t)s.isFile()&&isSupportedAssetFile(s.name,ASSET_EXTENSIONS)&&e.basenameIndex.add(s.name)}async function seedBasenameIndex(e){let t=e.contentDir,s=new Set;async function g(S){let w;try{w=await readdir(S,{withFileTypes:!0})}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`read-failed`,s,S);return}for(let E of w){let w=join(S,E.name),D=toPosix(relative(t,w));if(D.startsWith(`..`)||e.contentFilter?.isDirExcluded(D)&&E.isDirectory())continue;let O;try{O=await lstat(w)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`lstat-failed`,s,w);continue}if(O.isSymbolicLink()){let S;try{S=await realpath(w)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`realpath-failed`,s,w);continue}if(!isWithinDir(S,t)){e.onSkip?.(`symlink-escape`,void 0,w);continue}let E;try{E=await stat$1(S)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`symlink-stat-failed`,s,S);continue}if(s.has(E.ino))continue;s.add(E.ino),E.isDirectory()?await g(S):E.isFile()&&isSupportedAssetFile(w,LINKABLE_ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(D)&&e.basenameIndex.add(D);continue}if(O.isDirectory()){if(s.has(O.ino))continue;s.add(O.ino),await g(w);continue}O.isFile()&&isSupportedAssetFile(w,LINKABLE_ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(D)&&e.basenameIndex.add(D)}}await g(t)}var AutoStartDisabledError=class extends Error{constructor(e){super(e),this.name=`AutoStartDisabledError`}};const log$5=getLogger(`conflict-storage`);var ConflictStore=class{storePath;projectDir;branch;conflicts=[];constructor(e,t=`main`){this.storePath=join(getLocalDir(e),`conflicts.json`),this.projectDir=e,this.branch=t,this.load()}load(){if(!existsSync(this.storePath)){this.conflicts=[];return}try{let e=readFileSync(this.storePath,`utf-8`),t=JSON.parse(e);if(t.version!==1){log$5.warn({path:this.storePath},`[conflicts] unknown schema version — resetting`),this.conflicts=[];return}this.branch=t.branch??this.branch,this.conflicts=t.conflicts??[]}catch(e){log$5.warn({err:e},`[conflicts] failed to load conflicts.json — starting empty`),this.conflicts=[]}}save(){try{let e=dirname(this.storePath);existsSync(e)||mkdirSync(e,{recursive:!0});let t={version:1,branch:this.branch,conflicts:this.conflicts};writeFileSync(this.storePath,JSON.stringify(t,null,2),`utf-8`)}catch(e){log$5.warn({err:e},`[conflicts] failed to save conflicts.json`)}}addConflict(e){let t=this.conflicts.findIndex(t=>t.file===e.file);t===-1?this.conflicts.push(e):this.conflicts[t]=e,this.save()}removeConflict(e){this.conflicts=this.conflicts.filter(t=>t.file!==e),this.save()}clear(){this.conflicts=[],this.save()}count(){return this.conflicts.length}list(){return[...this.conflicts]}hasConflicts(){return this.conflicts.length>0}setBranch(e){this.branch=e}async resolveConflict(e,t,s,g=[]){if(!this.conflicts.find(t=>t.file===e))throw Error(`[conflicts] no conflict tracked for file: ${e}`);if(t===`content`&&s===void 0)throw Error(`[conflicts] strategy 'content' requires content parameter`);let{createGitInstance:S}=await import(`./git-handle-DdgvPBh6-Dv4DjLoy.mjs`),w=S(this.projectDir,{credentialArgs:g});switch(t){case`mine`:await w.git.raw([`checkout`,`--ours`,`--`,e]),await w.git.raw([`add`,`--`,e]);break;case`theirs`:await w.git.raw([`checkout`,`--theirs`,`--`,e]),await w.git.raw([`add`,`--`,e]);break;case`content`:{if(s===void 0)throw Error(`[conflicts] strategy 'content' requires content parameter`);let t=resolve(this.projectDir),g=resolve(t,e);if(!isWithinDir(g,t))throw Error(`[conflicts] file path escapes project directory: ${e}`);writeFileSync(g,s,`utf-8`),await w.git.raw([`add`,`--`,e]);break}case`delete`:await w.git.raw([`rm`,`--`,e]);break;default:throw Error(`[conflicts] unknown resolve strategy: ${t}`)}if(this.removeConflict(e),!this.hasConflicts())try{await w.git.raw([`commit`,`--no-edit`]),log$5.info({file:e},`[conflicts] all conflicts resolved — merge commit created`)}catch(t){let s=new Date().toISOString(),g=!1;try{let e=(await w.git.raw([`diff`,`--name-only`,`--diff-filter=U`])).split(`
1940
+ `:``)+t;composeAndWriteRawBody(te.dc.document,S,`agent`),recordFrontmatterEditSurface(`mcp-write`),ce=!0}se=!0},te.origin)})}finally{me?.touchMode(O,`idle`)}if(oe){let e;switch(oe.kind){case`invalid_value`:e={[oe.key]:oe.reason};break;case`reserved_key`:e={[oe.key]:`'${oe.key}' is reserved`};break;case`unknown_key`:e={[oe.key]:`'${oe.key}' is not a recognized key`};break;case`duplicate_target`:e={[oe.key]:`'${oe.key}' appears more than once`};break;case`reorder_mismatch`:e={__region__:`frontmatter reorder mismatch (expected: ${oe.expected.join(`, `)}; got: ${oe.got.join(`, `)})`};break;case`region_too_large`:e={__region__:`frontmatter region too large (${oe.bytes} > ${oe.limit} bytes)`};break;case`parse_failed`:e={__region__:`frontmatter region unparseable: ${oe.reason}`};break;case`invalid_path`:e={[oe.path.map(String).join(`.`)||`__path__`]:oe.reason};break;default:e={__region__:`unhandled frontmatter edit error (${String(oe)})`}}errorResponse(w,400,`urn:ok:error:invalid-frontmatter-patch`,`Frontmatter patch rejected: schema validation failed.`,{handler:`frontmatter-patch`,extensions:{fieldErrors:e}});return}if(se&&ue.length>0){if(recordContributor(D,O,k,j,void 0,Ki({clientName:F,clientVersion:L,label:B}),Y),incrementAgentWriteCalls(),Zi(ee),ce){let e=await Ht(D);if(e?.kind===`failure`){Ut(w,e.failure,`frontmatter-patch`);return}if(e?.kind===`divergence`){Wt(w,`frontmatter-patch`);return}}Vt(D,`frontmatter-patch`)}fe?.setFocus(O,{agentName:k,currentDoc:D,writeKind:`write`,ts:Date.now()}),ge?.();let de=zt(D),_e=Bt();_e===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(F)});let ve=Kt(ne),ye=$t();ye.add(D);let Ce=computeBrokenOutboundLinks(te.dc.document.getText(`source`).toString(),D,ye,en);successResponse(w,200,FrontmatterPatchSuccessSchema,{timestamp:ae,subscriberCount:de,systemSubscriberCount:_e,appliedKeys:ue,...J?{summary:J}:{},...ve?{warning:ve,warnings:[ve]}:{},brokenLinks:Ce},{handler:`frontmatter-patch`})}catch(e){if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`frontmatter-patch`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$6.error({err:e},`[frontmatter-patch] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`frontmatter-patch`,cause:e})}},{handler:`frontmatter-patch`,method:`POST`});function ks(e){let t=e.getMap(`lifecycle`),s=t.get(`status`);if(typeof s!=`string`||s.length===0)return null;let g=t.get(`reason`);return{status:s,reason:typeof g==`string`?g:``}}let As=withValidation(EmptyRequestSchema,async(e,s)=>{try{let S=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`docName`)||`test-doc`;if(!isSafeDocName(S)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`document-read`});return}let w=Rt(S);if(isSystemDoc(w)||isConfigDoc(w)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`'${w}' is a reserved document name.`,{handler:`document-read`});return}let E=t.documents.get(w);if(E){successResponse(s,200,DocumentReadSuccessSchema,{docName:w,content:E.getText(`source`).toString(),lifecycle:ks(E)},{handler:`document-read`});return}if(!existsSync(resolveContentEntryPath(g,`file`,w))){errorResponse(s,404,`urn:ok:error:doc-not-found`,`Document not found: ${w}.`,{handler:`document-read`});return}let D=await t.openDirectConnection(w);try{let e=D.document;if(!e){errorResponse(s,500,`urn:ok:error:doc-not-available`,`Document is not available.`,{handler:`document-read`});return}successResponse(s,200,DocumentReadSuccessSchema,{docName:w,content:e.getText(`source`).toString(),lifecycle:ks(e)},{handler:`document-read`})}finally{await D.disconnect()}}catch(e){errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to read document.`,{handler:`document-read`,cause:e})}},{handler:`document-read`,method:`GET`,skipBodyParse:!0}),Ns=withValidation(EmptyRequestSchema,async(e,t)=>{try{Me&&await Me.catch(e=>{log$6.warn({err:e,handler:`document-list`},`[api] ready gate rejected — responding with partial index`)});let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=s.searchParams.get(`dir`),D=s.searchParams.get(`showAll`)===`true`,O=s.searchParams.get(`depth`)===`1`?1:1/0;if(S)try{safeSubdir(g,S)}catch{errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid directory parameter.`,{handler:`document-list`});return}if(D&&Te&&showAllWantsNdjson(e)){let e=new AbortController;t.on(`close`,()=>{t.writableEnded||e.abort()}),t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let s=createStreamingErrorWriter(t,`document-list`),w=async e=>{t.writableEnded||t.destroyed||t.write(e)||await new Promise(e=>{let s=()=>{t.off(`drain`,s),t.off(`close`,s),e()};t.once(`drain`,s),t.once(`close`,s)})};try{let t=getShowAllMaxEntries(),s=streamShowAllEntries({contentDir:g,contentFilter:Te,dirFilter:S,getDocExtension,maxEntries:t,maxDepth:O,signal:e.signal}),E=0,D=await s.next();for(;!D.done;)await w(`${JSON.stringify(D.value)}\n`),E+=1,D=await s.next();let{truncated:k}=D.value;k&&log$6.info({handler:`document-list`,maxEntries:t,count:E},`[document-list][showAll] stream truncated at entry cap`),await w(`${JSON.stringify({type:`complete`,truncated:k,count:E})}\n`)}catch(e){!t.writableEnded&&!t.destroyed?s(500,`urn:ok:error:internal-server-error`,`Failed to list documents (showAll stream).`,{cause:e}):log$6.error({err:e,handler:`document-list`},`[document-list][showAll] stream failed after response ended`)}finally{t.writableEnded||t.end()}return}if(D&&Te){let e=`showAll:${O===1?`d1:`:``}${S??``}`,s=Ge.get(e);if(!s){let t=new AbortController,w=(async()=>{let e=[],s=getShowAllMaxEntries(),{truncated:w}=await walkContentDirForShowAll({contentDir:g,contentFilter:Te,dirFilter:S,documents:e,getDocExtension,maxEntries:s,maxDepth:O,signal:t.signal});return e.sort((e,t)=>{let s=e.kind===`folder`?e.path??``:e.docName??e.path??``,g=t.kind===`folder`?t.path??``:t.docName??t.path??``;return s.localeCompare(g)}),w&&log$6.info({handler:`document-list`,maxEntries:s,count:e.length},`[document-list][showAll] walk truncated at entry cap`),{documents:e,truncated:w}})();s={promise:w,controller:t,waiters:0};let E=s;Ge.set(e,E),w.finally(()=>{Ge.get(e)===E&&Ge.delete(e)})}let w=s;w.waiters+=1;let E=!1,D=()=>{t.writableEnded||E||(E=!0,--w.waiters,w.waiters<=0&&(w.controller.abort(),Ge.get(e)===w&&Ge.delete(e)))};t.on(`close`,D);try{let{documents:e,truncated:s}=await w.promise;if(E)return;successResponse(t,200,DocumentListSuccessSchema,s?{documents:e,truncated:s}:{documents:e},{handler:`document-list`})}catch(e){if(E)return;errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list documents (showAll mode).`,{handler:`document-list`,cause:e})}finally{t.removeListener(`close`,D)}return}let j=w(),F=E(),B=k?.()??new Map,H=[];for(let[e,t]of B)S&&!e.startsWith(`${S}/`)&&e!==S||H.push({kind:`folder`,path:e,size:0,modified:t.modified,docExt:`.md`,isSymlink:!1,canonicalDocName:null,targetPath:null});let q=[];try{let e=st(j);Xe?.signature!==e&&(Xe={signature:e,assets:collectReferencedAssets({contentDir:g,fileIndex:j,readMarkdown:e=>{try{return readFileSync(e,`utf-8`)}catch{return null}},isExcluded:Te?e=>Te.isPathIgnored(e):void 0})}),q=Xe?.assets??[]}catch(e){Xe=null,console.warn(`[document-list] asset collection failed; returning documents only:`,e)}let ee=new Set;for(let e of q)S&&!e.path.startsWith(`${S}/`)&&e.path!==S||(ee.add(e.path),H.push({kind:`asset`,docName:e.path,docExt:e.assetExt,path:e.path,assetExt:e.assetExt,mediaKind:e.mediaKind,referencedBy:e.referencedBy,size:e.size,modified:e.modified,isSymlink:!1,canonicalDocName:null,targetPath:null}));for(let[e,t]of F){if(t.kind===`markdown`){if(S&&!e.startsWith(`${S}/`)&&e!==S)continue;let s=getDocExtension(e);H.push({kind:`document`,docName:e,docExt:s,size:t.size,modified:t.modified,isSymlink:!1,canonicalDocName:null,targetPath:null});for(let w of t.aliases){if(S&&!w.startsWith(`${S}/`)&&w!==S)continue;let E=toPosix(relative(g,t.canonicalPath));H.push({kind:`document`,docName:w,docExt:s,size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:E})}continue}if((!S||e===S||e.startsWith(`${S}/`))&&!ee.has(e)){let s=synthesizeShowAllAssetExt(e);H.push({kind:`file`,docName:e,path:e,docExt:`.${s}`,assetExt:s,size:t.size,modified:t.modified,isSymlink:!1,canonicalDocName:null,targetPath:null})}for(let s of t.aliases){if(!(!S||s===S||s.startsWith(`${S}/`))||ee.has(s))continue;let w=toPosix(relative(g,t.canonicalPath)),E=synthesizeShowAllAssetExt(s);H.push({kind:`file`,docName:s,path:s,docExt:`.${E}`,assetExt:E,size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:w})}}let J=L?.()??new Map;if(J.size>0){let e=e=>!S||e===S||e.startsWith(`${S}/`),t=new Map;for(let[e,s]of J){let g=t.get(s);g?g.push(e):t.set(s,[e])}for(let[s,S]of t){let t=B.get(s),w=t?toPosix(relative(g,t.canonicalPath)):s;for(let g of S)e(g)&&H.push({kind:`folder`,path:g,size:0,modified:t?.modified??`1970-01-01T00:00:00.000Z`,docExt:`.md`,isSymlink:!0,canonicalDocName:s,targetPath:w})}let s=(s,g)=>{for(let S=s.indexOf(`/`);S!==-1;S=s.indexOf(`/`,S+1)){let w=t.get(s.slice(0,S));if(!w)continue;let E=s.slice(S);for(let t of w){let s=`${t}${E}`;e(s)&&g(s)}}};for(let[e,t]of B)s(e,s=>{H.push({kind:`folder`,path:s,size:0,modified:t.modified,docExt:`.md`,isSymlink:!0,canonicalDocName:e,targetPath:toPosix(relative(g,t.canonicalPath))})});for(let[e,t]of F)s(e,s=>{let S=toPosix(relative(g,t.canonicalPath));if(t.kind===`markdown`)H.push({kind:`document`,docName:s,docExt:getDocExtension(e),size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:S});else{let g=synthesizeShowAllAssetExt(s);H.push({kind:`file`,docName:s,path:s,docExt:`.${g}`,assetExt:g,size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:S})}})}H.sort((e,t)=>{let s=e.kind===`folder`?e.path??``:e.docName??e.path??``,g=t.kind===`folder`?t.path??``:t.docName??t.path??``;return s.localeCompare(g)}),successResponse(t,200,DocumentListSuccessSchema,{documents:H},{handler:`document-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list documents.`,{handler:`document-list`,cause:e})}},{handler:`document-list`,method:`GET`,skipBodyParse:!0}),Ps=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`backlinks`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!s){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`backlinks`});return}if(!isSafeDocName(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`backlinks`});return}successResponse(t,200,BacklinksSuccessSchema,{docName:s,backlinks:ce.getBacklinks(s).map(e=>({source:e.source,anchor:e.anchor,title:Dt(e.source),snippet:e.snippet}))},{handler:`backlinks`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read backlinks.`,{handler:`backlinks`,cause:e})}},{handler:`backlinks`,method:`GET`,skipBodyParse:!0}),Is=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`backlink-counts`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docNames`);if(!s){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docNames parameter.`,{handler:`backlink-counts`});return}let g={};for(let e of s.split(`,`)){let t=e.trim();!t||!isSafeDocName(t)||(g[t]=ce.getBacklinkCount(t))}successResponse(t,200,BacklinkCountsSuccessSchema,{counts:g},{handler:`backlink-counts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read backlink counts.`,{handler:`backlink-counts`,cause:e})}},{handler:`backlink-counts`,method:`GET`,skipBodyParse:!0}),Rs=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`forward-links`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!s){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`forward-links`});return}if(!isSafeDocName(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`forward-links`});return}let g=$t();successResponse(t,200,ForwardLinksSuccessSchema,{docName:s,forwardLinks:ce.getForwardLinkEntries(s).map(e=>e.kind===`doc`?{kind:`doc`,docName:e.target,anchor:e.anchor,title:jt(e.target,g),snippet:e.snippet}:{kind:`external`,url:e.url,title:e.label??e.url,snippet:e.snippet})},{handler:`forward-links`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read forward links.`,{handler:`forward-links`,cause:e})}},{handler:`forward-links`,method:`GET`,skipBodyParse:!0}),$s=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`link-graph`});return}try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`docName`);if(g&&!isSafeDocName(g)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`link-graph`});return}let S=s.searchParams.get(`degrees`);if(S&&!g){errorResponse(t,400,`urn:ok:error:invalid-request`,`docName is required when degrees is provided.`,{handler:`link-graph`});return}let w,E;if(S&&g){let e=Number.parseInt(S,10);if(!Number.isFinite(e)||e<0){errorResponse(t,400,`urn:ok:error:invalid-request`,`degrees must be a non-negative integer.`,{handler:`link-graph`});return}({nodes:w,links:E}=ce.getLinkGraphNeighborhood(g,e))}else ({nodes:w,links:E}=ce.getLinkGraph());let D=$t();successResponse(t,200,LinkGraphSuccessSchema,{nodes:w.map(e=>{if(e.kind===`doc`){let t=It(e.docName,D);return{id:e.id,kind:`doc`,docName:e.docName,anchor:e.anchor??null,label:jt(e.docName,D),cluster:t.cluster??null,category:t.category??null,tags:t.tags??null}}return{id:e.id,kind:`external`,url:e.url,label:e.label??e.url}}),links:E},{handler:`link-graph`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read link graph.`,{handler:`link-graph`,cause:e})}},{handler:`link-graph`,method:`GET`,skipBodyParse:!0}),ec=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`orphans`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`mode`)??`both`;if(!isOrphanMode(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid orphan mode. Allowed values: incoming, outgoing, both.`,{handler:`orphans`});return}successResponse(t,200,OrphansSuccessSchema,{orphans:ce.getOrphans([...w().keys()],s).map(e=>({docName:e,title:Dt(e)}))},{handler:`orphans`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read orphan pages.`,{handler:`orphans`,cause:e})}},{handler:`orphans`,method:`GET`,skipBodyParse:!0}),tc=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`hubs`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`limit`),g=s?Number.parseInt(s,10):20,S=Number.isFinite(g)&&g>0?g:20,w=$t();successResponse(t,200,HubsSuccessSchema,{hubs:ce.getHubs(S).map(e=>({docName:e.docName,title:jt(e.docName,w),count:e.count}))},{handler:`hubs`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read hub pages.`,{handler:`hubs`,cause:e})}},{handler:`hubs`,method:`GET`,skipBodyParse:!0}),nc=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`dead-links`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.getAll(`sourceDocName`);if(s.some(e=>e.length===0||!isSafeDocName(e))){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid sourceDocName.`,{handler:`dead-links`});return}let g=s.length?[...new Set(s.map(e=>Rt(e)))]:void 0;successResponse(t,200,DeadLinksSuccessSchema,{deadLinks:ce.getDeadLinks($t(),g).map(e=>({target:e.target,sources:e.sources.map(e=>({source:e.source,title:Dt(e.source),snippet:e.snippet}))}))},{handler:`dead-links`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read dead links.`,{handler:`dead-links`,cause:e})}},{handler:`dead-links`,method:`GET`,skipBodyParse:!0}),rc=withValidation(AgentPatchRequestSchema,async(S,w,E)=>{try{let{find:S,replace:D,offset:O}=E,k=requireNonEmptyDocName(E.docName,w,`agent-patch`);if(k===null)return;let j=Rt(k),{agentId:F,agentName:L,colorSeed:B,clientName:H,clientVersion:q,label:ee}=Gi(E);if(findLooksLikeFrontmatter(S)){agentPatchFmTouchCounter().add(1,{result:`rejected`}),errorResponse(w,400,`urn:ok:error:frontmatter-edit-not-supported`,`Frontmatter edits are not supported via a body find/replace. Use edit({ document: { path, frontmatter } }) to change frontmatter, or write({ document: { path, content, position: "replace" } }) to rewrite the whole document including its YAML block.`,{handler:`agent-patch`});return}if(isSystemDoc(j)||isConfigDoc(j)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${j}' is a reserved document name.`,{handler:`agent-patch`});return}let J=normalizeSummary(E.summary),Y=await s.getSession(j,F,{displayName:L,colorSeed:B,clientName:H}),te=reconcileDiskBeforeAgentWrite(t,j,g,e.resolveEmbed),ne=new Date().toISOString(),ae=!1,oe=!1,se=!1,ce;try{let t=iconFromClientName(H),s=AGENT_ICON_COLORS[t]??colorFromSeed(B??F);if(me?.setPresence(F,{displayName:L,icon:t,color:s,currentDoc:j,mode:`writing`,ts:Date.now()}),captureEffect(Y.dc.document.getText(`source`),F,B,H),Y.dc.document.transact(()=>{let{frontmatter:t,body:s}=stripFrontmatter(Y.dc.document.getText(`source`).toString()),g=prependFrontmatter(t,s),w=O==null?g.indexOf(S):g.slice(O,O+S.length)===S?O:-1;if(w===-1){O==null?ae=!0:oe=!0,console.warn(JSON.stringify({event:`agent-patch-find-mismatch`,"doc.name":j,findLength:S.length,replaceLength:D.length,hadOffset:O!=null})),incrementAgentPatchFindMismatches();return}if(w<t.length){se=!0;return}let{body:E}=stripFrontmatter(g.slice(0,w)+D+g.slice(w+S.length));ce=applyAgentMarkdownWrite(Y.dc.document,E,`patch`,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:j}:void 0),Y.dc.document.getMap(`agent-flash`).set(F,{agentId:F,timestamp:Date.now(),type:`insert`,description:`Patched (${L}): ${S.slice(0,50)}`})},Y.origin),ce!==void 0&&console.warn(JSON.stringify({event:`agent-write-content-divergence`,"doc.name":j,position:`patch`,intendedBytes:ce.intendedBytes,actualBytes:ce.actualBytes,byteDelta:ce.byteDelta,"agent.id":F,"agent.client_name":H})),!ae&&!oe&&!se){let{stored:e}=Yi(J);recordContributor(j,F,L,B,void 0,Ki({clientName:H,clientVersion:q,label:ee}),e),incrementAgentWriteCalls(),Zi(J),recordContentDivergenceGate(`agent-patch`,ce)}}finally{me?.touchMode(F,`idle`)}if(oe){errorResponse(w,409,`urn:ok:error:stale-target`,`Target text no longer matches at the requested offset.`,{handler:`agent-patch`});return}if(ae){errorResponse(w,404,`urn:ok:error:target-not-found`,`Text not found in document.`,{handler:`agent-patch`});return}if(se){agentPatchFmTouchCounter().add(1,{result:`rejected`}),errorResponse(w,400,`urn:ok:error:frontmatter-edit-not-supported`,`Frontmatter edits are not supported via a body find/replace. Use edit({ document: { path, frontmatter } }) to change frontmatter, or write({ document: { path, content, position: "replace" } }) to rewrite the whole document including its YAML block.`,{handler:`agent-patch`});return}let ue=await Ht(j);if(ue?.kind===`failure`){Ut(w,ue.failure,`agent-patch`);return}if(ue?.kind===`divergence`){Wt(w,`agent-patch`);return}Vt(j,`agent-patch`),fe?.setFocus(F,{agentName:L,currentDoc:j,writeKind:`edit`,ts:Date.now()}),ge?.();let de=zt(j),_e=Bt();_e===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(H)});let{response:ve}=Yi(J),ye=Y.dc.document.getText(`source`).toString(),Ce=await validateMermaidFences(ye,j),we=$t();we.add(j);let Te=computeBrokenOutboundLinks(ye,j,we,en),De=Kt(te),je=ce===void 0?void 0:toContentDivergenceWarning(ce),Me=[...je?[je]:[],...De?[De]:[],...Ce??[]];successResponse(w,200,AgentPatchSuccessSchema,{timestamp:ne,subscriberCount:de,systemSubscriberCount:_e,...ve?{summary:ve}:{},...je?{warning:je}:De?{warning:De}:{},...Me.length>0?{warnings:Me}:{},brokenLinks:Te},{handler:`agent-patch`})}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(w,e,`agent-patch`);return}if(e instanceof FrontmatterMalformedError){respondFrontmatterMalformed(w,e,`agent-patch`);return}if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-patch`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$6.error({err:e},`[agent-patch] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-patch`,cause:e})}},{handler:`agent-patch`,method:`POST`}),ic=withValidation(AgentUndoRequestSchema,async(t,g,S)=>{try{let t=requireNonEmptyDocName(S.docName,g,`agent-undo`);if(t===null)return;let w=Rt(t),{agentId:E,agentName:D,colorSeed:O,clientName:k,clientVersion:j,label:F}=Gi(S);if(isSystemDoc(w)||isConfigDoc(w)){errorResponse(g,400,`urn:ok:error:reserved-doc-name`,`'${w}' is a reserved document name.`,{handler:`agent-undo`});return}let{connectionId:L}=S,B=S.scope===`session`||S.scope===`file`?`session`:`last`;if(!s.hasSession(w,L)){errorResponse(g,404,`urn:ok:error:no-active-session`,`No active session for this connectionId and docName.`,{handler:`agent-undo`});return}let H=await s.getSession(w,L),q=!1;try{let t=iconFromClientName(k),s=AGENT_ICON_COLORS[t]??colorFromSeed(O??E);me?.setPresence(E,{displayName:D,icon:t,color:s,currentDoc:w,mode:`writing`,ts:Date.now()}),q=applyAgentUndo(H,B,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:w}:void 0),q&&recordContributor(w,L,D,O,void 0,Ki({clientName:k,clientVersion:j,label:F}))}finally{me?.touchMode(E,`idle`)}if(q){let e=await Ht(w);if(e?.kind===`failure`){Ut(g,e.failure,`agent-undo`);return}if(e?.kind===`divergence`){Wt(g,`agent-undo`);return}Vt(w,`agent-undo`)}fe?.setFocus(L,{agentName:L,currentDoc:w,writeKind:`undo`,ts:Date.now()}),successResponse(g,200,AgentUndoSuccessSchema,{docName:w,scope:B,undone:q},{handler:`agent-undo`})}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(g,e,`agent-undo`);return}log$6.error({err:e},`[agent-undo] handler failed`),errorResponse(g,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-undo`,cause:e})}},{handler:`agent-undo`,method:`POST`}),ac=withValidation(EmptyRequestSchema,async(e,t)=>{try{let g=validateAgentId(new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`agentId`));if(g===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`agentId required (alphanumeric/_/- only).`,{handler:`agent-activity`});return}successResponse(t,200,AgentActivitySuccessSchema,listAgentActivity(s,g),{handler:`agent-activity`})}catch(e){log$6.error({err:e},`[agent-activity] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-activity`,cause:e})}},{handler:`agent-activity`,method:`GET`,skipBodyParse:!0}),oc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let g=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=validateAgentId(g.searchParams.get(`agentId`)),w=g.searchParams.get(`docName`),E=g.searchParams.get(`stackIndex`);if(S===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`agentId required (alphanumeric/_/- only).`,{handler:`agent-burst-diff`});return}if(!w||w.trim()===``){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`agent-burst-diff`});return}if(!isSafeDocName(w)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`agent-burst-diff`});return}let D=Rt(w);if(isSystemDoc(D)||isConfigDoc(D)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${D}' is a reserved document name.`,{handler:`agent-burst-diff`});return}if(!E||Number.isNaN(Number(E))){errorResponse(t,400,`urn:ok:error:invalid-request`,`StackIndex must be a number.`,{handler:`agent-burst-diff`});return}let O=Number(E);if(!Number.isInteger(O)||O<0){errorResponse(t,400,`urn:ok:error:invalid-request`,`stackIndex must be a non-negative integer.`,{handler:`agent-burst-diff`});return}let k=s.getLiveSession(D,S);if(!k){errorResponse(t,404,`urn:ok:error:no-active-session`,`No active session for this agentId and docName.`,{handler:`agent-burst-diff`});return}let j=k.um;if(O>=j.undoStack.length){errorResponse(t,404,`urn:ok:error:not-found`,`stackIndex ${O} out of range (stack has ${j.undoStack.length} items).`,{handler:`agent-burst-diff`});return}let F=j.undoStack[O];successResponse(t,200,AgentBurstDiffSuccessSchema,{diff:synthesizeStackItemDiffText(F,k.dc.document.getText(`source`),D),generatedAt:Date.now()},{handler:`agent-burst-diff`})}catch(e){log$6.error({err:e},`[agent-burst-diff] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-burst-diff`,cause:e})}},{handler:`agent-burst-diff`,method:`GET`,skipBodyParse:!0}),sc=withValidation(EmptyRequestSchema,async(e,t)=>{try{await ee?.(),successResponse(t,200,TestFlushGitSuccessSchema,{},{handler:`test-flush-git`})}catch(e){log$6.error({err:e},`[test-flush-git] flush failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-flush-git`,cause:e})}},{handler:`test-flush-git`,method:`POST`,skipBodyParse:!0}),cc=withValidation(EmptyRequestSchema,async(e,S)=>{try{let w=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),E=Rt(w.searchParams.get(`docName`)??`test-doc`),D;try{D=safeContentPath(E,g)}catch(e){log$6.error({err:e,docName:E},`[test-reset] safeContentPath rejected docName`),errorResponse(S,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`test-reset`,cause:e});return}await s.closeAll(E),t.closeConnections(E);let O=`onStoreDocument-${E}`;t.debouncer.isDebounced(O)&&await t.debouncer.executeNow(O);let k=t.documents.get(E);if(k&&await(je??t.unloadDocument.bind(t))(k),writeFileSync(D,``,`utf-8`),ce&&(ce.deleteDocument(E),ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist cache after test-reset for ${E}:`,e)}),de?.(`backlinks`),de?.(`graph`)),w.searchParams.get(`reset-okignore`)!==`false`)try{let e=resolve(g,`.okignore`),s=t.documents.get(CONFIG_DOC_NAME_OKIGNORE);if(s){let e=s.getText(`source`);e.length>0&&s.transact(()=>{e.delete(0,e.length)},CONFIG_VALIDATION_REVERT_ORIGIN)}existsSync(e)&&writeFileSync(e,``,`utf-8`),Te&&await Te.rebuildIgnorePatterns()}catch(e){console.warn(`[test-reset] okignore reset partial failure:`,e)}de?.(`files`),successResponse(S,200,TestResetSuccessSchema,{},{handler:`test-reset`})}catch(e){errorResponse(S,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-reset`,cause:e})}},{handler:`test-reset`,method:`POST`,skipBodyParse:!0}),lc=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!ce){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`test-rescan-backlinks`});return}await ce.rebuildFromDisk(),await ce.ingestGlobalSkillBundles([resolve($l,`.ok`,`skills`)]),ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist cache after test-rescan-backlinks:`,e)}),de?.(`backlinks`),de?.(`graph`),successResponse(t,200,TestRescanBacklinksSuccessSchema,{},{handler:`test-rescan-backlinks`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-rescan-backlinks`,cause:e})}},{handler:`test-rescan-backlinks`,method:`POST`,skipBodyParse:!0}),uc=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!B){errorResponse(t,503,`urn:ok:error:file-rescan-not-configured`,`Watcher rescan capability is not configured.`,{handler:`test-rescan-files`});return}await B(),de?.(`files`),successResponse(t,200,TestRescanFilesSuccessSchema,{},{handler:`test-rescan-files`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-rescan-files`,cause:e})}},{handler:`test-rescan-files`,method:`POST`,skipBodyParse:!0}),dc=withValidation(SaveVersionRequestSchema,async(e,t,s)=>{try{let{rawAgentId:e,agentId:g,agentName:S,clientName:w}=Gi(s),E=q?.current;if(!E){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`save-version`});return}let D=/^[a-zA-Z0-9_-]+$/,O=[],k=!1;if(Array.isArray(s.writers))try{O=s.writers.map(e=>{let t=e.id??`unknown`;if(!D.test(t))throw Error(`Invalid writer id: ${t}`);return{id:t,name:(e.name??`unknown`).replace(/[\r\n]/g,``),email:(e.email??`noreply@openknowledge.local`).replace(/[\r\n]/g,``)}})}catch(e){errorResponse(t,400,`urn:ok:error:invalid-request`,e instanceof Error?e.message:`Invalid writer id.`,{handler:`save-version`,cause:e});return}let j=ae?.()??`main`;if(O.length===0)if(e!==void 0)O=[{id:g,name:w?`${S} (${w})`:S,email:`${g}@openknowledge.local`}];else{let e=(await enumerateWipChains(E,j)).filter(e=>!e.isPark);O=e.length>0?e.map(e=>({id:e.writerId,name:e.writerId,email:`${e.writerId}@openknowledge.local`})):[SERVICE_WRITER],k=!0}let F=se??`.`,L=normalizeSummary(typeof s.summary==`string`?s.summary:void 0),B=await saveVersion(E,F,O,j,L.kind===`value`?L.value:void 0,k?{includeUpstream:!1}:void 0);getLogger(`history`).info({checkpointRef:B.checkpointRef},`checkpoint`);try{await gcRenameLog(E,getOrLoadRenameLogIndex(E.gitDir))}catch(e){console.warn(`[rename-log] post-saveVersion GC failed:`,e)}successResponse(t,200,SaveVersionSuccessSchema,{checkpointRef:B.checkpointRef},{handler:`save-version`})}catch(e){log$6.error({err:e},`[save-version] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`save-version`,cause:e})}},{handler:`save-version`,method:`POST`}),fc=withValidation(EmptyRequestSchema,async(e,t)=>{let s=q?.current;if(!s){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`history`});return}let g=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=g.searchParams.get(`docName`)??``,w=g.searchParams.get(`folder`),E=g.searchParams.get(`branch`)??ae?.()??`main`;if(!S&&w===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`A docName or folder query parameter is required.`,{handler:`history`});return}if(E.includes(`..`)||!/^[a-zA-Z0-9][a-zA-Z0-9._/-]*$/.test(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid branch name.`,{handler:`history`});return}if(w!==null&&!S){let e=Ml(w,t,`folder`,`history`);if(!e)return;let S=Number(g.searchParams.get(`limit`)??`50`),D=Math.min(200,Number.isFinite(S)?S:50),O=Number(g.searchParams.get(`offset`)??`0`),k=Math.max(0,Number.isFinite(O)?O:0),j=`folder\0${E}\0${e.folderRel}\0${D}\0${k}`,{promise:F,coalesced:L}=Ke.run(j,()=>getFolderTimeline(s,e.folderRel,se??`.`,{branch:E,limit:D,offset:k}));L&&recordTimelineCoalesced(`folder`),successResponse(t,200,HistorySuccessSchema,{...await F},{handler:`history`});return}let D=se??`.`,O=safeDocPath(S,D);if(`error`in O){errorResponse(t,400,`urn:ok:error:invalid-request`,O.error,{handler:`history`});return}let k=Number(g.searchParams.get(`limit`)??`50`),j=Number(g.searchParams.get(`offset`)??`0`),F=Math.min(200,Number.isFinite(k)?k:50),L=Number.isFinite(j)?j:0,B=g.searchParams.get(`type`)??void 0,H=g.searchParams.get(`author`)??void 0,ee=g.searchParams.get(`excludeAuthor`)??void 0,J=g.searchParams.get(`includeAutoCheckpoints`)===`true`,Y=`doc\0${E}\0${S}\0${F}\0${L}\0${B??``}\0${H??``}\0${ee??``}\0${J?`1`:`0`}`,te=Date.now();try{let{promise:e,coalesced:g}=Ke.run(Y,()=>getDocumentHistory(s,{docName:S,branch:E,limit:F,offset:L,type:B,author:H,excludeAuthor:ee,includeAutoCheckpoints:J},D));g&&recordTimelineCoalesced(`doc`);let w=await e,O=Date.now()-te;getLogger(`timeline`).info({docName:S,entries:w.entries.length,durationMs:O},`query`),successResponse(t,200,HistorySuccessSchema,{...w},{handler:`history`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read history.`,{handler:`history`,cause:e})}},{handler:`history`,method:`GET`,skipBodyParse:!0});async function pc(e,t,s){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`history-version`,extraHeaders:{Allow:`GET`}});return}let g=q?.current;if(!g){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`history-version`});return}let S=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`docName`)??``,w=se??`.`,E=safeDocPath(S,w);if(`error`in E){errorResponse(t,400,`urn:ok:error:invalid-request`,E.error,{handler:`history-version`});return}let D=shadowGit(g),O=ae?.()??`main`;if(!/^[0-9a-f]{40}$/i.test(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid commit SHA.`,{handler:`history-version`});return}try{let e=await resolveDocPathAtCommit(g,S,s,O,getOrLoadRenameLogIndex(g.gitDir),e=>{let t=safeDocPath(e,w);return`error`in t?`${e}.md`:t.path},createAncestorShaSetCache());if(e===null){errorResponse(t,404,`urn:ok:error:doc-not-found`,`Document did not exist at this version.`,{handler:`history-version`});return}let E=await D.raw(`show`,`${s}:${e}`),[k=``,j=``]=(await D.raw(`log`,`-1`,`--format=%aI%x00%an`,s)).trim().split(`\0`);successResponse(t,200,HistoryVersionSuccessSchema,{sha:s,content:E,timestamp:k,author:j},{handler:`history-version`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`history-version`,cause:e})}}let mc=withValidation(RollbackRequestSchema,async(s,g,S)=>{let w=extractActorIdentity(S,Ce);if(w.kind===`invalid-summary`){errorResponse(g,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`rollback`});return}let E=t.documents.get(S.docName);if(E&&isDocInConflict(E)){respondDocInConflict(g,new DocInConflictError({file:`${S.docName}${getDocExtension(S.docName)}`}),`rollback`);return}let D=q?.current;if(!D){errorResponse(g,503,`urn:ok:error:rollback-not-configured`,`Shadow repo not configured.`,{handler:`rollback`});return}let{docName:O,commitSha:k}=S,j=se??`.`,F=safeDocPath(O,j);if(`error`in F){errorResponse(g,400,`urn:ok:error:invalid-request`,F.error,{handler:`rollback`});return}let L=shadowGit(D),B=Date.now();try{let s=getOrLoadRenameLogIndex(D.gitDir),S=createAncestorShaSetCache(),E=await resolveDocPathAtCommit(D,O,k,ae?.()??`main`,s,e=>{let t=safeDocPath(e,j);return`error`in t?`${e}.md`:t.path},S);if(E===null){errorResponse(g,404,`urn:ok:error:doc-not-found`,`Commit ${k.slice(0,7)} does not contain document ${O} at any known historical path.`,{handler:`rollback`});return}let F=await L.raw(`show`,`${k}:${E}`),H=new Date().toISOString();await safetyCheckpoint(D,j,{action:`rollback`,context:{docName:O,targetSha:k}});let q=t.documents.get(O);if(!q){errorResponse(g,409,`urn:ok:error:doc-not-open`,`Document is not currently open — open it in the editor first.`,{handler:`rollback`});return}let ee=e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:O}:void 0,J;q.transact(()=>{replaceRawBody(q,F,ee),J=evaluateContentDivergence(q.getText(`source`).toString(),F,`rollback`)},ROLLBACK_ORIGIN),J!==void 0&&console.warn(JSON.stringify({event:`agent-write-content-divergence`,"doc.name":O,position:`rollback`,intendedBytes:J.intendedBytes,actualBytes:J.actualBytes,byteDelta:J.byteDelta,"actor.kind":w.kind,...w.kind===`agent`||w.kind===`principal`?{"actor.writer_id":w.writerId}:{}})),recordContentDivergenceGate(`rollback`,J);let Y;switch(w.kind){case`agent`:{let e=k.slice(0,8),t=w.summary.kind===`value`,s=t?w.summary:normalizeSummary(`Restored to ${e}`),g=Yi(s);Y=t||!g.response?g.response:Xi(g.response),recordContributor(O,w.writerId,w.displayName,w.colorSeed,formatRollbackSubject(O,k),w.actor,g.stored),incrementAgentWriteCalls(),Zi(s,!t);break}case`principal`:{let e=Yi(w.summary);Y=e.response,recordContributor(O,w.writerId,w.displayName,w.colorSeed,formatRollbackSubject(O,k),w.actor,e.stored),Zi(w.summary,!1);break}case`anonymous`:log$6.debug({docName:O,commitSha:k.slice(0,8)},`[rollback] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`);break;default:throw Error(`Unhandled actor kind in handleRollback: ${String(w.kind)}`)}renameAttributionCounter().add(1,{kind:`rollback`,attribution_kind:w.kind});let te=await Ht(O);if(te?.kind===`failure`){Ut(g,te.failure,`rollback`);return}if(te?.kind===`divergence`){Wt(g,`rollback`);return}Vt(O,`rollback`);let ne=Date.now()-B;getLogger(`rollback`).info({docName:O,from:k.slice(0,8),durationMs:ne},`rollback`),w.kind===`agent`&&fe?.setFocus(w.writerId,{agentName:w.displayName,currentDoc:O,writeKind:`rollback-apply`,ts:Date.now()});let oe=J===void 0?void 0:toContentDivergenceWarning(J);successResponse(g,200,RollbackSuccessSchema,{restoredFrom:k,timestamp:H,...Y?{summary:Y}:{},...oe?{warning:oe,warnings:[oe]}:{}},{handler:`rollback`})}catch(e){errorResponse(g,500,`urn:ok:error:internal-server-error`,`Failed to roll back.`,{handler:`rollback`,cause:e})}},{handler:`rollback`,method:`POST`}),hc=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,MetricsReconciliationSuccessSchema,getMetrics(),{handler:`metrics-reconciliation`})}catch(e){log$6.error({err:e},`[metrics-reconciliation] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-reconciliation`,cause:e})}},{handler:`metrics-reconciliation`,method:`GET`,skipBodyParse:!0}),gc=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,MetricsParseHealthSuccessSchema,getParseHealth(),{handler:`metrics-parse-health`})}catch(e){log$6.error({err:e},`[metrics-parse-health] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-parse-health`,cause:e})}},{handler:`metrics-parse-health`,method:`GET`,skipBodyParse:!0}),_c=withValidation(EmptyRequestSchema,async(e,t)=>{try{Me&&await Me.catch(e=>{log$6.warn({err:e,handler:`server-info`},`[api] ready gate rejected — responding with current state`)});let e=getActiveBranch(),s=oe?.();successResponse(t,200,ServerInfoSuccessSchema,{serverInstanceId:S,currentBranch:e,...s===void 0?{}:{currentDiskAckSVs:s}},{handler:`server-info`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`server-info`,cause:e})}},{handler:`server-info`,method:`GET`,skipBodyParse:!0});async function vc(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`principal`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`principal`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`principal`,extraHeaders:{Allow:`GET`}});return}let s=Ce?.()??null;if(!s){errorResponse(t,404,`urn:ok:error:principal-not-available`,`Principal not available.`,{handler:`principal`});return}successResponse(t,200,PrincipalSuccessSchema,s,{handler:`principal`})}async function yc(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`metrics-agent-presence`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`metrics-agent-presence`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`metrics-agent-presence`,extraHeaders:{Allow:`GET`}});return}try{let e=me?.getPresenceMap()??{},s=Date.now(),g={};for(let[t,S]of Object.entries(e))s-S.ts<2e4&&(g[t]=S);successResponse(t,200,MetricsAgentPresenceSuccessSchema,{presence:g},{handler:`metrics-agent-presence`})}catch(e){log$6.error({err:e},`[metrics-agent-presence] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-agent-presence`,cause:e})}}async function bc(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`embed-detect`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`embed-detect`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`embed-detect`,extraHeaders:{Allow:`GET`}});return}let s=embedProbeRing.read();successResponse(t,200,EmbedDetectSuccessSchema,{entries:s,count:s.length,detection:deriveDetection(s[0])},{handler:`embed-detect`})}async function xc(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`workspace`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`workspace`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`workspace`,extraHeaders:{Allow:`GET`}});return}let s=resolve(g),S=s,w=!0;try{S=realpathSync(s)}catch(e){let g=e?.code;if(g===`ENOENT`)console.warn(`[workspace] contentDir does not exist; returning unresolved path`,{path:s}),w=!1;else{console.warn(`[workspace] realpath failed for contentDir`,{path:s,err:e}),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Workspace realpath failed.`,{handler:`workspace`,detail:g??void 0,cause:e});return}}successResponse(t,200,WorkspaceSuccessSchema,{contentDir:S,pathSeparator:sep,symlinkResolved:w},{handler:`workspace`})}let Sc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`path`);if(!s||s.includes(`\0`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing asset path.`,{handler:`asset`});return}let S=assetContentTypeForPath(s),w=extname(s).slice(1).toLowerCase();if(!S||!ASSET_EXTENSIONS.has(w)){errorResponse(t,415,`urn:ok:error:unsupported-asset-type`,`Unsupported asset type.`,{handler:`asset`});return}let E=realpathSync(g),D=resolve(E,s),O;try{O=realpathSync(D)}catch{errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}if(!isWithinContentDir(O,E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset`});return}let k;try{k=statSync(O)}catch{errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}if(!k.isFile()){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}let j=toContentRelativePath(E,O);if(j!==s.split(`\\`).join(`/`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset`});return}if(Te?.isPathIgnored(j)){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}let F=SANDBOXED_HTML_EXTENSIONS.has(w),L={"Content-Type":S,"Content-Length":String(k.size),"X-Content-Type-Options":`nosniff`,"Content-Disposition":INLINE_RENDERABLE_EXTENSIONS.has(w)||F?`inline`:`attachment`,"Cache-Control":`no-store`};w===`svg`?L[`Content-Security-Policy`]=`sandbox; default-src 'none'; style-src 'unsafe-inline'`:F&&(L[`Content-Security-Policy`]=SANDBOXED_HTML_CSP),t.writeHead(200,L);try{await pipeline(createReadStream(O),t)}catch(e){log$6.error({event:`api.asset.pipeline-failed`,handler:`asset`,assetPath:s,err:e},`[asset] pipeline failed mid-stream`),t.destroyed||t.destroy(e instanceof Error?e:void 0)}}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`asset`,cause:e})}},{handler:`asset`,method:`GET`,skipBodyParse:!0}),Cc=1048576,wc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`path`);if(!s||s.includes(`\0`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing asset path.`,{handler:`asset-text`});return}let S=realpathSync(g),w=resolve(S,s),E;try{E=realpathSync(w)}catch(e){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset-text`,cause:e});return}if(!isWithinContentDir(E,S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset-text`});return}let D;try{D=statSync(E)}catch(e){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset-text`,cause:e});return}if(!D.isFile()){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset-text`});return}if(toContentRelativePath(S,E)!==s.split(`\\`).join(`/`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset-text`});return}if(D.size>Cc){errorResponse(t,413,`urn:ok:error:payload-too-large`,`File exceeds the ${Cc}-byte text-viewer cap.`,{handler:`asset-text`});return}let O=(await readFile$1(E)).toString(`utf-8`);t.writeHead(200,{"Content-Type":`text/plain; charset=utf-8`,"X-Content-Type-Options":`nosniff`,"Content-Disposition":`inline`,"Cache-Control":`no-store`}),t.end(O)}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`asset-text`,cause:e})}},{handler:`asset-text`,method:`GET`,skipBodyParse:!0}),Tc=1440*60*1e3,Ec=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!q?.current){successResponse(t,200,RescueListSuccessSchema,[],{handler:`rescue-list`});return}let e=Date.now(),s=[],g=resolve(q.current.gitDir,`rescue`);if(existsSync(g))try{let t=readdirSync(g).filter(e=>isSupportedDocFile(e));for(let S of t){let t=resolve(g,S),w=statSync(t);if(e-w.mtimeMs>864e5){try{unlinkSync(t)}catch(e){console.debug(`[rescue] cleanup failed (non-critical):`,e)}continue}s.push({docName:stripDocExtension(S),timestamp:w.mtime.toISOString(),size:w.size,source:`flat`})}}catch(e){log$6.error({err:e},`[rescue] Failed to list flat-file rescue buffers`)}try{let e=ae?.()??`main`,t=await listRescueCheckpoints(q.current,e);for(let e of t)s.push({...e,source:`timeline`})}catch(e){log$6.error({err:e},`[rescue] Failed to list timeline-ref rescue checkpoints`)}successResponse(t,200,RescueListSuccessSchema,s,{handler:`rescue-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`rescue-list`,cause:e})}},{handler:`rescue-list`,method:`GET`,skipBodyParse:!0}),Dc=withValidation(CreatePageRequestSchema,async(e,t,s)=>{try{let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`create-page`});return}let S=s.path;if(!isSupportedDocFile(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must end with .md or .mdx.`,{handler:`create-page`});return}if(S.includes(`..`)||S.startsWith(`/`)||S.includes(`\0`)||S.includes(`\\`)){errorResponse(t,400,`urn:ok:error:path-escape`,`Invalid path.`,{handler:`create-page`,detail:`path must not contain .. or start with /`});return}let w=resolve(g),E=resolve(w,S);if(!isWithinDir(E,w)){errorResponse(t,400,`urn:ok:error:path-escape`,`path must not escape content directory.`,{handler:`create-page`});return}let O=stripDocExtension(S);if(isSystemDoc(O)||isConfigDoc(O)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${O}' is a reserved document name.`,{handler:`create-page`});return}if(S.split(`/`)[0]===`.ok`||isManagedArtifactDocName(O)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${O}' is a reserved document name.`,{handler:`create-page`,detail:`Cannot create a page under .ok/ — skills and templates are authored through their own validating flows.`});return}let k=typeof s.template==`string`?s.template.trim():``,j=``,F;if(k.length>0){if(!/^[A-Za-z0-9_-]+$/.test(k)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Template name must match [A-Za-z0-9_-]+.`,{handler:`create-page`});return}let s=S.includes(`/`)?S.slice(0,S.lastIndexOf(`/`)):``,g=resolveTemplatesAvailable(w,s),E=g.find(e=>e.name===k);if(!E){let e=g.length===0?`(none)`:g.map(e=>`"${e.name}" (${e.scope})`).join(`, `);errorResponse(t,400,`urn:ok:error:invalid-request`,`Template "${k}" does not resolve for folder "${s||`(root)`}". Available: ${e}`,{handler:`create-page`});return}let D=resolve(w,E.path),O;try{O=readFileSync(D,`utf-8`)}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template at ${E.path}.`,{handler:`create-page`,cause:e});return}let L=instantiateDoc(O),B=e.kind===`agent`||e.kind===`principal`?e.displayName??``:``;j=applySubstitution(L,{date:todayIsoUtc(),user:B}),F=E.scope}mkdirSync(dirname(E),{recursive:!0});try{writeFileSync(E,j,{encoding:`utf-8`,flag:`wx`})}catch(e){if(isAlreadyExistsError(e)){errorResponse(t,409,`urn:ok:error:doc-already-exists`,`File already exists.`,{handler:`create-page`,cause:e});return}throw e}let L=stripDocExtension(S);switch(Pe?.delete(L),Te&&Te.incrementMdDir(dirname(L)),registerWrite(E,contentHash(j)),e.kind){case`agent`:case`principal`:recordContributor(L,e.writerId,e.displayName,e.colorSeed,void 0,e.actor);break;case`anonymous`:break;default:throw Error(`Unhandled actor kind in handleCreatePage: ${String(e.kind)}`)}D?.({kind:`create`,path:E,docName:L,content:j}),ce&&(ce.updateDocumentFromMarkdown(L,j),ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist create-page cache for ${L}:`,e)}),de?.(`backlinks`),de?.(`graph`)),de?.(`files`),F!==void 0&&console.warn(JSON.stringify({event:`template-instantiate`,templateName:k,templateScope:F,docName:L})),successResponse(t,200,CreatePageSuccessSchema,{docName:L},{handler:`create-page`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to create page.`,{handler:`create-page`,cause:e})}},{handler:`create-page`,method:`POST`}),Oc=withValidation(CreateFolderRequestSchema,async(e,t,s)=>{try{if(extractActorIdentity(s,Ce).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`create-folder`});return}let e=s.path;if(!isValidRelativeContentPath(e)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`create-folder`});return}if(e===`.ok`||e.startsWith(`.ok/`)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'.ok' is a reserved directory.`,{handler:`create-folder`});return}if(Te?.isDirExcluded(e)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Destination folder is excluded by the workspace content config.`,{handler:`create-folder`});return}let S=resolveContentEntryPath(g,`folder`,e);if(existsSync(S)){errorResponse(t,409,`urn:ok:error:doc-already-exists`,`Folder already exists.`,{handler:`create-folder`});return}tracedMkdirSync(S,{recursive:!0}),rt(e),de?.(`files`),successResponse(t,200,CreateFolderSuccessSchema,{path:e},{handler:`create-folder`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to create folder.`,{handler:`create-folder`,cause:e})}},{handler:`create-folder`,method:`POST`}),kc=withValidation(DuplicatePathRequestSchema,async(e,s,S)=>{try{let e=extractActorIdentity(S,Ce);if(e.kind===`invalid-summary`){errorResponse(s,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`duplicate-path`});return}let{kind:w}=S,E=w===`file`?stripDocExtension(S.path):S.path;if(!isValidRelativeContentPath(E)){errorResponse(s,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`duplicate-path`});return}if(E===`.ok`||E.startsWith(`.ok/`)||w===`file`&&(isSystemDoc(E)||isConfigDoc(E))||w===`folder`&&isReservedSyntheticFolderPath(E)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`Reserved paths cannot be duplicated.`,{handler:`duplicate-path`});return}w===`file`&&probeAndRegisterSourceFileExtension(g,E);let O=resolveContentEntryPath(g,w,E);if(!existsSync(O)){if(w===`file`){let e=resolveContentEntryPath(g,`folder`,E);if(existsSync(e)&&statSync(e).isDirectory()){errorResponse(s,400,`urn:ok:error:invalid-request`,`Target path is not a ${w}.`,{handler:`duplicate-path`});return}}errorResponse(s,404,`urn:ok:error:doc-not-found`,`${w} does not exist.`,{handler:`duplicate-path`});return}let k=statSync(O);if(w===`file`&&!k.isFile()||w===`folder`&&!k.isDirectory()){errorResponse(s,400,`urn:ok:error:invalid-request`,`Target path is not a ${w}.`,{handler:`duplicate-path`});return}let j=w===`file`?[E]:Zr(resolveContentEntryPath(g,`folder`,E)),F=_e?.(),L=new Set(F?F.getConflicts().map(e=>e.file):[]);for(let e of j){let g=stripDocExtension(e),S=t.documents.get(g),w=`${g}${getDocExtension(g)}`,E=S!==void 0&&isDocInConflict(S),D=L.has(w);if(E||D){respondDocInConflict(s,new DocInConflictError({file:w}),`duplicate-path`);return}}let B,H=[];if(w===`file`){let e=extname(O);if(B=nextAvailableDuplicateDocName(g,E).docName,isSystemDoc(B)||isConfigDoc(B)||Te?.isExcluded(`${B}${e}`)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Duplicated document destination is excluded by the project content config.`,{handler:`duplicate-path`});return}let t=resolveDuplicateDocPath(g,B,e),S=readFileSync(O,`utf-8`),w=dirname(t),k=existsSync(w);try{tracedMkdirSync(w,{recursive:!0}),tracedWriteFileSync(t,S,{encoding:`utf-8`,flag:`wx`})}catch(e){if(isAlreadyExistsError(e)){errorResponse(s,409,`urn:ok:error:doc-already-exists`,`A file at the duplicate destination already exists.`,{handler:`duplicate-path`,cause:e});return}if(!k)try{tracedRmdirSync(w)}catch(e){let t=e.code;t!==`ENOENT`&&t!==`ENOTEMPTY`&&console.warn(`[duplicate-path] failed to clean duplicate parent directory:`,{destinationDir:w,err:e})}throw e}let j=!1;try{registerDocExtension(B,e),Pe?.delete(B),Te&&(Te.incrementMdDir(dirname(B)),j=!0),registerWrite(t,contentHash(S)),D?.({kind:`create`,path:t,docName:B,content:S}),ce?.updateDocumentFromMarkdown(B,S),H=[B]}catch(e){try{tracedRmSync(t,{force:!0})}catch(e){console.warn(`[duplicate-path] failed to clean partial file duplicate:`,{destinationPath:t,err:e})}throw forgetDocExtension(B),Te&&j&&Te.decrementMdDir(dirname(B)),D?.({kind:`delete`,path:t,docName:B}),e}}else{if(B=nextAvailableDuplicateFolderPath(g,E).folderPath,Te?.isDirExcluded(B)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Duplicated folder destination is excluded by the project content config.`,{handler:`duplicate-path`});return}let e=resolveContentEntryPath(g,`folder`,B);try{tracedCpSync(O,e,{recursive:!0,errorOnExist:!0,force:!1})}catch(e){if(isAlreadyExistsError(e)){errorResponse(s,409,`urn:ok:error:doc-already-exists`,`A folder at the duplicate destination already exists.`,{handler:`duplicate-path`,cause:e});return}throw e}try{for(let e of collectFolderPaths(g,B))rt(e);let e=collectMarkdownCopies(g,B);H=e.map(e=>e.docName);for(let t of e){let e=extname(t.fullPath);registerDocExtension(t.docName,e),Pe?.delete(t.docName),Te&&Te.incrementMdDir(dirname(t.docName)),registerWrite(t.fullPath,contentHash(t.content)),D?.({kind:`create`,path:t.fullPath,docName:t.docName,content:t.content}),ce?.updateDocumentFromMarkdown(t.docName,t.content)}}catch(t){try{tracedRmSync(e,{recursive:!0,force:!0})}catch(t){console.warn(`[duplicate-path] failed to clean partial folder duplicate:`,{destinationPath:e,err:t})}throw t}}switch(e.kind){case`agent`:case`principal`:for(let t of H)recordContributor(t,e.writerId,e.displayName,e.colorSeed,void 0,e.actor);break;case`anonymous`:break;default:throw Error(`Unhandled actor kind in handleDuplicatePath: ${String(e.kind)}`)}ce&&H.length>0&&(ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist duplicate-path cache:`,e)}),de?.(`backlinks`),de?.(`graph`)),de?.(`files`),successResponse(s,200,DuplicatePathSuccessSchema,{kind:w,path:B,duplicatedDocNames:H},{handler:`duplicate-path`})}catch(e){if(e instanceof DuplicateNameExhaustedError){errorResponse(s,409,`urn:ok:error:doc-already-exists`,`All available duplicate name slots are occupied for this path.`,{handler:`duplicate-path`,cause:e});return}let t=classifyDuplicatePathFilesystemProblem(e);if(t){errorResponse(s,t.status,t.type,t.title,{handler:`duplicate-path`,cause:e});return}errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to duplicate path.`,{handler:`duplicate-path`,cause:e})}},{handler:`duplicate-path`,method:`POST`}),Ac=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!s||s.length===0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName query parameter.`,{handler:`page-headings`});return}if(!isSafeDocName(s)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`page-headings`});return}let g=Et(s);if(!g){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`page-headings`});return}if(!existsSync(g)){errorResponse(t,404,`urn:ok:error:doc-not-found`,`Page not found.`,{handler:`page-headings`});return}successResponse(t,200,PageHeadingsSuccessSchema,{docName:s,headings:extractHeadings(readFileSync(g,`utf-8`))},{handler:`page-headings`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read headings.`,{handler:`page-headings`,cause:e})}},{handler:`page-headings`,method:`GET`,skipBodyParse:!0}),jc=withValidation(RenamePathRequestSchema,async(e,s,S)=>{try{let e=extractActorIdentity(S,Ce);if(e.kind===`invalid-summary`){errorResponse(s,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`rename-path`});return}let{kind:w,fromPath:E,toPath:D}=S;if(!isValidRelativeContentPath(E)||!isValidRelativeContentPath(D)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Paths must be relative content paths.`,{handler:`rename-path`});return}if(w===`file`&&(isSystemDoc(E)||isSystemDoc(D)||isConfigDoc(E)||isConfigDoc(D))){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`Reserved document names cannot be renamed.`,{handler:`rename-path`});return}if(E===`.ok`||E.startsWith(`.ok/`)||D===`.ok`||D.startsWith(`.ok/`)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`.ok is a reserved directory.`,{handler:`rename-path`});return}if(E===D){successResponse(s,200,RenamePathSuccessSchema,{renamed:[],renamedAssets:[],rewrittenDocs:[]},{handler:`rename-path`});return}let O=w===`asset`&&isSupportedDocFile(E)&&isSupportedDocFile(D)?`file`:w;if(O===`asset`){let t;try{t=isSupportedDocFile(E)&&!isSupportedDocFile(D)?await Hi(E,D):await ji(E,D)}catch(e){if(e instanceof DocInConflictError){respondDocInConflict(s,e,`rename-path`);return}let{status:t,type:g,error:S}=Ir(e);errorResponse(s,t,g,S,{handler:`rename-path`,cause:e});return}t.renamedAssets.length>0&&vt();let g;if(t.renamedAssets.length>0&&t.rewrittenDocs.length>0){let s=`Renamed asset ${E} → ${D}`;g=ka(e,s,t.rewrittenDocs.map(({docName:e})=>({docName:e,subject:s})),{context:`handleRenamePath asset branch`,onAnonymous:()=>{log$6.debug({kind:`asset`,fromPath:E,toPath:D,affectedDocs:t.rewrittenDocs.length,affectedAssets:t.renamedAssets.length},`[rename-path] anonymous actor; no contributor recorded (no agentId in body and getPrincipal() returned null)`)}})}if(renameAttributionCounter().add(1,{kind:`rename-asset`,attribution_kind:e.kind}),J)try{await J()}catch(e){console.warn(`[rename-path] flushContributors failed after asset rename (commitSha backfill may be deferred):`,e)}successResponse(s,200,RenamePathSuccessSchema,{renamed:[],renamedAssets:t.renamedAssets,rewrittenDocs:t.rewrittenDocs,...g?{summary:g}:{}},{handler:`rename-path`});return}let k=O===`file`?[stripDocExtension(E)]:Zr(resolveContentEntryPath(g,`folder`,E)),j=_e?.(),F=new Set(j?j.getConflicts().map(e=>e.file):[]);for(let e of k){let g=stripDocExtension(e),S=t.documents.get(g),w=O===`file`?E:`${g}${getDocExtension(e)}`,D=S!==void 0&&isDocInConflict(S),k=F.has(w);if(D||k){respondDocInConflict(s,new DocInConflictError({file:w}),`rename-path`);return}}if(O===`file`&&probeAndRegisterSourceFileExtension(g,E),Te&&(O===`file`?Te.isExcluded(isSupportedDocFile(D)?D:`${D}${getDocExtension(E)}`):Te.isDirExcluded(D))){errorResponse(s,400,`urn:ok:error:invalid-request`,`Destination ${O===`file`?`document`:`folder`} is excluded by the project content config.`,{handler:`rename-path`});return}let L=e.kind===`agent`||e.kind===`principal`?{writerId:e.writerId,displayName:e.displayName,colorSeed:e.colorSeed,actorMetadata:e.actor}:void 0,B;try{B=await Ui(E,D,O,L?{actor:L}:{})}catch(e){if(e instanceof ManagedRenameCollisionError){errorResponse(s,409,`urn:ok:error:doc-already-exists`,Fr(e.message),{handler:`rename-path`,extensions:{colliding:e.colliding},cause:e});return}throw e}if(B.renamed.length===0&&B.renamedAssets.length===0){successResponse(s,200,RenamePathSuccessSchema,{renamed:[],renamedAssets:[],rewrittenDocs:[]},{handler:`rename-path`});return}B.renamedAssets.length>0&&vt();let H,q=B.renamed.filter(({fromDocName:e,toDocName:t})=>e!==t);if(q.length>0&&(H=ka(e,`Renamed ${E} → ${D}`,q.map(({fromDocName:e,toDocName:t})=>({docName:t,subject:formatRenameSubject(e,t)})),{context:`handleRenamePath`,onAnonymous:()=>{log$6.debug({kind:w,fromPath:E,toPath:D,affectedDocs:B.renamed.length},`[rename-path] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`)}})),renameAttributionCounter().add(1,{kind:`rename-${O}`,attribution_kind:e.kind}),J)try{await J()}catch(e){console.warn(`[rename-path] flushContributors failed (commitSha backfill may be deferred):`,e)}successResponse(s,200,RenamePathSuccessSchema,{renamed:B.renamed,renamedAssets:B.renamedAssets,rewrittenDocs:B.rewrittenDocs,...H?{summary:H}:{}},{handler:`rename-path`})}catch(e){let{status:t,type:g,error:S}=Ir(e);errorResponse(s,t,g,S,{handler:`rename-path`,cause:e})}},{handler:`rename-path`,method:`POST`}),Mc=withValidation(DeletePathRequestSchema,async(e,s,S)=>{try{Gi(S);let{kind:e,path:w}=S;if(!isValidRelativeContentPath(w)){errorResponse(s,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`delete-path`});return}let E=e===`asset`?Xr(w):{path:w,ambiguous:!1};if(E.ambiguous){errorResponse(s,400,`urn:ok:error:invalid-request`,`Asset path without an extension matches multiple files.`,{handler:`delete-path`});return}let O=E.path,k=e===`asset`&&isSupportedDocFile(O)?`file`:e;if(k===`file`&&probeAndRegisterSourceFileExtension(g,O),k===`asset`&&isReservedProjectStatePath(O)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`.ok and .git are reserved directories.`,{handler:`delete-path`});return}let j=k===`asset`?resolveContentEntryPath(g,`folder`,O):resolveContentEntryPath(g,k,O);if(!existsSync(j)){errorResponse(s,404,`urn:ok:error:doc-not-found`,`${k} does not exist.`,{handler:`delete-path`});return}let F=statSync(j);if(k===`file`&&!F.isFile()||k===`asset`&&!F.isFile()||k===`folder`&&!F.isDirectory()){errorResponse(s,400,`urn:ok:error:invalid-request`,`Target path is not a ${k}.`,{handler:`delete-path`});return}let L=k===`asset`?[]:k===`file`?[stripDocExtension(O)]:Zr(resolveContentEntryPath(g,`folder`,O)),B=_e?.(),H=new Set(B?B.getConflicts().map(e=>e.file):[]);for(let e of L){let g=stripDocExtension(e),S=t.documents.get(g),w=k===`file`&&isSupportedDocFile(O)?O:`${g}${getDocExtension(g)}`,E=S!==void 0&&isDocInConflict(S),D=H.has(w);if(E||D){respondDocInConflict(s,new DocInConflictError({file:w}),`delete-path`);return}}if(await Lr(L),Pe)for(let e of L)isSystemDoc(e)||isConfigDoc(e)||(Pe.setDeleted(e),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:e,kind:`deleted`,source:`handleDeletePath`})));k===`file`||k===`asset`?tracedUnlinkSync(j):(tracedRmSync(j,{recursive:!0,force:!1}),it(O)),vt();for(let e of L)D?.({kind:`delete`,path:resolve(g,`${e}${getDocExtension(e)}`),docName:e});de?.(`files`),successResponse(s,200,DeletePathSuccessSchema,{deletedDocNames:L},{handler:`delete-path`})}catch(e){errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to delete path.`,{handler:`delete-path`,cause:e})}},{handler:`delete-path`,method:`POST`}),Nc=withValidation(TrashCleanupRequestSchema,async(e,t,s)=>withSpan(`ok.fs.trash_cleanup`,{attributes:{"ok.cleanup.kind":s.kind,"ok.cleanup.path":normalizeFsPath(s.path),"ok.cleanup.path.role":classifyFsPath(s.path)}},async()=>{try{if(extractActorIdentity(s,Ce).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`trash-cleanup`});return}let{kind:e,path:S}=s;if(!isValidRelativeContentPath(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`trash-cleanup`});return}let E=e===`asset`&&isSupportedDocFile(S)?`file`:e,O=stripDocExtension(S);E===`file`&&probeAndRegisterSourceFileExtension(g,S);let k=E===`folder`&&isReservedSyntheticFolderPath(S),j=E===`asset`&&isReservedProjectStatePath(S);if(E===`file`&&(isSystemDoc(O)||isConfigDoc(O))||k||j){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${S}' is a reserved document name.`,{handler:`trash-cleanup`});return}if(E===`asset`){vt(),de?.(`files`),successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:[]},{handler:`trash-cleanup`});return}let F=w(),L=E===`file`?F.has(O)?[O]:[]:listAffectedDocNames(F,E,S);if(vt(),L.length===0){successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:[]},{handler:`trash-cleanup`});return}if(await Lr(L),Pe)for(let e of L)isSystemDoc(e)||isConfigDoc(e)||(Pe.setDeleted(e),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:e,kind:`deleted`,source:`handleTrashCleanup`})));for(let e of L)D?.({kind:`delete`,path:resolve(g,`${e}${getDocExtension(e)}`),docName:e});E===`folder`&&it(S),de?.(`files`),successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:L},{handler:`trash-cleanup`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to clean up after trash.`,{handler:`trash-cleanup`,cause:e})}}),{handler:`trash-cleanup`,method:`POST`}),Pc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=w(),s=[];for(let[t,S]of e){let e=t,w,E=getDocExtension(t);try{let s=readFileSync(resolve(g,`${t}${E}`),`utf-8`);e=extractPageTitle(s,t),w=extractPageIcon(s)}catch(e){console.warn(`[pages] Failed to read title for ${t}:`,e)}s.push({docName:t,title:e,docExt:E,size:S.size,modified:S.modified,icon:w})}s.sort((e,t)=>e.docName.localeCompare(t.docName)),successResponse(t,200,PagesSuccessSchema,{pages:s},{handler:`pages`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list pages.`,{handler:`pages`,cause:e})}},{handler:`pages`,method:`GET`,skipBodyParse:!0}),Fc=withValidation(EmptyRequestSchema,async(e,s)=>{try{let g=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!g){errorResponse(s,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`suggest-links`});return}if(!isSafeDocName(g)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`suggest-links`});return}if(isSystemDoc(g)||isConfigDoc(g)){errorResponse(s,400,`urn:ok:error:reserved-doc-name`,`'${g}' is a reserved document name.`,{handler:`suggest-links`});return}successResponse(s,200,SuggestLinksSuccessSchema,await suggestLinks({hocuspocus:t,fileIndex:w(),docName:g}),{handler:`suggest-links`})}catch(e){if(e instanceof SuggestLinksTargetNotFoundError){errorResponse(s,404,`urn:ok:error:doc-not-found`,`Page not found.`,{handler:`suggest-links`,cause:e});return}errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to suggest links.`,{handler:`suggest-links`,cause:e})}},{handler:`suggest-links`,method:`GET`,skipBodyParse:!0});async function Ic(e,t){if(e.method!==`POST`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`upload-asset`,extraHeaders:{Allow:`POST`}});return}let s;try{s=await readUploadBody(e,ye??g)}catch(e){if(e instanceof UploadWriteError){errorResponse(t,uploadStatusFor(e.reason),e.reason,uploadTitleFor(e.reason),{handler:`upload-asset`,cause:e});return}errorResponse(t,400,`urn:ok:error:malformed-upload`,`Failed to parse upload.`,{handler:`upload-asset`,cause:e});return}let{filename:S,tempPath:w,sha:E,byteLength:D,parentDocName:O}=s,k=()=>{if(existsSync(w))try{unlinkSync(w)}catch{}},j=validateBody(UploadRequestSchema,{parentDocName:O},t,{handler:`upload-asset`});if(!j.ok){k();return}let{parentDocName:F}=j.value,{agentId:L,agentName:B}=Gi(Object.fromEntries(new URL(e.url??``,`http://localhost`).searchParams.entries()));if(D===0){k(),errorResponse(t,400,`urn:ok:error:no-file-received`,`No file received.`,{handler:`upload-asset`});return}if(F.includes(`\0`)||F.includes(`..`)||F.startsWith(`/`)){k(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}let H=resolve(g),q=resolveUploadDestDir(F,`./`,H);if(!isWithinContentDir(q,H)){k(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}try{assertNoSymlinkEscape(q,H)}catch(e){if(k(),(e instanceof Error?e.message:String(e)).startsWith(`symlink-escape:`)){errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}log$6.error({err:e,destDir:q},`[upload] failed to validate destination directory`),errorResponse(t,500,`urn:ok:error:storage-error`,`Storage error.`,{handler:`upload-asset`,cause:e});return}try{mkdirSync(q,{recursive:!0})}catch(e){if(!isAlreadyExistsError(e)){k();let s=classifyUploadErrno(e);errorResponse(t,uploadStatusFor(s),s,uploadTitleFor(s),{handler:`upload-asset`,cause:e,detail:`failed to create attachment directory`});return}}try{let e=realpathSync(q),s;try{s=realpathSync(H)}catch{s=H}if(!isWithinContentDir(e,s)){k(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}}catch(e){if(e.code!==`ENOENT`){k(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`,cause:e});return}}let ee=await fileTypeFromFile(w),J=ee?.mime,Y=ee?.ext;if(!J){let e=readTempFileHead(w,256).toString(`utf-8`).replace(/^/,``).trimStart();(e.startsWith(`<svg`)||e.startsWith(`<?xml`)&&e.includes(`<svg`))&&(J=`image/svg+xml`,Y=`svg`)}{let s=await findDuplicateAsset(q,E,D);if(s){k();let S=toPosix(relative(g,resolve(q,s)));log$6.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:L,agentName:B,dedup:!0,mime:J??null,size:D,destPath:S,httpStatus:200},`[upload] dedup hit`),successResponse(t,200,UploadAssetSuccessSchema,{src:s,path:S,deduped:!0},{handler:`upload-asset`});return}}let te;if(!S||S===`upload`||GENERIC_PASTE_NAMES.test(S)){let e=new Date().toISOString().replace(/[-:T]/g,``).slice(0,14).replace(/(\d{8})(\d{6})/,`$1-$2`),t=S?extname(S).slice(1):``,s=Y??t??``;te=s===``?`pasted-${e}`:`pasted-${e}.${s}`}else te=sanitizeFilename(S);try{let s=linkTempToFinalWithCollisionRetry(w,q,te),S=toPosix(relative(g,resolve(q,s)));log$6.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:L,agentName:B,dedup:!1,mime:J??null,size:D,destPath:S,httpStatus:200},`[upload] write ok`),successResponse(t,200,UploadAssetSuccessSchema,{src:s,path:S,deduped:!1},{handler:`upload-asset`})}catch(s){let g=s instanceof UploadWriteError?s.reason:`urn:ok:error:storage-error`;log$6.error({event:`upload`,endpoint:e.url??`/api/upload`,agentId:L,agentName:B,filename:te,size:D,reason:g,httpStatus:uploadStatusFor(g),err:s},`[upload] write failed`),errorResponse(t,uploadStatusFor(g),g,uploadTitleFor(g),{handler:`upload-asset`,cause:s})}}let Lc=`/api/local-op/clone`,Rc=`/api/local-op/ok-init`,zc=600*1e3,Bc=45e3,Vc=`local-op-clone`,Hc=withValidation(LocalOpCloneRequestSchema,Uc,{handler:Vc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Vc})});async function Uc(e,t,s){let{url:g,dir:S,branch:w}=s;if(!isAllowedGitUrl(g)){errorResponse(t,400,`urn:ok:error:url-not-allowed`,`URL protocol is not allowed for clone.`,{handler:Vc,cause:Error(`url=${g}`)});return}if(!isSafeLocalPath(S)){errorResponse(t,400,`urn:ok:error:dir-outside-home`,`Clone destination must be within the user home directory.`,{handler:Vc,cause:Error(`dir=${S}`)});return}if(!We.tryAcquire(Lc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A clone operation is already in progress.`,{handler:Vc,extraHeaders:{"Retry-After":`30`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let E=createStreamingErrorWriter(t,Vc),D=null,O=runCloneSubprocess({cliArgs:ve,url:g,dir:S,branch:w,timeoutMs:zc,onEvent:e=>{if(e.type===`complete`){D=e.dir;return}if(e.type===`error`){e.message&&log$6.warn({stderr:redactShareSubprocessStderr(e.message),url:g,dir:S},`[local-op/clone] clone failed`);let t=classifyCloneError(e.message??``);E(500,`urn:ok:error:clone-failed`,t.title,{detail:t.detail||void 0,cause:e.message?Error(redactShareSubprocessStderr(e.message)):void 0});return}if(!t.writableEnded&&!t.destroyed)try{t.write(`${JSON.stringify(e)}\n`)}catch{}}});(async()=>{try{if(await O.done,D&&!t.writableEnded&&!t.destroyed){let e=await Wc(D);!t.writableEnded&&!t.destroyed&&(`port`in e?t.write(`${JSON.stringify({type:`complete`,port:e.port,dir:D})}\n`):E(500,`urn:ok:error:server-start-failed`,`Cloned successfully but failed to start the project server.`,{cause:Error(e.error)}))}}catch(e){!t.writableEnded&&!t.destroyed?E(500,`urn:ok:error:internal-server-error`,`Unexpected error during clone post-processing.`,{cause:e}):log$6.error({err:e,handler:Vc},`clone IIFE rejected after stream ended`)}finally{t.writableEnded||t.end(),We.release(Lc)}})(),t.on(`close`,()=>{O.cancel()})}async function Wc(e,t){let s=resolve(expandTilde(e)),g=getLocalDir(s),S=readUiLock(g);if(S&&S.port>0)return{port:S.port};let[w,...E]=ve,D=e=>{let s=t===void 0?[]:e===`ui`?[`--port`,String(t)]:[`--ui-port`,String(t)];return[...E,e,...s]},O=async e=>{let t=spawn(w,D(e),{cwd:s,detached:!0,stdio:[`ignore`,`ignore`,`pipe`],env:{...process.env,OK_LOCK_KIND:`interactive`}}),S=[];t.stderr?.on(`data`,t=>{S.push(t),log$6.warn({cwd:s,cliCmd:e,msg:t.toString(`utf-8`).trim()},`[local-op/clone] child stderr`)});let E=null,O=null,k=null;t.on(`exit`,(e,t)=>{E=e??-1,O=t??null}),t.on(`error`,t=>{k=t.message,E=-1,log$6.error({cwd:s,cliCmd:e,err:t.message},`[local-op/clone] failed to spawn child`)}),t.unref();let j=Date.now()+45e3;for(;Date.now()<j;){await setTimeout$1(500);let t=readUiLock(g);if(t&&t.port>0)return{port:t.port};if(E!==null){let t=Buffer.concat(S).toString(`utf-8`).trim();return{error:`\`ok ${e}\` exited (${k?`spawn failed: ${k}`:O?`killed by ${O}`:`code ${E}`})${t?` — ${t}`:``}`,exited:!0}}}let F=Buffer.concat(S).toString(`utf-8`).trim();return{error:`UI did not start within the expected time${F?` — ${F}`:``}`,exited:!1}},k=readServerLock(g),j=k&&k.port>0?`ui`:`start`,F=await O(j);if(j===`start`&&`error`in F&&F.exited){let e=readServerLock(g);if(e&&e.port>0){let e=await O(`ui`);return`port`in e?e:{error:`${F.error}; connect fallback failed: ${e.error}`}}}return`port`in F?F:{error:F.error}}let Gc=`local-op-ok-init`,Kc=withValidation(LocalOpOkInitRequestSchema,async(e,t,s)=>{let{projectPath:g}=s;if(!isAbsolute(g)){errorResponse(t,400,`urn:ok:error:invalid-request`,`projectPath must be an absolute path.`,{handler:Gc,cause:Error(`projectPath=${g}`)});return}let S;try{S=realpathSync(g)}catch(e){successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!1,reason:`not-a-git-worktree`,message:`projectPath does not exist or is not accessible: ${e.message}`},{handler:Gc});return}if(!isSafeLocalPath(S)){errorResponse(t,400,`urn:ok:error:dir-outside-home`,`projectPath must be within the user home directory.`,{handler:Gc,cause:Error(`projectPath=${g}`)});return}let w=resolveGitDirDetailed(S).kind;if(w!==`directory`&&w!==`linked`){console.warn(`[ok-init] action=init project=${basename(S)} result=not-a-git-worktree kind=${w}`),successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!1,reason:`not-a-git-worktree`,message:`projectPath is not a git working tree (.git is ${w}).`},{handler:Gc});return}if(isProjectRoot(S)){console.warn(`[ok-init] action=init project=${basename(S)} result=already-initialized`),successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!0,projectPath:S},{handler:Gc});return}if(!We.tryAcquire(Rc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An ok-init operation is already in progress.`,{handler:Gc,extraHeaders:{"Retry-After":`2`}});return}try{await withParentLock(async()=>{initContent(S)}),console.warn(`[ok-init] action=init project=${basename(S)} result=success`),successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!0,projectPath:S},{handler:Gc})}catch(e){let s=e instanceof Error?e.message:String(e);console.warn(`[ok-init] action=init project=${basename(S)} result=failed reason=${s}`),successResponse(t,200,LocalOpOkInitResponseSchema,{ok:!1,reason:`init-failed`,message:s},{handler:Gc})}finally{We.release(Rc)}},{handler:Gc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Gc})}),qc=`/api/local-op/auth/login`,Jc=`/api/local-op/auth/status`,Yc=`/api/local-op/auth/repos`,Xc=`/api/local-op/auth/signout`,Zc=null,Qc=`local-op-auth-login`,$c=withValidation(LocalOpAuthHostRequestSchema,nl,{handler:Qc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Qc})});async function nl(e,t,s){let g=s.host??`github.com`;if(!We.tryAcquire(qc)){let e=Zc;if(!e){console.error(JSON.stringify({event:`ok-local-op:auth-login-slot-no-controller`,channel:`auth`,transport:`http`})),errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth login operation is already in progress.`,{handler:Qc,extraHeaders:{"Retry-After":`5`}});return}e.cancel(),Zc=null,console.warn(JSON.stringify({event:`ok-local-op:idempotent-start-replaced-stale-slot`,channel:`auth`,transport:`http`}))}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let S=createStreamingErrorWriter(t,Qc),w=runDeviceFlowSubprocess({cliArgs:ve,host:g,timeoutMs:zc,onEvent:e=>{if(e.type===`error`){S(500,`urn:ok:error:auth-failed`,`Auth subprocess reported an error.`,{cause:e.message?Error(e.message):void 0});return}if(resumeSyncOnAuthEvent(e,_e),!t.writableEnded&&!t.destroyed)try{t.write(`${JSON.stringify(e)}\n`)}catch{}}});Zc=w;let E=()=>{w.cancel(),Zc===w&&(Zc=null,We.release(qc))};t.on(`close`,E),w.done.finally(()=>{if(t.off(`close`,E),!t.writableEnded&&!t.destroyed)try{t.end()}catch{}Zc===w&&(Zc=null,We.release(qc))})}let il=`local-op-auth-status`,al=withValidation(LocalOpAuthHostRequestSchema,async(e,t,s)=>{let g=s.host??`github.com`;if(!We.tryAcquire(Jc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth status operation is already in progress.`,{handler:il,extraHeaders:{"Retry-After":`5`}});return}try{let[e,...s]=ve,S=[...s,`auth`,`status`,`--json`,`--host`,g],w=(await new Promise((t,s)=>{let g=spawn(e,S,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),w=!1,E=setTimeout(()=>{w=!0,g.kill(`SIGTERM`)},3e4),D=[];g.stdout.on(`data`,e=>D.push(e)),g.on(`close`,()=>{if(clearTimeout(E),w){s(Error(`auth status subprocess timed out after 30s`));return}t(Buffer.concat(D).toString(`utf-8`))}),g.on(`error`,e=>{clearTimeout(E),s(e)})})).split(`
1941
+ `).map(e=>e.trim()).filter(Boolean),E=null;for(let e=w.length-1;e>=0;e--)try{E=JSON.parse(w[e]);break}catch{}E===null?successResponse(t,200,LocalOpAuthStatusSuccessSchema,{authenticated:!1},{handler:il}):successResponse(t,200,LocalOpAuthStatusSuccessSchema,E,{handler:il})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth status check failed.`,{handler:il,cause:e})}finally{We.release(Jc)}},{handler:il,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:il})}),cl=`local-op-auth-repos`,ll=withValidation(LocalOpAuthHostRequestSchema,ul,{handler:cl,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:cl})});async function ul(e,t,s){let g=s.host??`github.com`;if(!We.tryAcquire(Yc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth repos operation is already in progress.`,{handler:cl,extraHeaders:{"Retry-After":`5`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let S=createStreamingErrorWriter(t,cl),[w,...E]=ve,D=[...E,`auth`,`repos`,`--json`,`--host`,g],O=!1,k=``,j=spawn(w,D,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),F=setTimeout(()=>{j.kill(`SIGTERM`)},zc);j.stdout.on(`data`,e=>{k+=e.toString(`utf-8`);let s=k.split(`
1942
+ `);k=s.pop()??``;for(let e of s){if(!e.trim())continue;let s=null;try{s=JSON.parse(e)}catch{}if(s&&s.type===`error`){S(500,`urn:ok:error:auth-failed`,`Auth repos subprocess reported an error.`,{detail:typeof s.message==`string`?s.message:void 0});continue}if(!t.writableEnded&&!t.destroyed)try{t.write(`${e}\n`)}catch{}}}),j.stderr.on(`data`,e=>{log$6.debug({msg:e.toString(`utf-8`).trim()},`[local-op/auth/repos] stderr`)}),j.on(`close`,e=>{clearTimeout(F),O||(O=!0,e!==0&&!t.writableEnded&&S(500,`urn:ok:error:auth-failed`,`Auth repos subprocess exited with code ${e}.`),t.end(),We.release(Yc))}),j.on(`error`,e=>{clearTimeout(F),O||(O=!0,t.writableEnded||(S(500,`urn:ok:error:auth-failed`,`Failed to spawn the auth repos subprocess.`,{cause:e}),t.end()),We.release(Yc))}),t.on(`close`,()=>{O||(O=!0,clearTimeout(F),j.kill(`SIGTERM`),We.release(Yc))})}let dl=`local-op-auth-signout`,fl=withValidation(LocalOpAuthHostRequestSchema,async(e,t,s)=>{let g=s.host??`github.com`;if(!We.tryAcquire(Xc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth signout operation is already in progress.`,{handler:dl,extraHeaders:{"Retry-After":`5`}});return}try{let[e,...s]=ve,S=[...s,`auth`,`signout`,`--host`,g];await new Promise((t,s)=>{let g=spawn(e,S,{stdio:`ignore`,env:{...process.env}}),w=setTimeout(()=>{g.kill(`SIGTERM`)},3e4);g.on(`close`,()=>{clearTimeout(w),t()}),g.on(`error`,e=>{clearTimeout(w),s(e)})}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:dl})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth signout failed.`,{handler:dl,cause:e})}finally{We.release(Xc)}},{handler:dl,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:dl})}),pl=`/api/local-op/auth/set-identity`,ml=`local-op-auth-set-identity`,hl=withValidation(LocalOpAuthSetIdentityRequestSchema,async(e,t,s)=>{let g=s.name.trim(),S=s.email.trim();if(!ye){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:ml});return}if(!We.tryAcquire(pl)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A set-identity operation is already in progress.`,{handler:ml,extraHeaders:{"Retry-After":`5`}});return}try{writeGitIdentity(ye,g,S),_e?.()?.refreshIdentity().catch(()=>{}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:ml})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Set-identity failed.`,{handler:ml,cause:e})}finally{We.release(pl)}},{handler:ml,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:ml})});async function gl(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-status`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-status`,extraHeaders:{Allow:`GET`}});return}try{let e=_e?.();if(!e){successResponse(t,200,SyncStatusSchema,{state:`dormant`,lastSyncUtc:null,lastFetchUtc:null,lastPushedSha:null,ahead:0,behind:0,consecutiveFailures:0,conflictCount:0,hasRemote:!1,syncEnabled:!1,identityUnresolved:!1,remote:null},{handler:`sync-status`});return}await e.refreshRemote(),successResponse(t,200,SyncStatusSchema,e.getStatus(),{handler:`sync-status`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-status`,cause:e})}}}let _l=withValidation(SyncTriggerRequestSchema,async(e,t,s)=>{let g=_e?.();if(!g){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`});return}let S=s.op??`sync`;successResponse(t,202,SyncTriggerSuccessSchema,{op:S},{handler:`sync-trigger`}),g.trigger(S)},{handler:`sync-trigger`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-trigger`})?_e?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`}),!1):!1});async function vl(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-conflicts`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflicts`,extraHeaders:{Allow:`GET`}});return}try{let e=_e?.();successResponse(t,200,SyncConflictsSuccessSchema,{conflicts:e?e.getConflicts():[]},{handler:`sync-conflicts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-conflicts`,cause:e})}}}let yl=withValidation(SyncResolveConflictRequestSchema,async(e,t,s)=>{let g=_e?.();if(!g){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`});return}let{file:S,strategy:w,content:E}=s;try{await g.resolveConflict(S,w,E),successResponse(t,200,SyncResolveConflictSuccessSchema,{},{handler:`sync-resolve-conflict`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to resolve conflict.`,{handler:`sync-resolve-conflict`,cause:e,detail:e instanceof Error?e.message:void 0})}},{handler:`sync-resolve-conflict`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-resolve-conflict`})?_e?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`}),!1):!1});async function xl(e,s){if(!checkLocalOpSecurity(e,s,{handler:`sync-conflict-content`}))return;if(e.method!==`GET`){errorResponse(s,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflict-content`,extraHeaders:{Allow:`GET`}});return}if(!ye){errorResponse(s,503,`urn:ok:error:project-repo-not-configured`,`Project repo not configured.`,{handler:`sync-conflict-content`});return}let g=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=g.searchParams.get(`file`);if(!S){errorResponse(s,400,`urn:ok:error:invalid-request`,`Missing required query param: file.`,{handler:`sync-conflict-content`});return}if(S.includes(`..`)||S.startsWith(`/`)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Invalid file path.`,{handler:`sync-conflict-content`});return}let w=stripDocExtension(S),E=t.documents.get(w)?.getMap(`lifecycle`).get(`status`)===`conflict`,D=_e?.(),O=D?D.getConflicts().some(e=>e.file===S):!1;if(!E&&!O){errorResponse(s,404,`urn:ok:error:no-conflict-tracked`,`No conflict is tracked for this path.`,{handler:`sync-conflict-content`,extensions:{file:S}});return}let k=g.searchParams.get(`source`),j=esm_default({baseDir:ye,timeout:{block:15e3}});async function F(e){try{return{present:!0,content:await j.raw([`show`,`:${e}:${S}`])}}catch(t){let s=t instanceof Error?t.message:String(t);if(!/pathspec|did not match|exists on disk, but not in|is in the index, but not at stage/i.test(s))throw console.warn(JSON.stringify({event:`showstage-unexpected-error`,stage:e,file:S,detail:s,handler:`sync-conflict-content`})),t;return{present:!1}}}try{let[e,g,w]=await Promise.all([F(1),F(2),F(3)]),E=e.present?e.content:``,D=w.present?w.content:``,O=g.present&&w.present?`both-modified`:!g.present&&w.present?`delete-modify`:g.present&&!w.present?`modify-delete`:`both-modified`,j=g.present?g.content:``,L=null;if(k===`ytext`){let e=stripDocExtension(S),s=t.documents.get(e);if(s){let t=s.getMap(`lifecycle`).get(`status`);if(L=typeof t==`string`&&t.length>0?t:null,O!==`delete-modify`){let t=Ie?Ie(e):null;t!==null&&!ytextHasConflictMarkers(t)?j=t:t!==null&&console.warn(JSON.stringify({event:`ytext-conflict-marker-detected`,"doc.name":e,handler:`sync-conflict-content`}))}}else console.warn(`[conflict-content] doc ${e} not loaded; lifecycleStatus unavailable`)}successResponse(s,200,SyncConflictContentSuccessSchema,{file:S,base:E,ours:j,theirs:D,kind:O,lifecycleStatus:L},{handler:`sync-conflict-content`})}catch(e){errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to read conflict content.`,{handler:`sync-conflict-content`,cause:e})}}async function Cl(e,t){if(!checkLocalOpSecurity(e,t,{handler:`seed-plan`}))return;if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-plan`,extraHeaders:{Allow:`GET`}});return}let s=new URL(e.url??`/`,`http://localhost`),S=s.searchParams.get(`rootDir`)??void 0,w=s.searchParams.get(`packId`),E=coercePackId(w);if(w!==null&&w!==``&&E===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-plan`,detail:`Pack id "${w}" is not registered.`});return}try{successResponse(t,200,SeedPlanSuccessSchema,{plan:await planSeed({projectDir:g,rootDir:S,packId:E})},{handler:`seed-plan`})}catch(e){if(e instanceof SeedPrerequisiteError){errorResponse(t,422,`urn:ok:error:seed-prerequisite-missing`,`Seed prerequisite missing.`,{handler:`seed-plan`,cause:e});return}if(e instanceof SeedRootDirError){errorResponse(t,400,`urn:ok:error:seed-invalid-root`,`Invalid seed root directory.`,{handler:`seed-plan`,detail:`The provided root directory is not within the workspace content directory.`,cause:e});return}errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`seed-plan`,cause:e})}}let Tl=withValidation(SeedApplyRequestSchema,async(e,t,s)=>{let S=s.plan;if(!S||typeof S!=`object`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid plan payload.`,{handler:`seed-apply`});return}let w=S,E=s.packId,D=coercePackId(E);if(typeof E==`string`&&E.length>0&&D===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-apply`,detail:`Pack id "${E}" is not registered.`});return}try{successResponse(t,200,SeedApplySuccessSchema,{result:await applySeed(w,{projectDir:g,packId:D})},{handler:`seed-apply`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to apply seed plan.`,{handler:`seed-apply`,cause:e})}},{handler:`seed-apply`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`seed-apply`})});async function El(e,t){if(checkLocalOpSecurity(e,t,{handler:`seed-packs`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-packs`,extraHeaders:{Allow:`GET`}});return}successResponse(t,200,SeedListPacksSuccessSchema,{packs:listStarterPacks()},{handler:`seed-packs`})}}let Dl=withValidation(InstallSkillRequestSchema,async(e,t,s)=>{if(s.out!==void 0&&!isSafeLocalPath(s.out)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Output path must be within home directory.`,{handler:`install-skill`});return}try{successResponse(t,200,InstallSkillSuccessSchema,await buildAndOpenSkill({...s.noOpen===void 0?{}:{noOpen:s.noOpen},...s.out===void 0?{}:{out:s.out}}),{handler:`install-skill`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to install skill.`,{handler:`install-skill`,cause:e})}},{handler:`install-skill`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`install-skill`})});async function Ol(e,t){if(checkLocalOpSecurity(e,t,{handler:`installed-agents`}))try{await handleInstalledAgents(e,t,Tt.probeAll)}catch(e){t.headersSent||(log$6.error({err:e},`[installed-agents] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`installed-agents`,cause:e}))}}let kl=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ue){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-list`});return}try{successResponse(t,200,TagsListSuccessSchema,{tags:ue.getAllTags()},{handler:`tags-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tags.`,{handler:`tags-list`,cause:e})}},{handler:`tags-list`,method:`GET`,skipBodyParse:!0});async function jl(e,t,s){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`tags-for-name`,extraHeaders:{Allow:`GET`}});return}if(!ue){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-for-name`});return}let g;try{g=decodeURIComponent(s)}catch{errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid tag name encoding.`,{handler:`tags-for-name`});return}if(!g){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing tag name.`,{handler:`tags-for-name`});return}try{let e=ue.getDocsForTagWithMatches(g).map(({docName:e,matchingTags:t})=>({docName:e,title:Dt(e),matchingTags:t,snippet:null}));successResponse(t,200,TagsForNameSuccessSchema,{name:g,docs:e},{handler:`tags-for-name`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tag membership.`,{handler:`tags-for-name`,cause:e})}}function Ml(e,t,s=`path`,S=`folder-config`){let w=e.replace(/^\.\//,``).replace(/^\/+/,``).replace(/\/+$/,``);if(w.split(`/`).some(e=>e===`..`)||e.startsWith(`/`))return errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid ${s}: must be project-root-relative.`,{handler:S}),null;let E=resolve(g),D=w===``?E:resolve(E,w);return D!==E&&!D.startsWith(`${E}${sep}`)?(errorResponse(t,400,`urn:ok:error:invalid-request`,`Path escapes content directory.`,{handler:S}),null):{folderRel:w,resolvedContentDir:E}}let Pl=/^[A-Za-z0-9_-]+$/;function Fl(e,t,s=`template`){return!e||!Pl.test(e)?(errorResponse(t,400,`urn:ok:error:invalid-request`,"Invalid name: must be letters / digits / `_` / `-` only (no `.md` extension).",{handler:s}),!1):!0}function Il(e,t,s){let g=t===``?[]:t.split(`/`);for(let t=g.length;t>=0;t--){let S=t===0?``:g.slice(0,t).join(`/`),w=S===``?e:resolve(e,S);if(w!==e&&!w.startsWith(`${e}${sep}`))continue;let E=resolve(w,`.ok`,`templates`,`${s}.md`);if(existsSync(E))return{abs:E,folder:S,scope:t===g.length?`local`:`inherited`}}return null}function Ll(e){let t={};if(!e||typeof e!=`object`||Array.isArray(e))return t;for(let[s,g]of Object.entries(e))g!==void 0&&(t[s]=g);return t}async function Rl(e,t){if(e.method===`GET`)return zl(e,t);if(e.method===`PUT`)return Bl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`folder-config`,extraHeaders:{Allow:`GET, PUT`}})}let zl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=Ml(new URL(e.url??``,`http://localhost`).searchParams.get(`path`)??``,t,`path`,`folder-config-get`);if(!s)return;let g=await enrichDirectory(s.folderRel,{projectDir:s.resolvedContentDir}),S=resolve(resolve(s.resolvedContentDir,s.folderRel,`.ok`),`frontmatter.yml`),w=null;if(existsSync(S))try{let e=(0,import_dist$1.parse)(await readFile$1(S,`utf-8`));w=e&&typeof e==`object`&&!Array.isArray(e)?e:{}}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[folder-config:get] malformed YAML in ${S}: ${t}`),w=null}successResponse(t,200,FolderConfigGetSuccessSchema,{folder:g,frontmatter_local:w},{handler:`folder-config-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read folder config.`,{handler:`folder-config-get`,cause:e})}},{handler:`folder-config-get`,method:`GET`,skipBodyParse:!0}),Bl=withValidation(FolderConfigPutRequestSchema,async(e,t,s)=>{try{if(Ue){errorResponse(t,403,`urn:ok:error:single-file-mode`,`Folder configuration is not available in single-file mode.`,{handler:`folder-config-put`});return}let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`folder-config-put`});return}let g=Ml(s.path,t,`path`,`folder-config-put`);if(!g)return;let S=[];if(s.frontmatter!==void 0){let w=applyFolderFrontmatterPatch({anchorDir:g.resolvedContentDir,folderRel:g.folderRel,patch:s.frontmatter});if(!w.ok){let e=w.error.code===`WRITE_ERROR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to write folder config.`:w.error.message,{handler:`folder-config-put`,detail:w.error.code,cause:Error(w.error.message)});return}S.push({path:w.path,action:w.action}),w.action!==`noop`&&(xs(e,_s(`folder-frontmatter`,g.folderRel),`folder-frontmatter-${w.action===`deleted`?`delete`:`edit`}: ${w.path}`),await Cs(`folder-config-put`))}successResponse(t,200,FolderConfigPutSuccessSchema,{applied:S},{handler:`folder-config-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write folder config.`,{handler:`folder-config-put`,cause:e})}},{handler:`folder-config-put`,method:`PUT`});function Vl(e,s,g,S){if(!s)return!1;let w=e===``?`.ok/templates/${s}`:`${e.replace(/\/$/,``)}/.ok/templates/${s}`,E=t.documents.get(w);return E&&isDocInConflict(E)?(respondDocInConflict(S,new DocInConflictError({file:`${w}.md`}),g),!0):!1}function Hl(e,s,g){let S=t.documents.get(e);return S&&isDocInConflict(S)?(respondDocInConflict(g,new DocInConflictError({file:`${e}.md`}),s),!0):!1}let Ul=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=resolveProjectTemplates(resolve(g));successResponse(t,200,TemplatesListSuccessSchema,{templates:e.templates.map(e=>{let{scope:t,...s}=e;return s}),truncated:e.truncated},{handler:`templates-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list templates.`,{handler:`templates-list`,cause:e})}},{handler:`templates-list`,method:`GET`,skipBodyParse:!0});async function Wl(e,t){if(e.method===`GET`)return Kl(e,t);if(e.method===`PUT`)return ql(e,t);if(e.method===`POST`)return Yl(e,t);if(e.method===`DELETE`)return Jl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`template`,extraHeaders:{Allow:`GET, PUT, POST, DELETE`}})}let Gl=e=>{let{frontmatter:t,body:s}=stripFrontmatter(e),g={};if(t!==``)try{let e=(0,import_dist$1.parse)(unwrapFrontmatterFences(t));e&&typeof e==`object`&&!Array.isArray(e)&&(g=e)}catch{}return{frontmatter:g,body:s}},Kl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Fl(g,t,`template-get`))return;let S=Ml(s.searchParams.get(`folder`)??``,t,`folder`,`template-get`);if(!S)return;let{folderRel:w,resolvedContentDir:E}=S,D=Il(E,w,g);if(!D){errorResponse(t,404,`urn:ok:error:template-not-found`,`Template not found.`,{handler:`template-get`,detail:`Template "${g}" not found for folder "${w||`.`}". Walked leaf → root.`});return}let{abs:O,folder:k,scope:j}=D,F=parseTemplateFile(await readFile$1(O,`utf-8`)),L=F.identity,B=F.starterContent;successResponse(t,200,TemplateGetSuccessSchema,{template:{name:g,folder:k,scope:j,path:relative(E,O).split(/[\\/]/).filter(Boolean).join(`/`),frontmatter:L,body:B}},{handler:`template-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template.`,{handler:`template-get`,cause:e})}},{handler:`template-get`,method:`GET`,skipBodyParse:!0}),ql=withValidation(TemplatePutRequestSchema,async(e,t,g)=>{try{if(Ue){errorResponse(t,403,`urn:ok:error:single-file-mode`,`Templates are not available in single-file mode.`,{handler:`template-put`});return}let e=extractActorIdentity(g,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`template-put`});return}let S=g.name;if(!Fl(S,t,`template-put`))return;let w=Ml(g.folder,t,`folder`,`template-put`);if(!w||Vl(w.folderRel,S,`template-put`,t))return;let E=composeTemplateContent({name:S,body:typeof g.body==`string`?g.body:``,frontmatter:Ll(g.frontmatter)});if(!E.ok){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid template request.`,{handler:`template-put`,detail:E.error.code,cause:Error(E.error.message)});return}let D=resolve(w.resolvedContentDir,w.folderRel,`.ok`,`templates`,`${S}.md`),O=!existsSync(D),k=relative(w.resolvedContentDir,D).split(/[\\/]/).filter(Boolean).join(`/`),j=tu(w.folderRel,S),{agentId:F,agentName:L,colorSeed:B,clientName:H}=Gi(g),q=await s.getSession(j,F,{displayName:L,colorSeed:B,clientName:H});q.dc.document.transact(()=>{composeAndWriteRawBody(q.dc.document,E.content,`agent`)},q.origin);let ee=await Ht(j);if(ee?.kind===`failure`){Ut(t,ee.failure,`template-put`);return}if(ee?.kind===`divergence`){Wt(t,`template-put`);return}xs(e,_s(`template`,w.folderRel,S),`${O?`template-create`:`template-edit`}: ${k}`),await Cs(`template-put`),successResponse(t,200,TemplatePutSuccessSchema,{path:k,created:O,warnings:E.warnings},{handler:`template-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write template.`,{handler:`template-put`,cause:e})}},{handler:`template-put`,method:`PUT`}),Jl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Fl(g,t,`template-delete`))return;let S=Ml(s.searchParams.get(`folder`)??``,t,`folder`,`template-delete`);if(!S)return;let w=s.searchParams,E=extractActorIdentity({agentId:w.get(`agentId`)??void 0,agentName:w.get(`agentName`)??void 0,colorSeed:w.get(`colorSeed`)??void 0,clientName:w.get(`clientName`)??void 0,clientVersion:w.get(`clientVersion`)??void 0,label:w.get(`label`)??void 0,summary:w.get(`summary`)??void 0},Ce);if(E.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`template-delete`});return}if(Vl(S.folderRel,g,`template-delete`,t))return;await Lr([tu(S.folderRel,g)]);let D=applyTemplateDelete({projectDir:S.resolvedContentDir,folder:S.folderRel,name:g});if(!D.ok){let e=D.error.code===`WRITE_ERROR`||D.error.code===`UNLINK_FAILED`||D.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete template.`:`Invalid template request.`,{handler:`template-delete`,detail:D.error.code,cause:Error(D.error.message)});return}D.existed&&(xs(E,_s(`template`,S.folderRel,g),`template-delete: ${D.path}`),await Cs(`template-delete`)),successResponse(t,200,TemplateDeleteSuccessSchema,{existed:D.existed,path:D.path},{handler:`template-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete template.`,{handler:`template-delete`,cause:e})}},{handler:`template-delete`,method:`DELETE`,skipBodyParse:!0}),Yl=withValidation(TemplateMoveRequestSchema,async(e,t,s)=>{try{let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`template-move`});return}if(!Fl(s.fromName,t,`template-move`)||!Fl(s.toName,t,`template-move`))return;let g=Ml(s.fromFolder,t,`folder`,`template-move`);if(!g)return;let S=Ml(s.toFolder,t,`folder`,`template-move`);if(!S||Vl(g.folderRel,s.fromName,`template-move`,t))return;await Lr([tu(g.folderRel,s.fromName)]);let w=await applyTemplateMove({projectDir:g.resolvedContentDir,fromFolder:g.folderRel,fromName:s.fromName,toFolder:S.folderRel,toName:s.toName,relocate:async(e,t)=>{let s=await renameTrackedPathInGit(ye,e,t);return s||renamePathOnDisk(e,t),s}});if(!w.ok){if(w.error.code===`TEMPLATE_NOT_FOUND`){let e=Il(g.resolvedContentDir,g.folderRel,s.fromName);if(e?.scope===`inherited`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Template "${s.fromName}" is inherited from "${e.folder||`(root)`}", not local to "${g.folderRel||`(root)`}". Move it from the folder that owns it, or create a local copy here first (then move that).`,{handler:`template-move`,detail:`TEMPLATE_INHERITED`});return}errorResponse(t,404,`urn:ok:error:template-not-found`,`Template not found.`,{handler:`template-move`,detail:w.error.message});return}if(w.error.code===`TEMPLATE_EXISTS`){errorResponse(t,409,`urn:ok:error:doc-already-exists`,w.error.message,{handler:`template-move`,detail:w.error.code});return}let e=w.error.code===`WRITE_ERROR`||w.error.code===`MOVE_FAILED`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to move template.`:`Invalid template move request.`,{handler:`template-move`,detail:w.error.code,cause:Error(w.error.message)});return}let E=null;if(s.body!==void 0||s.frontmatter!==void 0){let e;if(typeof s.body==`string`)e=s.body;else try{e=instantiateDoc(readFileSync(resolve(S.resolvedContentDir,w.toPath),`utf-8`))}catch{e=null}if(e===null)E={code:`READ_FAILED`,message:`could not read the moved template to apply the metadata change; the move succeeded with the original content intact — retry the edit`};else{let t=applyTemplateWrite({projectDir:S.resolvedContentDir,folder:S.folderRel,name:s.toName,body:e,frontmatter:Ll(s.frontmatter)});t.ok||(E=t.error)}}if(xs(e,_s(`template`,S.folderRel,s.toName),`template-rename: ${w.fromPath} -> ${w.toPath}`,[{from:w.fromPath,to:w.toPath}]),await Cs(`template-move`),de?.(`files`),E){let e=E.code===`WRITE_ERROR`||E.code===`READ_FAILED`;errorResponse(t,e?500:400,e?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,`Template moved to "${w.toPath}", but updating its content failed.`,{handler:`template-move`,detail:E.code,cause:Error(E.message)});return}successResponse(t,200,TemplateMoveSuccessSchema,{from:w.fromPath,to:w.toPath,committed:w.committed},{handler:`template-move`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to move template.`,{handler:`template-move`,cause:e})}},{handler:`template-move`,method:`POST`}),Xl=500;function Zl(e,t,s){return!e||e.length>64||!SKILL_NAME_REGEX.test(e)?(errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill name: lowercase letters, digits, and hyphens only (≤64 chars; no slashes, dots, spaces, or uppercase).`,{handler:s}),!1):!0}function Ql(e,t,s){let g=SkillScopeSchema.safeParse(e??`project`);return g.success?g.data:(errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill scope (expected "project" or "global").`,{handler:s}),null)}let $l=we??homedir();function eu(e){return resolve(e===`global`?$l:g,`.ok`,`skills`)}function tu(e,t){return`${MANAGED_ARTIFACT_PREFIX_TEMPLATE}${[...e?e.split(`/`).filter(Boolean).map(encodeURIComponent):[],encodeURIComponent(t)].join(`/`)}`}function nu(e){return e===`navigation`||e===`relevance`?e:void 0}function ru(e,t){return relative(t===`global`?$l:g,e).split(/[\\/]/).filter(Boolean).join(`/`)}function iu(e){return e===`global`?$l:ye}async function au(e,t){let s=await removeSkillInstall(e,t);return reverseProjectSkill(t,e,PROJECT_SKILL_EDITOR_IDS),s!==null}function ou(e,t){let s=[];if(!existsSync(e))return{skills:s,truncated:!1};let g;try{g=readdirSync(e,{withFileTypes:!0})}catch(g){return getLogger(`skills`).warn({err:g,skillsRoot:e,scope:t},`failed to read skills root — returning empty skills list`),{skills:s,truncated:!1}}let S=!1;for(let w of g.sort((e,t)=>e.name.localeCompare(t.name))){if(!w.isDirectory()||!SKILL_NAME_REGEX.test(w.name))continue;if(s.length>=500){S=!0;break}let g=resolve(e,w.name,`SKILL.md`);if(!existsSync(g))continue;let E,D;try{let{frontmatter:e}=Gl(readFileSync(g,`utf-8`));typeof e.description==`string`&&(E=e.description),typeof e.version==`string`&&e.version.trim()!==``&&(D=e.version)}catch{}s.push({name:w.name,...E===void 0?{}:{description:E},scope:t,path:ru(g,t),absolutePath:g,...D===void 0?{}:{installedVersion:D}})}return{skills:s,truncated:S}}let su=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=ou(eu(`project`),`project`),s=ou(eu(`global`),`global`),g=ye?readInstalledSkills(ye).skills:{},S=readInstalledSkills($l).skills,w=(e,t)=>e.skills.map(e=>{let s=t[e.name]?.hosts??[],g=computePackUpdateStatus(e.name,e.installedVersion);return{...e,installed:s.length>0,hosts:s,...g}});successResponse(t,200,SkillsListSuccessSchema,{skills:[...w(e,g),...w(s,S)],truncated:e.truncated||s.truncated},{handler:`skills-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list skills.`,{handler:`skills-list`,cause:e})}},{handler:`skills-list`,method:`GET`,skipBodyParse:!0});async function cu(e,t){if(e.method===`GET`)return mu(e,t);if(e.method===`PUT`)return hu(e,t);if(e.method===`POST`)return _u(e,t);if(e.method===`DELETE`)return gu(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`skill`,extraHeaders:{Allow:`GET, PUT, POST, DELETE`}})}let lu=object$1({managed:boolean().nullable(),importable:number().int().nonnegative()}),uu=()=>({managed:ye?readSkillManagement(ye)?.manageEditorSkills??null:null,importable:ye?countImportableEditorSkills({projectDir:ye,skillsRoot:eu(`project`)}):0}),du=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ye){errorResponse(t,400,`urn:ok:error:invalid-request`,`No project root resolved.`,{handler:`skills-management-get`,detail:`NO_PROJECT_ROOT`});return}successResponse(t,200,lu,uu(),{handler:`skills-management-get`})},{handler:`skills-management-get`,method:`GET`,skipBodyParse:!0}),fu=withValidation(object$1({manageEditorSkills:boolean()}),async(e,t,s)=>{if(!ye){errorResponse(t,400,`urn:ok:error:invalid-request`,`No project root resolved.`,{handler:`skills-management-put`,detail:`NO_PROJECT_ROOT`});return}if(await writeSkillManagement(ye,{manageEditorSkills:s.manageEditorSkills,surface:`ui`}),s.manageEditorSkills){let e=await reconcileSkillInstalls({projectDir:ye,skillsRoot:eu(`project`)});e.adopted.length+e.collided.length>0&&de?.(`files`)}successResponse(t,200,lu,uu(),{handler:`skills-management-put`})},{handler:`skills-management-put`,method:`PUT`});async function pu(e,t){if(e.method===`GET`)return du(e,t);if(e.method===`PUT`)return fu(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`skills-management`,extraHeaders:{Allow:`GET, PUT`}})}let mu=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Zl(g,t,`skill-get`))return;let S=Ql(s.searchParams.get(`scope`),t,`skill-get`);if(S===null)return;let w=eu(S),E=resolve(w,g,`SKILL.md`);if(!existsSync(E)){errorResponse(t,404,`urn:ok:error:not-found`,`Skill not found.`,{handler:`skill-get`,detail:`Skill "${g}" not found in ${S} scope.`});return}let{frontmatter:D,body:O}=Gl(await readFile$1(E,`utf-8`));successResponse(t,200,SkillGetSuccessSchema,{skill:{name:g,scope:S,path:ru(E,S),frontmatter:{name:typeof D.name==`string`?D.name:g,description:typeof D.description==`string`?D.description:``},body:O,files:readSkillBundledFiles(resolve(w,g))}},{handler:`skill-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill.`,{handler:`skill-get`,cause:e})}},{handler:`skill-get`,method:`GET`,skipBodyParse:!0}),hu=withValidation(SkillPutRequestSchema,async(e,t,g)=>{try{let e=extractActorIdentity(g,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-put`});return}if(!Zl(g.name,t,`skill-put`))return;let S=composeSkillContent({name:g.name,body:typeof g.body==`string`?g.body:``,frontmatter:{name:g.frontmatter.name,description:g.frontmatter.description}});if(!S.ok){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill request.`,{handler:`skill-put`,detail:S.error.code,cause:Error(S.error.message)});return}let w=eu(g.scope),E=resolve(w,g.name,`SKILL.md`),D=!existsSync(E),O=relative(w,E).split(/[\\/]/).filter(Boolean).join(`/`),k=skillLiveDocName(g.scope,g.name);if(Hl(k,`skill-put`,t))return;let{agentId:j,agentName:F,colorSeed:L,clientName:B}=Gi(g),H=await s.getSession(k,j,{displayName:F,colorSeed:L,clientName:B});H.dc.document.transact(()=>{composeAndWriteRawBody(H.dc.document,S.content,`agent`)},H.origin);let q=await Ht(k);if(q?.kind===`failure`){Ut(t,q.failure,`skill-put`);return}if(q?.kind===`divergence`){Wt(t,`skill-put`);return}g.scope===`project`&&(xs(e,_s(`skill`,``,g.name),`${D?`skill-create`:`skill-edit`}: ${O}`),await Cs(`skill-put`)),de?.(`files`),successResponse(t,200,SkillPutSuccessSchema,{path:O,created:D,warnings:S.warnings},{handler:`skill-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write skill.`,{handler:`skill-put`,cause:e})}},{handler:`skill-put`,method:`PUT`}),gu=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Zl(g,t,`skill-delete`))return;let S=Ql(s.searchParams.get(`scope`),t,`skill-delete`);if(S===null)return;let w=eu(S),E=s.searchParams,D=extractActorIdentity({agentId:E.get(`agentId`)??void 0,agentName:E.get(`agentName`)??void 0,colorSeed:E.get(`colorSeed`)??void 0,clientName:E.get(`clientName`)??void 0,clientVersion:E.get(`clientVersion`)??void 0,label:E.get(`label`)??void 0,summary:E.get(`summary`)??void 0},Ce);if(D.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-delete`});return}await Lr([skillLiveDocName(S,g)]);let O=applySkillDelete({skillsRoot:w,name:g});if(!O.ok){let e=O.error.code===`UNLINK_FAILED`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete skill.`:`Invalid skill request.`,{handler:`skill-delete`,detail:O.error.code,cause:Error(O.error.message)});return}O.existed&&(S===`project`&&(xs(D,_s(`skill`,``,g),`skill-delete: ${O.path}`),await Cs(`skill-delete`)),de?.(`files`));let k=iu(S);k&&await au(k,g),successResponse(t,200,SkillDeleteSuccessSchema,{existed:O.existed,path:O.path},{handler:`skill-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete skill.`,{handler:`skill-delete`,cause:e})}},{handler:`skill-delete`,method:`DELETE`,skipBodyParse:!0}),_u=withValidation(SkillMoveRequestSchema,async(e,t,s)=>{try{let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-move`});return}if(!Zl(s.fromName,t,`skill-move`)||!Zl(s.toName,t,`skill-move`))return;let g=eu(s.scope);await Lr([skillLiveDocName(s.scope,s.fromName)]);let S=await applySkillMove({skillsRoot:g,fromName:s.fromName,toName:s.toName,relocate:async(e,t)=>{let s=await renameTrackedPathInGit(ye,e,t);return s||renamePathOnDisk(e,t),s}});if(!S.ok){if(S.error.code===`SKILL_NOT_FOUND`){errorResponse(t,404,`urn:ok:error:not-found`,`Skill not found.`,{handler:`skill-move`,detail:S.error.message});return}if(S.error.code===`SKILL_EXISTS`){errorResponse(t,409,`urn:ok:error:doc-already-exists`,S.error.message,{handler:`skill-move`,detail:S.error.code});return}let e=S.error.code===`MOVE_FAILED`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to move skill.`:`Invalid skill move request.`,{handler:`skill-move`,detail:S.error.code,cause:Error(S.error.message)});return}let w=null,E=resolve(g,s.toName,`SKILL.md`),D=``,O=``;try{let e=Gl(readFileSync(E,`utf-8`));D=e.body,typeof e.frontmatter.description==`string`&&(O=e.frontmatter.description)}catch{}let k=typeof s.body==`string`?s.body:D,j=s.frontmatter===void 0?O:s.frontmatter.description,F=applySkillWrite({skillsRoot:g,name:s.toName,body:k,frontmatter:{name:s.toName,description:j}});if(F.ok||(w=F.error),s.scope===`project`&&!w)try{Su(g,s.fromName,s.toName)}catch(e){getLogger(`skill-move`).warn({err:e,fromName:s.fromName,toName:s.toName},`reindex of moved project skill docs failed — rename succeeded, deferring to next rescan`)}let L=ru(resolve(g,s.fromName),s.scope),B=ru(resolve(g,s.toName),s.scope);s.scope===`project`&&(xs(e,_s(`skill`,``,s.toName),`skill-rename: ${L} -> ${B}`,[{from:L,to:B}]),await Cs(`skill-move`));let H=iu(s.scope);if(H){let e=await removeSkillInstall(H,s.fromName);if(e){let t=resolvedHosts(e.hosts);reverseProjectSkill(s.fromName,H,t);let S=projectSkill(resolve(g,s.toName),s.toName,H,t);await recordSkillInstall(H,s.toName,{...e,hosts:S})}}if(de?.(`files`),w){let e=w.code===`WRITE_ERROR`;errorResponse(t,e?500:400,e?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,`Skill renamed to "${s.toName}", but updating its SKILL.md failed — its name frontmatter may not match the new directory.`,{handler:`skill-move`,detail:w.code,cause:Error(w.message)});return}successResponse(t,200,SkillMoveSuccessSchema,{from:L,to:B,committed:S.committed},{handler:`skill-move`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to move skill.`,{handler:`skill-move`,cause:e})}},{handler:`skill-move`,method:`POST`});function vu(e){if(e.includes(`\0`))return null;let t=e.replace(/\\/g,`/`).split(`/`).filter(e=>e!==``&&e!==`.`);return t.length<2||t.some(e=>e===`..`)?null:t[0]===`references`?`reference`:t[0]===`scripts`?`script`:null}function yu(e,t,s){return e===`project`&&t===`reference`&&s.toLowerCase().endsWith(`.md`)}function bu(e,t){let s=t.replace(/\.md$/i,``);return`${projectSkillContentDocName(e).replace(/\/SKILL$/,``)}/${s}`}function xu(e,t){let s=resolve(e,t,`references`);if(!existsSync(s))return[];let g=[],S=(e,t)=>{for(let s of readdirSync(e,{withFileTypes:!0})){let w=t?`${t}/${s.name}`:s.name;s.isDirectory()?S(resolve(e,s.name),w):s.isFile()&&s.name.toLowerCase().endsWith(`.md`)&&g.push(`references/${w}`)}};return S(s,``),g}function Su(e,t,s){if(!ce)return;let g=(e,t,s)=>{let g;try{g=readFileSync(s,`utf-8`)}catch{ce.deleteDocument(e),ue?.deleteDocument(e);return}ce.renameDocument(e,t,g),ue?.renameDocument(e,t,g)};g(projectSkillContentDocName(t),projectSkillContentDocName(s),resolve(e,s,`SKILL.md`));for(let S of xu(e,s))g(bu(t,S),bu(s,S),resolve(e,s,S));de?.(`backlinks`),de?.(`graph`)}let Cu=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Zl(g,t,`skill-file-get`))return;let S=Ql(s.searchParams.get(`scope`),t,`skill-file-get`);if(S===null)return;let w=s.searchParams.get(`path`)??``,E=vu(w);if(E===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill file path (must be a file under references/ or scripts/).`,{handler:`skill-file-get`});return}let D=resolve(eu(S),g),O=resolve(D,w);if(O!==D&&!O.startsWith(`${D}${sep}`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Skill file path escapes the skill dir.`,{handler:`skill-file-get`});return}let k=O,j=w;if(!existsSync(k)){let e=w.match(/^(.*)\.(?:md|mdx)$/),s=e?SUPPORTED_DOC_EXTENSIONS.map(t=>`${e[1]}${t}`).find(e=>e!==w&&existsSync(resolve(D,e))):void 0;if(s===void 0){errorResponse(t,404,`urn:ok:error:not-found`,`Skill file not found.`,{handler:`skill-file-get`,detail:`${w} not found in skill "${g}" (${S}).`});return}j=s,k=resolve(D,s)}let F=await readFile$1(k);if(F.includes(0)){errorResponse(t,415,`urn:ok:error:invalid-request`,`Skill file is binary — only text bundle files are readable via MCP.`,{handler:`skill-file-get`});return}successResponse(t,200,SkillFileGetSuccessSchema,{path:j.replace(/\\/g,`/`),kind:E,text:F.toString(`utf-8`)},{handler:`skill-file-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill file.`,{handler:`skill-file-get`,cause:e})}},{handler:`skill-file-get`,method:`GET`,skipBodyParse:!0}),wu=withValidation(SkillFilePutRequestSchema,async(e,t,g)=>{try{let e=extractActorIdentity(g,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-file-put`});return}if(!Zl(g.name,t,`skill-file-put`))return;let S=vu(g.path);if(S===null){errorResponse(t,400,`urn:ok:error:invalid-request`,"Invalid skill file path (must be a file under references/ or scripts/, no `..`).",{handler:`skill-file-put`});return}if(Buffer.byteLength(g.content,`utf-8`)>262144){errorResponse(t,400,`urn:ok:error:invalid-request`,`Skill file exceeds the 256 KB per-file cap.`,{handler:`skill-file-put`});return}let w=eu(g.scope);if(!existsSync(resolve(w,g.name,`SKILL.md`))){errorResponse(t,404,`urn:ok:error:not-found`,`Skill not found.`,{handler:`skill-file-put`,detail:`Create skill "${g.name}" before adding bundle files.`});return}let E=g.path.replace(/\\/g,`/`),D=yu(g.scope,S,E),O;if(D){let e=bu(g.name,E);if(Hl(e,`skill-file-put`,t))return;if(O=!existsSync(resolve(w,g.name,E)),O&&countBundleFiles(resolve(w,g.name))>=50){errorResponse(t,400,`urn:ok:error:invalid-request`,`Skill "${g.name}" already holds 50 bundle files (the cap) — delete one before adding another.`,{handler:`skill-file-put`});return}let{agentId:S,agentName:D,colorSeed:k,clientName:j}=Gi(g),F=await s.getSession(e,S,{displayName:D,colorSeed:k,clientName:j});F.dc.document.transact(()=>{composeAndWriteRawBody(F.dc.document,g.content,`agent`)},F.origin);let L=await Ht(e);if(L?.kind===`failure`){Ut(t,L.failure,`skill-file-put`);return}if(L?.kind===`divergence`){Wt(t,`skill-file-put`);return}}else{let e=applySkillBundleFileWrite({skillsRoot:w,name:g.name,relPath:E,content:g.content});if(!e.ok){let s=e.error.code===`WRITE_ERROR`?500:e.error.code===`SKILL_NOT_FOUND`?404:400;errorResponse(t,s,s===500?`urn:ok:error:internal-server-error`:s===404?`urn:ok:error:not-found`:`urn:ok:error:invalid-request`,s===500?`Failed to write skill file.`:`Invalid skill file request.`,{handler:`skill-file-put`,detail:e.error.code,cause:Error(e.error.message)});return}O=e.created}g.scope===`project`&&(xs(e,_s(`skill`,``,g.name),`${O?`skill-file-create`:`skill-file-edit`}: .ok/skills/${g.name}/${E}`),await Cs(`skill-file-put`)),de?.(`files`),successResponse(t,200,SkillFilePutSuccessSchema,{path:E,created:O,kind:S,content:D},{handler:`skill-file-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write skill file.`,{handler:`skill-file-put`,cause:e})}},{handler:`skill-file-put`,method:`PUT`}),Tu=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`).searchParams,g=s.get(`name`)??``;if(!Zl(g,t,`skill-file-delete`))return;let S=Ql(s.get(`scope`),t,`skill-file-delete`);if(S===null)return;let w=(s.get(`path`)??``).replace(/\\/g,`/`),E=vu(w);if(E===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid skill file path (must be a file under references/ or scripts/).`,{handler:`skill-file-delete`});return}let D=extractActorIdentity({agentId:s.get(`agentId`)??void 0,agentName:s.get(`agentName`)??void 0,colorSeed:s.get(`colorSeed`)??void 0,clientName:s.get(`clientName`)??void 0,clientVersion:s.get(`clientVersion`)??void 0,label:s.get(`label`)??void 0,summary:s.get(`summary`)??void 0},Ce);if(D.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-file-delete`});return}let O=eu(S);yu(S,E,w)&&await Lr([bu(g,w)]);let k=applySkillBundleFileDelete({skillsRoot:O,name:g,relPath:w});if(!k.ok){let e=k.error.code===`UNLINK_FAILED`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete skill file.`:`Invalid skill file request.`,{handler:`skill-file-delete`,detail:k.error.code,cause:Error(k.error.message)});return}k.existed&&S===`project`&&(xs(D,_s(`skill`,``,g),`skill-file-delete: .ok/skills/${g}/${w}`),await Cs(`skill-file-delete`)),k.existed&&de?.(`files`),successResponse(t,200,SkillFileDeleteSuccessSchema,{path:w,existed:k.existed,kind:E},{handler:`skill-file-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete skill file.`,{handler:`skill-file-delete`,cause:e})}},{handler:`skill-file-delete`,method:`DELETE`,skipBodyParse:!0});async function Eu(e,t){if(e.method===`GET`)return Cu(e,t);if(e.method===`PUT`)return wu(e,t);if(e.method===`DELETE`)return Tu(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`skill-file`,extraHeaders:{Allow:`GET, PUT, DELETE`}})}let Du=withValidation(SkillInstallRequestSchema,async(e,t,s)=>{try{let e=eu(s.scope);if(!Zl(s.name,t,`skill-install`))return;if(s.scope===`project`&&!ye){errorResponse(t,400,`urn:ok:error:invalid-request`,`Cannot install — no project root is resolved for this server. Skills project into editor host dirs at the project root.`,{handler:`skill-install`,detail:`NO_PROJECT_ROOT`});return}let g=iu(s.scope),S=resolve(e,s.name);if(!existsSync(S)){errorResponse(t,404,`urn:ok:error:not-found`,`Skill not found.`,{handler:`skill-install`,detail:`Skill "${s.name}" not found in ${s.scope} scope — create it with write({ skill }) first.`});return}let w=validateSkillForInstall(S,s.name);if(!w.ok){errorResponse(t,400,`urn:ok:error:invalid-request`,`Skill "${s.name}" cannot be installed: ${w.errors.join(` `)}`,{handler:`skill-install`,detail:`INVALID_SKILL_SOURCE`});return}let E=s.scope===`global`?s.targets?PROJECT_SKILL_EDITOR_IDS.filter(e=>s.targets?.some(t=>t===e)):[...PROJECT_SKILL_EDITOR_IDS]:s.targets===void 0?resolveSkillTargets(g,readSkillTargets(g)??void 0):PROJECT_SKILL_EDITOR_IDS.filter(e=>s.targets?.some(t=>t===e)),D=[],O=[];E.length===0&&s.targets===void 0&&(D.push(s.scope===`global`?`No editor skill folders are configured to install into.`:"No project-configured editors detected — nothing was projected. Set up an editor for this project (add .mcp.json / .cursor/mcp.json / .codex/config.toml) or pass explicit `targets`."),O.push(`no-targets`)),w.hasScripts&&(D.push("This skill includes executable `scripts/`. After you install it, the AI agent in your editor (Claude, Cursor, Codex) can run them — Open Knowledge itself never runs anything. Review the scripts before sharing."),O.push(`scripts-present`));let k=resolvedHosts(readInstalledSkills(g).skills[s.name]?.hosts??[]).filter(e=>!E.includes(e));k.length>0&&reverseProjectSkill(s.name,g,k);let j=projectSkill(S,s.name,g,E);j.length===0?await removeSkillInstall(g,s.name):await recordSkillInstall(g,s.name,{hosts:j,scope:s.scope,scripts:w.hasScripts,installedAt:new Date().toISOString()}),de?.(`files`),successResponse(t,200,SkillInstallSuccessSchema,{name:s.name,hosts:j,scripts:w.hasScripts,warnings:D,warningCodes:O},{handler:`skill-install`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to install skill.`,{handler:`skill-install`,cause:e})}},{handler:`skill-install`,method:`POST`}),Ou=withValidation(SkillUninstallRequestSchema,async(e,t,s)=>{try{if(!Zl(s.name,t,`skill-uninstall`))return;let e=iu(s.scope);if(!e){errorResponse(t,400,`urn:ok:error:invalid-request`,`Cannot uninstall — no project root is resolved for this server.`,{handler:`skill-uninstall`,detail:`NO_PROJECT_ROOT`});return}let g=await au(e,s.name);de?.(`files`),successResponse(t,200,SkillUninstallSuccessSchema,{name:s.name,uninstalled:g},{handler:`skill-uninstall`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to uninstall skill.`,{handler:`skill-uninstall`,cause:e})}},{handler:`skill-uninstall`,method:`POST`});async function ku(e,t){if(e.method===`GET`)return Au(e,t);if(e.method===`PUT`)return ju(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`skill-targets`,extraHeaders:{Allow:`GET, PUT`}})}let Au=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=ye?readSkillTargets(ye):null;successResponse(t,200,SkillTargetsGetSuccessSchema,{targets:resolveSkillTargets(ye??``,e??void 0),configured:e!==null},{handler:`skill-targets-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill targets.`,{handler:`skill-targets-get`,cause:e})}},{handler:`skill-targets-get`,method:`GET`,skipBodyParse:!0}),ju=withValidation(SkillTargetsPutRequestSchema,async(e,t,s)=>{try{if(!ye){errorResponse(t,400,`urn:ok:error:invalid-request`,`Cannot set skill targets — no project root is resolved for this server.`,{handler:`skill-targets-put`,detail:`NO_PROJECT_ROOT`});return}let e=s.targets,g=new Set(e),S=resolveSkillTargets(ye,readSkillTargets(ye)??void 0),w=eu(`project`);await writeSkillTargets(ye,e);let{reprojected:E,bundleHosts:D}=await reprojectAllManagedSkills({projectDir:ye,skillsRoot:w,targets:e});de?.(`files`),successResponse(t,200,SkillTargetsPutSuccessSchema,{targets:e,reprojected:E,bundleHosts:D,removedFrom:S.filter(e=>!g.has(e))},{handler:`skill-targets-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to set skill targets.`,{handler:`skill-targets-put`,cause:e})}},{handler:`skill-targets-put`,method:`PUT`}),Mu=withValidation(SkillRestoreRequestSchema,async(e,t,s)=>{try{let e=extractActorIdentity(s,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-restore`});return}if(!Zl(s.name,t,`skill-restore`))return;if(s.scope===`global`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Global skills are unversioned — there is no version history to restore from.`,{handler:`skill-restore`,detail:`GLOBAL_SCOPE_UNVERSIONED`});return}let S=q?.current;if(!S){errorResponse(t,409,`urn:ok:error:shadow-not-configured`,`No version history available to restore from.`,{handler:`skill-restore`,detail:`NO_SHADOW_REPO`});return}let w=await restoreSkillVersion({shadow:S,contentDir:g,contentRoot:se??`.`,name:s.name,version:s.version});if(!w.ok){let[e,s]={"no-shadow":[409,`urn:ok:error:shadow-not-configured`],"version-not-found":[404,`urn:ok:error:not-found`],"skill-absent":[404,`urn:ok:error:not-found`],"io-error":[500,`urn:ok:error:storage-error`],"path-escape":[500,`urn:ok:error:path-escape`]}[w.code];errorResponse(t,e,s,w.error,{handler:`skill-restore`,detail:w.code});return}let E=[],D=validateSkillForInstall(resolve(g,`.ok`,`skills`,s.name),s.name);D.ok||E.push(`Restored, but the skill no longer validates: ${D.errors.join(` `)}`),E.push("Run `install` to push the restored version to your editors."),xs(e,_s(`skill`,``,s.name),`skill-restore: ${s.name} @ ${s.version.slice(0,8)}`),await Cs(`skill-restore`),de?.(`files`),successResponse(t,200,SkillRestoreSuccessSchema,{name:s.name,version:s.version,restoredFiles:w.restoredFiles,warnings:E},{handler:`skill-restore`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to restore skill.`,{handler:`skill-restore`,cause:e})}},{handler:`skill-restore`,method:`POST`}),Nu=withValidation(SkillUpdateRequestSchema,async(e,t,g)=>{try{let e=extractActorIdentity(g,Ce);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`skill-update`});return}if(!Zl(g.name,t,`skill-update`))return;if(!isPackSkillName(g.name)){errorResponse(t,400,`urn:ok:error:invalid-request`,"Only starter-pack skills (`open-knowledge-pack-*`) can be updated from the bundle.",{handler:`skill-update`,detail:`NOT_A_PACK_SKILL`});return}if(g.scope===`global`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Pack skills are project-scope — there is no global-scope pack to update.`,{handler:`skill-update`,detail:`GLOBAL_SCOPE`});return}let S=readBundledPackSkill(g.name);if(S===null||S.version===void 0){errorResponse(t,404,`urn:ok:error:not-found`,`No bundled version is available for this pack skill.`,{handler:`skill-update`,detail:`NO_BUNDLED_VERSION`});return}let w=resolve(eu(`project`),g.name,`SKILL.md`);if(!existsSync(w)){errorResponse(t,404,`urn:ok:error:not-found`,`Skill is not installed.`,{handler:`skill-update`,detail:`SKILL_ABSENT`});return}let E;try{E=readSkillVersion(readFileSync(w,`utf-8`))}catch{}let D,O=q?.current;if(O)try{let e=ae?.()??`main`;D=(await saveVersion(O,se??`.`,[SERVICE_WRITER],e,`Before updating ${g.name} (${E??`unversioned`} → ${S.version})`)).checkpointRef}catch(e){getLogger(`skills`).warn({err:e,skill:g.name},`pre-update checkpoint failed — proceeding with overwrite`)}let k=skillLiveDocName(`project`,g.name);if(Hl(k,`skill-update`,t))return;let{agentId:j,agentName:F,colorSeed:L,clientName:B}=Gi(g),H=await s.getSession(k,j,{displayName:F,colorSeed:L,clientName:B});H.dc.document.transact(()=>{composeAndWriteRawBody(H.dc.document,S.content,`agent`)},H.origin);let ee=await Ht(k);if(ee?.kind===`failure`){Ut(t,ee.failure,`skill-update`);return}if(ee?.kind===`divergence`){Wt(t,`skill-update`);return}xs(e,_s(`skill`,``,g.name),`skill-pack-update: ${g.name} (${E??`unversioned`} → ${S.version})`),await Cs(`skill-update`),de?.(`files`),successResponse(t,200,SkillUpdateSuccessSchema,{name:g.name,version:S.version,...E===void 0?{}:{previousVersion:E},...D===void 0?{}:{checkpointRef:D}},{handler:`skill-update`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to update skill.`,{handler:`skill-update`,cause:e})}},{handler:`skill-update`,method:`POST`});function Pu(e){let t=new Map;for(let s of e){let e=s.path.split(`/`).filter(Boolean);e.pop();for(let g=1;g<=e.length;g++){let S=e.slice(0,g).join(`/`);t.set(S,Math.max(t.get(S)??0,s.modifiedTs))}}return[...t.entries()].map(([e,t])=>createWorkspaceSearchDocument({kind:`folder`,path:e,modifiedTs:t}))}function Fu(e,t){let s=t.trim().toLowerCase();if(!s||!e)return;let g=e.toLowerCase().indexOf(s);if(g<0)return;let S=Math.max(0,g-80),w=Math.min(e.length,g+s.length+120),E=S>0?`…`:``,D=w<e.length?`…`:``;return`${E}${e.slice(S,w).replace(/\s+/g,` `).trim()}${D}`}function Iu(e){return e===`autocomplete`||e===`full_text`||e===`omnibar`?e:`omnibar`}function Lu(e){let t=typeof e==`string`?e.split(`,`):Array.isArray(e)?e:void 0;if(!t)return;let s=t.filter(e=>e===`page`||e===`folder`||e===`content`||e===`file`);return s.length>0?s:void 0}function Ru(e){if(typeof e==`boolean`)return e;if(e===`true`)return!0;if(e===`false`)return!1}function zu(e){return e===`omnibar`||e===`mcp`||e===`http`?e:`http`}async function Bu(e,t,s,g){let S=g.documents.filter(e=>!isHiddenDocName(e.path)),w=S.reduce((e,t)=>e+(t.kind===`page`?1:0),0);if(!ze?.isEnabled()||s!==!0)return{queryEmbedMs:null,pageTotal:w,capable:!1};ze.embedCorpus(S);let E,D=null;if(t===`full_text`&&e.trim().length>=3){let t=performance.now(),s=await ze.queryScores(e,S);if(D=performance.now()-t,s&&s.size>0){let e=Be?.();E=e===void 0?{scores:s}:{scores:s,similarityFloor:e}}}let O=ze.getStatus();return{input:E,status:{capable:O.capable,applied:!1,coverage:{embedded:O.embeddedCount,total:w}},queryEmbedMs:D,pageTotal:w,capable:O.capable}}function Vu(e,t){return{kind:e.document.kind,path:e.document.path,title:e.document.title,score:e.score,signals:e.signals,snippet:e.document.kind===`page`?Fu(e.document.content,t):void 0}}async function Hu(e){let t=performance.now();if(Zu())return{query:e.query,intent:e.intent,results:[],elapsedMs:Math.max(0,performance.now()-t),ready:!1};let{corpus:s,truncated:g}=await Qu(),S=await Bu(e.query,e.intent,e.semanticParam,s),w=searchWorkspaceCorpus(s,e.query,{intent:e.intent,ranking:e.ranking,scopes:e.scopes,limit:e.limit,semantic:S.input}).map(t=>Vu(t,e.query)),E;if(S.status){let t=w.reduce((e,t)=>e+(t.signals.vector===void 0?0:1),0),s=t>0;E={...S.status,applied:s},recordSemanticQuery({outcome:S.capable?s?`applied`:S.status.coverage.embedded===0?`warming`:`no_match`:`incapable`,source:e.source,capable:S.capable,embedded:S.status.coverage.embedded,total:S.pageTotal,queryEmbedMs:S.queryEmbedMs,vectorContributors:t})}return{query:e.query,intent:e.intent,results:w,elapsedMs:Math.max(0,performance.now()-t),ready:!0,...E?{semantic:E}:{},...g?{truncated:!0}:{}}}function Uu(){let e=eu(`project`);if(!existsSync(e))return[];let t;try{t=readdirSync(e,{withFileTypes:!0})}catch{return[]}let s=[];for(let g of t.sort((e,t)=>e.name.localeCompare(t.name))){if(!g.isDirectory()||!SKILL_NAME_REGEX.test(g.name))continue;let t=resolve(e,g.name,`SKILL.md`);try{let e=statSync(t);s.push({name:g.name,absolutePath:t,mtimeMs:e.mtimeMs,size:e.size})}catch{}}return s}function Wu(){let e=[];for(let t of Uu()){let s=t.name,g=``;try{let{frontmatter:e,body:S}=Gl(readFileSync(t.absolutePath,`utf-8`));typeof e.name==`string`&&e.name&&(s=e.name),g=`${typeof e.description==`string`?e.description:``}\n\n${S}`.trim()}catch{}e.push(createWorkspaceSearchDocument({kind:`page`,path:skillLiveDocName(`project`,t.name),title:s,content:g,modifiedTs:t.mtimeMs}))}return e}function Gu(e){return`${e.modified}\0${e.size}\0${e.canonicalPath}\0${e.inode}\0${e.aliases.join(`\0`)}`}let Ku=new Map;async function qu(){let e=[],t=[],s=new Set;for(let[g,S]of E()){if(isSystemDoc(g)||isConfigDoc(g)||g.startsWith(`.ok/skills/`))continue;if(S.kind===`file`){t.push(createWorkspaceSearchDocument({kind:`file`,path:g,modifiedTs:Date.parse(S.modified),aliases:S.aliases}));continue}s.add(g);let w=Gu(S),E=Ku.get(g);if(E&&E.key===w){e.push(E.doc);continue}let D=``,O=g,k=!1;try{D=await readFile$1(S.canonicalPath,`utf-8`)}catch(e){k=!0,console.warn(`[search] Failed to read ${g}:`,e)}if(!k)try{O=extractPageTitle(D,g)}catch(e){console.warn(`[search] Failed to extract title for ${g}:`,e)}let j=createWorkspaceSearchDocument({kind:`page`,path:g,title:O,content:D,modifiedTs:Date.parse(S.modified),aliases:S.aliases});k||Ku.set(g,{key:w,doc:j}),e.push(j)}for(let e of Ku.keys())s.has(e)||Ku.delete(e);let g=getSearchMaxEntries(),S=t,w=!1;return t.length>g&&(w=!0,S=[...t].sort((e,t)=>e.path.split(`/`).length-t.path.split(`/`).length||e.path.localeCompare(t.path)).slice(0,g),getLogger(`search`).warn({dropped:t.length-S.length,retained:S.length,limit:g},`[search] corpus name-only file tier truncated at OK_SEARCH_MAX_ENTRIES`),searchCorpusTruncatedCounter().add(1)),{documents:[...e,...Wu(),...S,...Pu([...e,...S])],truncated:w}}function Ju(){return Uu().map(e=>`${e.name} ${e.mtimeMs} ${e.size}`).join(``)}function Yu(){return O?`gen:${O()}|skills${Ju()}`:`${[...E()].filter(([e])=>!isSystemDoc(e)&&!isConfigDoc(e)).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}\0${Gu(t)}`).join(``)}|skills${Ju()}`}let Xu=Me===void 0;Me?.then(()=>{Xu=!0},e=>{Xu=!0,log$6.warn({err:e,handler:`search`},`[api] ready gate rejected — search serves the partial index`)});function Zu(){return!Xu}async function Qu(){let e=`${g}${ye??``}`,t=Yu(),s=workspaceSearchCaches.get(e);if(s?.fingerprint===t&&s.corpus)return{corpus:s.corpus,truncated:s.truncated??!1};if(s?.fingerprint===t&&s.pending)return s.pending;let S=qu().then(({documents:e,truncated:t})=>({corpus:createWorkspaceSearchCorpus(e),truncated:t}));workspaceSearchCaches.set(e,{fingerprint:t,pending:S});try{let s=await S;return workspaceSearchCaches.get(e)?.pending===S&&workspaceSearchCaches.set(e,{fingerprint:t,corpus:s.corpus,truncated:s.truncated}),s}catch(t){throw workspaceSearchCaches.get(e)?.pending===S&&workspaceSearchCaches.delete(e),t}}function $u(){if(process.env.NODE_ENV!==`test`)for(let e of[0,1e3,3e3])setTimeout(()=>{Qu().catch(e=>{console.warn(`[search] Failed to prewarm workspace search cache:`,e)})},e)}$u();async function ed(e,t){if(e.method===`GET`)return td(e,t);if(e.method===`POST`)return nd(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`search`,extraHeaders:{Allow:`GET, POST`}})}let td=withValidation(EmptyRequestSchema,async(e,t)=>{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`limit`),S=s.searchParams.get(`query`)??``,w=Iu(s.searchParams.get(`intent`)),E=nu(s.searchParams.get(`ranking`)),D=Lu(s.searchParams.get(`scope`)??s.searchParams.get(`scopes`)),O=Ru(s.searchParams.get(`semantic`)),k=zu(s.searchParams.get(`source`)),j=g===null?void 0:Number(g);if(S.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-get`});return}try{successResponse(t,200,SearchSuccessSchema,await Hu({query:S,intent:w,ranking:E,scopes:D,limit:j,semanticParam:O,source:k}),{handler:`search-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-get`,cause:e})}},{handler:`search-get`,method:`GET`,skipBodyParse:!0}),nd=withValidation(SearchRequestSchema,async(e,t,s)=>{let g=typeof s.query==`string`?s.query:``,S=Iu(s.intent),w=nu(s.ranking),E=Lu(s.scopes??s.scope),D=typeof s.limit==`number`?s.limit:void 0,O=Ru(s.semantic),k=zu(s.source);if(g.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-post`});return}try{successResponse(t,200,SearchSuccessSchema,await Hu({query:g,intent:S,ranking:w,scopes:E,limit:D,semanticParam:O,source:k}),{handler:`search-post`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-post`,cause:e})}},{handler:`search-post`,method:`POST`}),rd=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,SkillInstallStateSuccessSchema,{...await readSkillInstallStateSnapshot(homedir())},{handler:`skill-install-state`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill install state.`,{handler:`skill-install-state`,cause:e})}},{handler:`skill-install-state`,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`skill-install-state`})});async function ad(e,t){if(checkLocalOpSecurity(e,t,{handler:`handoff`}))try{await handleHandoffDispatch(e,t,{contentDir:g,platform:process.platform})}catch(e){t.headersSent||(log$6.error({err:e},`[handoff] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`handoff`,cause:e}))}}async function od(e,t){if(checkLocalOpSecurity(e,t,{handler:`spawn-cursor`}))try{await handleSpawnCursor(e,t,{contentDir:g,platform:process.platform})}catch(e){t.headersSent||(log$6.error({err:e},`[spawn-cursor] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`spawn-cursor`,cause:e}))}}let sd=withValidation(ShareConstructUrlRequestSchema,async(e,t,s)=>{try{if(!ye){emitShareConstructUrlLog(`no-remote`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!isValidSharePath(s.kind===`doc`?s.docPath:s.folderPath,s.kind)){emitShareConstructUrlLog(`invalid-path`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`invalid-path`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let e=readGitHeadBranch(ye);if(e===null){if(readOriginGitHubRepo(ye).kind===`no-remote`){emitShareConstructUrlLog(`no-remote`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}emitShareConstructUrlLog(`detached-head`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`detached-head`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let S=readOriginGitHubRepo(ye);if(S.kind===`no-remote`){emitShareConstructUrlLog(`no-remote`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(S.kind===`non-github`){emitShareConstructUrlLog(`non-github-remote`,{kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`non-github-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!branchExistsOnOrigin(ye,e)){emitShareConstructUrlLog(`branch-not-on-origin`,{branchExists:!1,kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`branch-not-on-origin`,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let w=toGitRelativePath(ye,g);if(w===null)throw Error(`content dir is not contained within the project dir`);let E=s.kind===`doc`?s.docPath!==``:s.folderPath!==``;w!==``&&E&&getLogger(`share`).warn({action:`construct-url`,kind:s.kind},`[share] content.dir != "." — non-root share URL omits the content.dir prefix; the github.com link may point at the wrong subtree. In-app receive navigation is content-relative and lands correctly.`);let D;if(s.kind===`doc`)D=buildGitHubBlobUrl(S.owner,S.repo,e,s.docPath);else{let t=s.folderPath===``?w:s.folderPath;D=buildGitHubTreeUrl(S.owner,S.repo,e,t)}let O=`${SHARE_BASE_URL}${encodeShareUrl(D)}`;emitShareConstructUrlLog(`ok`,{branchExists:!0,kind:s.kind}),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!0,shareUrl:O,sharedUrl:D,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,cause:e})}},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})}),cd=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!ye){errorResponse(t,500,`urn:ok:error:internal-server-error`,`projectDir is not configured for this server.`,{handler:BRANCH_INFO_HANDLER_TAG});return}let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`branch`),S=s.searchParams.get(`path`),w=s.searchParams.get(`kind`)===`folder`?`folder`:`doc`;if(!isValidBranchName(g)){errorResponse(t,400,`urn:ok:error:invalid-request`,`branch query param missing or malformed.`,{handler:BRANCH_INFO_HANDLER_TAG});return}if(!isValidBranchInfoPath(S,w)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path query param missing or malformed.`,{handler:BRANCH_INFO_HANDLER_TAG});return}successResponse(t,200,BranchInfoResponseSchema,await computeBranchInfo(ye,g,S,w),{handler:BRANCH_INFO_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:BRANCH_INFO_HANDLER_TAG,cause:e})}},{handler:BRANCH_INFO_HANDLER_TAG,method:`GET`,skipBodyParse:!0}),ld=withValidation(CheckoutRequestSchema,async(e,t,s)=>{if(extractActorIdentity(s,Ce).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:CHECKOUT_HANDLER_TAG});return}if(!ye){errorResponse(t,500,`urn:ok:error:internal-server-error`,`projectDir is not configured for this server.`,{handler:CHECKOUT_HANDLER_TAG});return}try{successResponse(t,200,CheckoutResponseSchema,await withParentLock(()=>runCheckoutFlow(ye,s.branch)),{handler:CHECKOUT_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:CHECKOUT_HANDLER_TAG,cause:e})}},{handler:CHECKOUT_HANDLER_TAG,method:`POST`});async function ud(e){let[t,...s]=ve,g=[...s,...e];return await new Promise((e,s)=>{let S=spawn(t,g,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),w=!1,E=setTimeout(()=>{w=!0,S.kill(`SIGTERM`)},SHARE_PUBLISH_TIMEOUT_MS),D=[],O=[];S.stdout.on(`data`,e=>D.push(e)),S.stderr.on(`data`,e=>O.push(e)),S.on(`close`,t=>{if(clearTimeout(E),w){s(Error(`share subprocess timed out after ${SHARE_PUBLISH_TIMEOUT_MS}ms`));return}let g=Buffer.concat(D).toString(`utf-8`);if(t!==0){let e=redactShareSubprocessStderr(Buffer.concat(O).toString(`utf-8`)).slice(0,500);console.warn(`[share] subprocess exited code=${t} stderr=${e}`)}e({stdout:g,code:t})}),S.on(`error`,e=>{clearTimeout(E),s(e)})})}let dd=withValidation(EmptyRequestSchema,async(e,t)=>{if(!We.tryAcquire(`/api/share/publish/owners`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share owners operation is already in progress.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await ud([`share`,`owners`,`--json`]),s=parseOwnersEvent(pickTerminalJsonLine(e));emitSharePublishLog(`owners-list`,s.ok?`ok`:s.error,s.ok?{count:s.owners.length}:void 0),successResponse(t,200,SharePublishOwnersResponseSchema,s,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,cause:e})}finally{We.release(SHARE_PUBLISH_OWNERS_KEY)}},{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}),fd=withValidation(EmptyRequestSchema,async(e,t)=>{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`owner`)??``,S=s.searchParams.get(`name`)??``;if(!isValidShareOwnerName(g)||!isValidShareRepoName(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name query params must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG});return}if(!We.tryAcquire(`/api/share/publish/name-check`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share name-check operation is already in progress.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await ud([`share`,`name-check`,`--owner`,g,`--name`,S,`--json`]),s=parseNameCheckEvent(pickTerminalJsonLine(e));emitSharePublishLog(`name-check`,s.ok?`ok`:s.error,s.ok?{available:s.available}:void 0),successResponse(t,200,SharePublishNameCheckResponseSchema,s,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,cause:e})}finally{We.release(SHARE_PUBLISH_NAME_CHECK_KEY)}},{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}),pd=withValidation(SharePublishRequestSchema,async(e,t,s)=>{if(!ye){emitSharePublishLog(`publish-create`,`no-project`),successResponse(t,200,SharePublishResponseSchema,{ok:!1,error:`no-project`},{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!isValidShareOwnerName(s.owner)||!isValidShareRepoName(s.name)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!We.tryAcquire(`/api/share/publish`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share publish operation is already in progress.`,{handler:SHARE_PUBLISH_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let e=[`share`,`publish`,`--owner`,s.owner,`--name`,s.name,`--visibility`,s.visibility,`--project-dir`,ye,`--json`];s.description!==void 0&&s.description.length>0&&e.push(`--description`,s.description);let{stdout:g}=await ud(e),S=parsePublishEvent(pickTerminalJsonLine(g));emitSharePublishLog(`publish-create`,S.ok?`ok`:S.error),S.ok&&_e?.()?.refreshRemote().catch(()=>{}),successResponse(t,200,SharePublishResponseSchema,S,{handler:SHARE_PUBLISH_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_HANDLER_TAG,cause:e})}finally{We.release(SHARE_PUBLISH_KEY)}},{handler:SHARE_PUBLISH_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_HANDLER_TAG})}),md=withValidation(ClientLogsRequestSchema,async(e,t,s)=>{try{let e=getLogger(`renderer`);for(let t of s.entries)try{e[t.level]({...t.fields,source:`renderer-console`,transport:`web`,...t.sourceId?{sourceId:t.sourceId}:{},...t.lineNumber===void 0?{}:{lineNumber:t.lineNumber},...t.ts===void 0?{}:{clientTs:t.ts}},t.event??t.message)}catch{}successResponse(t,200,ClientLogsSuccessSchema,{accepted:s.entries.length},{handler:`client-logs`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`client-logs`,cause:e})}},{handler:`client-logs`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`client-logs`})}),hd=ye?getLocalDir(ye):null;async function gd(e,t){if(e.method===`DELETE`){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-config`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-config`});return}hd&&clearArmedPaneTarget(hd),t.setHeader(`Cache-Control`,`no-store`),t.statusCode=204,t.end();return}if(e.method===`GET`||e.method===`HEAD`){try{let s=e.headers.host,g={collabUrl:s?`ws://${s}/collab`:null,previewUrl:null,port:hd?readServerLock(hd)?.port??0:0,paneTarget:hd?readArmedPaneTarget(hd):null,singleFile:Ue};if(e.method===`HEAD`){t.setHeader(`Content-Type`,`application/json`),t.setHeader(`Cache-Control`,`no-store`),t.setHeader(`X-Content-Type-Options`,`nosniff`),t.statusCode=200,t.end();return}successResponse(t,200,ApiConfigSuccessSchema,g,{handler:`api-config`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`api-config`,cause:e})}return}errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`api-config`,extraHeaders:{Allow:`GET, HEAD, DELETE`}})}let _d=`local-op-embeddings-set-key`,vd=`local-op-embeddings-clear-key`,yd=`/api/local-op/embeddings`,bd=withValidation(LocalOpEmbeddingsSetKeyRequestSchema,async(e,t,s)=>{if(!We.tryAcquire(yd)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An embeddings key operation is already in progress.`,{handler:_d,extraHeaders:{"Retry-After":`5`}});return}try{await new FileEmbeddingsBackend(Ve).set(s.key),successResponse(t,200,LocalOpEmbeddingsMutationSuccessSchema,{keyPresent:!0},{handler:_d,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to store the key.`,{handler:_d,cause:e})}finally{We.release(yd)}},{handler:_d,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:_d})}),xd=withValidation(EmptyRequestSchema,async(e,t)=>{if(!We.tryAcquire(yd)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An embeddings key operation is already in progress.`,{handler:vd,extraHeaders:{"Retry-After":`5`}});return}try{await clearEmbeddingsKeyFromAllBackends(Ve),successResponse(t,200,LocalOpEmbeddingsMutationSuccessSchema,{keyPresent:!1},{handler:vd,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to clear the key.`,{handler:vd,cause:e})}finally{We.release(yd)}},{handler:vd,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:vd})}),Sd=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=!1,s=!1,g=!1,S=0;if(ze){let t=ze.getStatus();e=t.enabled,s=t.ready,g=t.capable,S=t.embeddedCount}let E=await new FileEmbeddingsBackend(Ve).get(),D=process.env.OK_EMBEDDINGS_API_KEY??null,O=E?`file`:D?`env`:null,k=O!==null,j=E??D,F=j&&j.length>=8?j.slice(-4):null,L=0;for(let[e]of w())!isSystemDoc(e)&&!isConfigDoc(e)&&!isHiddenDocName(e)&&(L+=1);successResponse(t,200,SemanticIndexStatusSchema,{enabled:e,keyPresent:k,keySource:O,keyHint:F,ready:s,capable:g,embedded:S,total:L},{handler:`semantic-status`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`semantic-status`,cause:e})}},{handler:`semantic-status`,method:`GET`,skipBodyParse:!0}),Cd={"/api/config":gd,"/api/asset":Sc,"/api/asset-text":wc,"/api/document":As,"/api/documents":Ns,"/api/backlinks":Ps,"/api/backlink-counts":Is,"/api/forward-links":Rs,"/api/link-graph":$s,"/api/dead-links":nc,"/api/orphans":ec,"/api/hubs":tc,"/api/tags":kl,"/api/pages":Pc,"/api/folder-config":Rl,"/api/template":Wl,"/api/templates":Ul,"/api/skill":cu,"/api/skill-file":Eu,"/api/skills":su,"/api/skills/management":pu,"/api/skill/install":Du,"/api/skill/uninstall":Ou,"/api/skill/restore":Mu,"/api/skill/update":Nu,"/api/skill-targets":ku,"/api/search":ed,"/api/semantic-status":Sd,"/api/suggest-links":Fc,"/api/page-headings":Ac,"/api/create-page":Dc,"/api/create-folder":Oc,"/api/duplicate-path":kc,"/api/rename-path":jc,"/api/delete-path":Mc,"/api/trash/cleanup":Nc,"/api/upload":Ic,"/api/agent-write":Ts,"/api/agent-write-md":Ds,"/api/frontmatter-patch":Os,"/api/agent-patch":rc,"/api/agent-undo":ic,"/api/agent-activity":ac,"/api/agent-burst-diff":oc,"/api/save-version":dc,"/api/history":fc,"/api/rollback":mc,"/api/metrics/reconciliation":hc,"/api/metrics/parse-health":gc,"/api/metrics/agent-presence":yc,"/api/__embed-detect":bc,"/api/server-info":_c,"/api/share/construct-url":sd,"/api/git/branch-info":cd,"/api/git/checkout":ld,"/api/share/publish/owners":dd,"/api/share/publish/name-check":fd,"/api/share/publish":pd,"/api/principal":vc,"/api/rescue":Ec,"/api/workspace":xc,"/api/sync/status":gl,"/api/sync/trigger":_l,"/api/sync/conflicts":vl,"/api/sync/conflict-content":xl,"/api/sync/resolve-conflict":yl,"/api/local-op/clone":Hc,"/api/local-op/ok-init":Kc,"/api/local-op/auth/login":$c,"/api/local-op/auth/status":al,"/api/local-op/auth/repos":ll,"/api/local-op/auth/signout":fl,"/api/local-op/auth/set-identity":hl,"/api/local-op/embeddings/set-key":bd,"/api/local-op/embeddings/clear-key":xd,"/api/installed-agents":Ol,"/api/spawn-cursor":od,"/api/handoff":ad,"/api/install-skill":Dl,"/api/skill/install-state":rd,"/api/seed/plan":Cl,"/api/seed/apply":Tl,"/api/seed/packs":El,"/api/client-logs":md};H&&(Cd[`/api/test-reset`]=cc,Cd[`/api/test-flush-git`]=sc,Cd[`/api/test-rescan-backlinks`]=lc,Cd[`/api/test-rescan-files`]=uc);let wd=new Set(`/api/upload./api/create-page./api/create-folder./api/duplicate-path./api/rename-path./api/delete-path./api/trash/cleanup./api/agent-write./api/agent-write-md./api/frontmatter-patch./api/agent-patch./api/agent-undo./api/save-version./api/rollback./api/sync/trigger./api/sync/resolve-conflict./api/git/checkout./api/test-reset./api/test-flush-git./api/test-rescan-backlinks./api/test-rescan-files./api/install-skill./api/folder-config./api/template./api/skill./api/skill-file./api/skill/install./api/skill/uninstall./api/skill/restore./api/skill/update./api/skills/management./api/skill-targets./api/seed/apply./api/client-logs`.split(`.`)),Td=[`/api/local-op/`];return{priority:100,async onRequest({request:e,response:t}){let s=e.url?.split(`?`)[0];if(!s)return;let g=t=>{let s=e.headers[t];if(s!==void 0)return Array.isArray(s)?s.join(`, `):s};if(recordEmbedProbe({ts:Date.now(),url:s,method:e.method??``,ua:g(`user-agent`),origin:g(`origin`),referer:g(`referer`),host:g(`host`),remote:e.socket?.remoteAddress,secChUa:g(`sec-ch-ua`),secChUaMobile:g(`sec-ch-ua-mobile`),secChUaPlatform:g(`sec-ch-ua-platform`),secFetchSite:g(`sec-fetch-site`),secFetchDest:g(`sec-fetch-dest`),secFetchMode:g(`sec-fetch-mode`),secFetchUser:g(`sec-fetch-user`)}),s.startsWith(`/api/`)){let s=e.headers.origin;if(s!==void 0&&!isAllowedApiOrigin(s)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`api-origin-gate`});return}if(typeof t.setHeader==`function`&&(s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`)),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, traceparent, tracestate, baggage, ${CLIENT_VERSION_HEADER.protocol}, ${CLIENT_VERSION_HEADER.runtime}, ${CLIENT_VERSION_HEADER.kind}`)),e.method===`OPTIONS`){t.writeHead(204),t.end();return}}if(wd.has(s)||Td.some(e=>s.startsWith(e))){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-mutating-gate`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-mutating-gate`});return}}if(Ue&&s.startsWith(`/api/`)){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-ephemeral-gate`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-ephemeral-gate`});return}}if(!s.startsWith(`/api/`))return;let S=propagation.extract(context.active(),e.headers),w=e.method??`GET`,E=s;s.startsWith(`/api/history/`)?E=`/api/history/:sha`:s.startsWith(`/api/tags/`)?E=`/api/tags/:name`:Cd[s]||(E=`/api/*`);let D=getTracer(),O=Date.now();await context.with(S,()=>D.startActiveSpan(`HTTP ${w} ${E}`,{kind:SpanKind.SERVER,attributes:{[ATTR_HTTP_REQUEST_METHOD]:w,[ATTR_HTTP_ROUTE]:E,[ATTR_URL_PATH]:s,[ATTR_URL_SCHEME]:`http`,[ATTR_USER_AGENT_ORIGINAL]:e.headers[`user-agent`]??``}},async g=>{try{let S=Cd[s],E=!1;if(S)E=!0,await S(e,t);else if(s.startsWith(`/api/history/`)){let g=decodeURIComponent(s.slice(13));g&&(E=!0,await pc(e,t,g))}else if(s.startsWith(`/api/tags/`)){let g=s.slice(10);g&&(E=!0,await jl(e,t,g))}E||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`api-dispatch`,detail:`No handler for ${w} ${s}`});let D=t.statusCode;g.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE,D),D>=500&&g.setStatus({code:SpanStatusCode.ERROR,message:`status ${D}`})}catch(e){throw g.recordException(e),g.setStatus({code:SpanStatusCode.ERROR,message:e instanceof Error?e.message:String(e)}),!t.headersSent&&!t.writableEnded&&!t.destroyed&&errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:E,cause:e}),e}finally{g.end();let e=(Date.now()-O)/1e3;httpDurationHist().record(e,{[ATTR_HTTP_REQUEST_METHOD]:w,[ATTR_HTTP_ROUTE]:E,[ATTR_HTTP_RESPONSE_STATUS_CODE]:t.statusCode})}}))}}}function errnoCode(e){let t=e?.code;return typeof t==`string`?t:void 0}function seedSingleDirBasenameIndex(e){let t;try{t=readdirSync(e.contentDir,{withFileTypes:!0})}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`read-failed`,s,e.contentDir);return}for(let s of t)s.isFile()&&isSupportedAssetFile(s.name,ASSET_EXTENSIONS)&&e.basenameIndex.add(s.name)}async function seedBasenameIndex(e){let t=e.contentDir,s=new Set;async function g(S){let w;try{w=await readdir(S,{withFileTypes:!0})}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`read-failed`,s,S);return}for(let E of w){let w=join(S,E.name),D=toPosix(relative(t,w));if(D.startsWith(`..`)||e.contentFilter?.isDirExcluded(D)&&E.isDirectory())continue;let O;try{O=await lstat(w)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`lstat-failed`,s,w);continue}if(O.isSymbolicLink()){let S;try{S=await realpath(w)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`realpath-failed`,s,w);continue}if(!isWithinDir(S,t)){e.onSkip?.(`symlink-escape`,void 0,w);continue}let E;try{E=await stat$1(S)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`symlink-stat-failed`,s,S);continue}if(s.has(E.ino))continue;s.add(E.ino),E.isDirectory()?await g(S):E.isFile()&&isSupportedAssetFile(w,LINKABLE_ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(D)&&e.basenameIndex.add(D);continue}if(O.isDirectory()){if(s.has(O.ino))continue;s.add(O.ino),await g(w);continue}O.isFile()&&isSupportedAssetFile(w,LINKABLE_ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(D)&&e.basenameIndex.add(D)}}await g(t)}var AutoStartDisabledError=class extends Error{constructor(e){super(e),this.name=`AutoStartDisabledError`}};const log$5=getLogger(`conflict-storage`);var ConflictStore=class{storePath;projectDir;branch;conflicts=[];constructor(e,t=`main`){this.storePath=join(getLocalDir(e),`conflicts.json`),this.projectDir=e,this.branch=t,this.load()}load(){if(!existsSync(this.storePath)){this.conflicts=[];return}try{let e=readFileSync(this.storePath,`utf-8`),t=JSON.parse(e);if(t.version!==1){log$5.warn({path:this.storePath},`[conflicts] unknown schema version — resetting`),this.conflicts=[];return}this.branch=t.branch??this.branch,this.conflicts=t.conflicts??[]}catch(e){log$5.warn({err:e},`[conflicts] failed to load conflicts.json — starting empty`),this.conflicts=[]}}save(){try{let e=dirname(this.storePath);existsSync(e)||mkdirSync(e,{recursive:!0});let t={version:1,branch:this.branch,conflicts:this.conflicts};writeFileSync(this.storePath,JSON.stringify(t,null,2),`utf-8`)}catch(e){log$5.warn({err:e},`[conflicts] failed to save conflicts.json`)}}addConflict(e){let t=this.conflicts.findIndex(t=>t.file===e.file);t===-1?this.conflicts.push(e):this.conflicts[t]=e,this.save()}removeConflict(e){this.conflicts=this.conflicts.filter(t=>t.file!==e),this.save()}clear(){this.conflicts=[],this.save()}count(){return this.conflicts.length}list(){return[...this.conflicts]}hasConflicts(){return this.conflicts.length>0}setBranch(e){this.branch=e}async resolveConflict(e,t,s,g=[]){if(!this.conflicts.find(t=>t.file===e))throw Error(`[conflicts] no conflict tracked for file: ${e}`);if(t===`content`&&s===void 0)throw Error(`[conflicts] strategy 'content' requires content parameter`);let{createGitInstance:S}=await import(`./git-handle-DdgvPBh6-Dv4DjLoy.mjs`),w=S(this.projectDir,{credentialArgs:g});switch(t){case`mine`:await w.git.raw([`checkout`,`--ours`,`--`,e]),await w.git.raw([`add`,`--`,e]);break;case`theirs`:await w.git.raw([`checkout`,`--theirs`,`--`,e]),await w.git.raw([`add`,`--`,e]);break;case`content`:{if(s===void 0)throw Error(`[conflicts] strategy 'content' requires content parameter`);let t=resolve(this.projectDir),g=resolve(t,e);if(!isWithinDir(g,t))throw Error(`[conflicts] file path escapes project directory: ${e}`);writeFileSync(g,s,`utf-8`),await w.git.raw([`add`,`--`,e]);break}case`delete`:await w.git.raw([`rm`,`--`,e]);break;default:throw Error(`[conflicts] unknown resolve strategy: ${t}`)}if(this.removeConflict(e),!this.hasConflicts())try{await w.git.raw([`commit`,`--no-edit`]),log$5.info({file:e},`[conflicts] all conflicts resolved — merge commit created`)}catch(t){let s=new Date().toISOString(),g=!1;try{let e=(await w.git.raw([`diff`,`--name-only`,`--diff-filter=U`])).split(`
1939
1943
  `).map(e=>e.trim()).filter(Boolean);for(let t of e)this.addConflict({file:t,detectedAt:s});g=e.length>0}catch(e){log$5.warn({err:e},`[conflicts] commit failed and re-scan of unmerged files failed — falling back to single-file re-add`)}g||this.addConflict({file:e,detectedAt:s}),log$5.warn({err:t},`[conflicts] failed to commit merge after all conflicts resolved — unmerged files re-added`);let S=t instanceof Error?t.message:String(t);throw Error(`Merge commit failed after resolving ${e}; ${g?`unmerged files re-added`:`original file re-added`} — ${S}`,{cause:t})}}};const GIT_PREFLIGHT_FAIL_SPAN_NAME=`ok.preflight.git.fail`;function emitPreflightFailureSpan(e){let t=e instanceof GitTooOldError?`too_old`:`not_available`,s=e instanceof GitTooOldError?e.detected:``;withSpanSync(GIT_PREFLIGHT_FAIL_SPAN_NAME,{attributes:{"ok.platform":e.platform,"ok.preflight.git.reason":t,"ok.preflight.git.detected_version":s}},()=>{})}const DEFAULT_WARN_BEFORE_MS=300*1e3;function attachIdleShutdown(e){let t=e.scheduler??defaultScheduler,s=e.warnBeforeMs??DEFAULT_WARN_BEFORE_MS,g=0,S=null,w=null,E=!1,D=!1;function O(){S!==null&&(t.clearTimeout(S),S=null),w!==null&&(t.clearTimeout(w),w=null)}function k(){O(),!(D||E)&&g===0&&(s>0&&s<e.thresholdMs&&(w=t.setTimeout(()=>{w=null,g===0&&!E&&e.log?.warn({msUntilShutdown:s,webSocketClientCount:0},`idle shutdown pending: no WebSocket clients`)},e.thresholdMs-s)),S=t.setTimeout(()=>{if(S=null,!(D||E)&&g===0){E=!0,e.log?.info({webSocketClientCount:0},`idle shutdown firing`);try{let t=e.onShutdown();t&&typeof t.then==`function`&&t.catch(t=>{e.log?.error({err:t},`idle shutdown handler rejected`)})}catch(t){e.log?.error({err:t},`idle shutdown handler threw`)}}},e.thresholdMs))}let j=(e,t)=>{e.url?.startsWith(`/collab`)&&(g++,O(),t.once(`close`,()=>{g--,g<0&&(g=0),g===0&&k()}))};return e.httpServer.on(`upgrade`,j),k(),{detach:()=>{D||(D=!0,e.httpServer.off(`upgrade`,j),O())}}}function isObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function readRawSinkBlock(e){if(!existsSync(e))return{};let t;try{t=(0,import_dist$1.parse)(readFileSync(e,`utf-8`))}catch(t){return console.warn(`[telemetry.localSink] failed to parse ${e}; falling back to schema defaults — any explicit telemetry.localSink fields in this file are being ignored. Reason: ${t instanceof Error?t.message:String(t)}`),{}}if(!isObject(t))return{};let s=t.telemetry;if(!isObject(s))return{};let g=s.localSink;return isObject(g)?g:{}}function readBoolean(e){return typeof e==`boolean`?e:void 0}function readPositiveNumber(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?e:void 0}function readStringArray(e){if(Array.isArray(e)&&e.every(e=>typeof e==`string`))return e}function readMaxBytes(e){if(isObject(e))return readPositiveNumber(e.maxBytes)}function resolveLocalSinkConfig(e){if(process.env.OK_DISABLE_LOCAL_SINK===`1`||process.env.OK_DISABLE_LOCAL_SINK===`true`)return null;let t=readRawSinkBlock(resolveConfigPath(`project`,e.projectDir)),s=readRawSinkBlock(resolveConfigPath(`project-local`,e.projectDir));if((readBoolean(s.enabled)??readBoolean(t.enabled)??!0)===!1)return null;let g=readMaxBytes(s.spans)??readMaxBytes(t.spans)??52428800,S=readMaxBytes(s.logs)??readMaxBytes(t.logs)??26214400,w=readStringArray(s.attributeDenylist)??readStringArray(t.attributeDenylist)??DEFAULT_TELEMETRY_ATTRIBUTE_DENYLIST;return{telemetry:{projectDir:e.projectDir,spansMaxBytes:g,attributeDenylist:w},logs:{projectDir:e.projectDir,maxBytes:S}}}const MCP_CONNECTION_ID_HEADER=`x-ok-connection-id`;function sanitizeClientName(e,t){let s=Array.from(e??``).map(e=>{let t=e.charCodeAt(0);return t<=31||t===127?` `:e}).join(``).replace(/\s+/g,` `).trim();return s?s.slice(0,128):t}function installPrettyZodErrors(e){let t=e;if(t.__prettyZodErrorsInstalled===!0)return;let s=t.validateToolInput;if(typeof s!=`function`){console.warn(`[pretty-zod-errors] McpServer.validateToolInput not found — SDK internals may have changed. Falling back to default error formatting.`);return}t.validateToolInput=async function(e,t,g){if(!e.inputSchema||!isZodSchema(e.inputSchema))return s.call(this,e,t,g);let S=await e.inputSchema.safeParseAsync(t);if(S.success)return S.data;let w=prettifyError(S.error);throw new McpError(ErrorCode.InvalidParams,`Input validation error: Invalid arguments for tool ${g}:\n${w}`)},t.__prettyZodErrorsInstalled=!0}function isZodSchema(e){return typeof e!=`object`||!e?!1:typeof e.safeParseAsync==`function`}const loggerContext=new AsyncLocalStorage;var McpLogger=class e{sessionId;corrId;component;constructor(e=`mcp`,t){this.sessionId=t??randomUUID$1().slice(0,12),this.corrId=randomUUID$1().slice(0,8),this.component=e}info(e,t={}){this.emit(`info`,e,t)}warn(e,t={}){this.emit(`warn`,e,t)}error(e,t,s={}){let g=t?{error:t instanceof Error?t.message:String(t),...s}:s;this.emit(`error`,e,g)}debug(e,t={}){(process.env.MCP_DEBUG===`1`||process.env.DEBUG?.includes(`mcp`))&&this.emit(`debug`,e,t)}child(t){return new e(t??this.component,this.sessionId)}asCallback(){return e=>this.info(e)}emit(e,t,s){let g={ts:new Date().toISOString(),level:e,sessionId:this.sessionId,corrId:this.corrId,component:this.component,msg:t,...s},S=`${JSON.stringify(g)}\n`;process.stderr.write(S);let w=process.env.OK_LOG_FILE;if(w)try{appendFileSync(w,S)}catch(e){console.warn(`[mcp-logger] Failed to write to OK_LOG_FILE: ${e instanceof Error?e.message:e}`)}}};function runWithMcpLogger(e,t){return loggerContext.run(e,t)}function getCurrentMcpLogger(){return loggerContext.getStore()}const REDACTED_STRING_KEYS=new Set([`find`,`markdown`,`replace`]),COMMON_ARRAY_KEYS=[`backlinks`,`deadLinks`,`documents`,`enrichedPaths`,`entries`,`forwardLinks`,`hints`,`hubs`,`orphans`,`results`],COMMON_SCALAR_KEYS=[`checkpointRef`,`cwd`,`fileCount`,`matchCount`,`ok`,`query`,`stdoutTruncated`,`truncated`];function isPlainObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isToolExtraLike(e){return isPlainObject(e)&&`requestId`in e}function summarizeStringForLog(e,t){if(REDACTED_STRING_KEYS.has(e))return{redacted:!0,type:`string`,length:t.length,lines:t.length===0?0:t.split(`
1940
1944
  `).length};let s=e===`command`?240:120;return t.length<=s?t:{type:`string`,length:t.length,preview:`${t.slice(0,s)}...`}}function summarizeArgValue(e,t){if(t===null)return null;if(typeof t==`string`)return summarizeStringForLog(e,t);if(typeof t==`number`||typeof t==`boolean`)return t;if(Array.isArray(t))return{type:`array`,length:t.length};if(isPlainObject(t)){let e=Object.keys(t).sort();return{type:`object`,keyCount:e.length,keys:e.slice(0,12)}}if(t!==void 0)return{type:typeof t}}function summarizeArgsForLog(e,t){return isPlainObject(t)?Object.fromEntries(Object.entries(t).map(([e,t])=>[e,summarizeArgValue(e,t)])):summarizeArgValue(e,t)}function summarizeStructuredContentForLog(e){let t={structuredKeys:Object.keys(e).sort()};for(let s of COMMON_SCALAR_KEYS)s in e&&(t[s]=e[s]);for(let s of COMMON_ARRAY_KEYS){let g=e[s];Array.isArray(g)&&(t[`${s}Count`]=g.length)}return`previewUrl`in e&&(t.previewUrl=e.previewUrl??null),`previewUrlSource`in e&&(t.previewUrlSource=e.previewUrlSource),Array.isArray(e.warnings)&&(t.warningsCount=e.warnings.length),isPlainObject(e.warning)&&(t.warning=!0,`previewUrl`in e.warning&&(t.warningPreviewUrl=e.warning.previewUrl??null)),t}function summarizeToolResultForLog(e){if(!isPlainObject(e))return{resultType:typeof e};let t={isError:e.isError===!0};return Array.isArray(e.content)&&(t.contentItems=e.content.length,t.contentTextChars=e.content.reduce((e,t)=>isPlainObject(t)&&typeof t.text==`string`?e+t.text.length:e,0)),isPlainObject(e.structuredContent)&&Object.assign(t,summarizeStructuredContentForLog(e.structuredContent)),t}function summarizeIdentityForLog(e){return{connectionId:e.connectionId.slice(0,8),displayName:e.displayName,...e.clientInfo?.name?{clientName:e.clientInfo.name}:{}}}function splitInvocationArgs(e){let t=e.at(-1);return isToolExtraLike(t)?{toolArgs:e.length>1?e[0]:void 0,extra:t}:{toolArgs:e[0],extra:void 0}}function wrapToolHandlerForLogging(e,t,s){let g=s.logger;return g?async(...S)=>{let w=g.child(),E=Date.now(),{toolArgs:D,extra:O}=splitInvocationArgs(S);w.info(`tool start`,{tool:e,...O?.requestId===void 0?{}:{requestId:O.requestId},...O?.sessionId?{transportSessionId:O.sessionId}:{},...s.identityRef?.current?{agent:summarizeIdentityForLog(s.identityRef.current)}:{},...D===void 0?{}:{args:summarizeArgsForLog(e,D)}});try{let s=await runWithMcpLogger(w,async()=>await t(...S));return w.info(`tool finish`,{tool:e,...O?.requestId===void 0?{}:{requestId:O.requestId},durationMs:Date.now()-E,result:summarizeToolResultForLog(s)}),s}catch(t){throw w.error(`tool error`,t,{tool:e,...O?.requestId===void 0?{}:{requestId:O.requestId},durationMs:Date.now()-E}),t}}:t}function createLoggedServer(e,t){if(!t.logger)return e;let s=e.tool.bind(e),g=e.registerTool,S=typeof g==`function`?g.bind(e):void 0,w=Object.create(e);return w.tool=((...e)=>{let g=String(e[0]),S=e.at(-1);if(typeof S!=`function`)return s(...e);let w=[...e];return w[w.length-1]=wrapToolHandlerForLogging(g,S,t),s(...w)}),S&&(w.registerTool=((e,s,g)=>typeof g==`function`?S(e,s,wrapToolHandlerForLogging(e,g,t)):S(e,s,g))),w}const DESCRIPTION$18=[`[Requires: Hocuspocus server] Save a project-wide checkpoint of every document — a single restore point you can return to.`,``,`**Parameters:**`,'- `summary` — Optional one-line label for the checkpoint (≤80 chars). Defaults to "Checkpoint version". Appears as the checkpoint subject in `history`. Avoid secrets or PII — persisted to git history.',``,"Returns `{ version }` — the 40-char checkpoint SHA. Find checkpoints later via `history`; restore a single doc with `restore_version({ document, version })`."].join(`
1941
1945
  `);function register$18(e,t){e.registerTool(`checkpoint`,{description:DESCRIPTION$18,inputSchema:{summary:summaryArgSchema.describe(`Optional one-line label for the checkpoint (≤80 chars). Defaults to "Checkpoint version". Persisted to git history.`),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({version:string().describe(VERSION_FIELD_DESCRIBE),previewUrl:previewUrlOutputField.describe(`Always null — a checkpoint is project-wide, not scoped to one doc.`)})},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{url:g}=s;if(!g)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let S=t.identityRef?.current,w=await httpPost(g,`/api/save-version`,{...e.summary===void 0?{}:{summary:e.summary},...S?{writers:[{id:`agent-${S.connectionId}`,name:S.displayName,email:`agent-${S.connectionId}@openknowledge.local`}]}:{}});if(!w.ok)return textResult(`Error: ${w.error}`,!0);let E=typeof w.checkpointRef==`string`?w.checkpointRef:``,D=E.split(`/`).pop()??``;return/^[0-9a-f]{40}$/i.test(D)?textPlusStructured(`Checkpoint saved. Version: ${D}`,{version:D,previewUrl:null}):textResult(`Error: checkpoint committed but the server returned no usable version ref ("${E}"). Find the latest checkpoint via \`history\`.`,!0)})}const DESCRIPTION$17=[`[Operates on disk; no running OK server required] Read the effective merged OpenKnowledge config (defaults → user → project).`,``,`Use this when you need to inspect the config mid-session — e.g., after a write that may have changed disk state, or to re-confirm the value of a field before reading it again.`,``,"Read returns the FULL merged config or a sub-tree when `key` is provided. There is no allowlist on reads — every field is readable.",``,"Note: the `server.*`, `mcp.*`, and `github.*` config sub-trees, plus `preview.baseUrl` and `preview.scriptSrc`, were removed; their values are now built-in constants in `@inkeep/open-knowledge-core` (or, for the preview iframe, a fixed open network policy). Reading those keys returns `exists: false`. (`appearance.preview.autoOpen` is still a live key.)",``,`**Parameters:**`,'- `key` (optional) — Dotted config key. `"content"` returns the content sub-tree; `"appearance.theme"` returns just that leaf. Omit for full config.',"- `cwd` (optional) — Project root (see `cwd` description below)."].join(`
@@ -1945,11 +1949,11 @@ Change history for this knowledge base, newest entry first. Add a dated entry (\
1945
1949
  `),{skill:{ok:!0,path:w,created:S},...O?{previewUrl:O.url,previewUrlSource:O.source}:{}})}async function fetchSkill(e,t,s){let g=await httpGet(e,`/api/skill?${new URLSearchParams({name:s,scope:t}).toString()}`);if(!g.ok)return{ok:!1,error:String(g.error),notFound:g.httpStatus===404};let S=g.skill,w=Array.isArray(S?.files)?S.files.map(e=>typeof e?.path==`string`?{path:e.path}:null).filter(e=>e!==null):[];return{ok:!0,description:typeof S?.frontmatter?.description==`string`?S.frontmatter.description:``,body:typeof S?.body==`string`?S.body:``,files:w}}async function writeSkillFile(e,t){let s=resolveSkillName(t.name);if(!s.ok)return textResult(`Error: ${s.error}`,!0);if(!e)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let g=await httpPut(e,`/api/skill-file`,{...t.scope===void 0?{}:{scope:t.scope},name:t.name,path:t.path,content:t.content,...t.summary===void 0?{}:{summary:t.summary},...agentIdentityFields(t.identity)});if(!g.ok)return textResult(`Error: ${g.error}`,!0);let S=g.created===!0,w=typeof g.path==`string`?g.path:t.path,E=g.kind===`script`?`script`:`reference`;return textPlusStructured(`${S?`Created`:`Updated`} skill ${E} "${t.path}" in "${t.name}". Run \`install\` if not yet projected.`,{skill:{ok:!0,file:{path:w,kind:E,created:S}}})}async function readSkillFile(e,t,s,g){let S=await httpGet(e,`/api/skill-file?${new URLSearchParams({name:s,scope:t,path:g}).toString()}`);return S.ok?{ok:!0,path:typeof S.path==`string`?S.path:g,kind:S.kind===`script`?`script`:`reference`,text:typeof S.text==`string`?S.text:``}:{ok:!1,error:String(S.error),status:S.httpStatus}}async function deleteSkillFile(e,t){let s=resolveSkillName(t.name);if(!s.ok)return textResult(`Error: ${s.error}`,!0);if(!e)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let g=new URLSearchParams({name:t.name,scope:t.scope??`project`,path:t.path});t.summary!==void 0&&g.set(`summary`,t.summary),appendIdentityParams(g,t.identity);let S=await httpDelete(e,`/api/skill-file?${g.toString()}`);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let w=S.existed===!0;return textPlusStructured(w?`Deleted skill file "${t.path}" from "${t.name}".`:`Skill file "${t.path}" did not exist in "${t.name}" — nothing to delete.`,{skill:{ok:!0,file:{path:t.path,existed:w}}})}async function deleteSkill(e,t){let s=resolveSkillName(t.name);if(!s.ok)return textResult(`Error: ${s.error}`,!0);if(!e)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let g=new URLSearchParams({name:t.name,scope:t.scope??`project`});t.summary!==void 0&&g.set(`summary`,t.summary),appendIdentityParams(g,t.identity);let S=await httpDelete(e,`/api/skill?${g.toString()}`);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let w=S.existed===!0;return textPlusStructured(w?`Deleted skill "${t.name}".`:`Skill "${t.name}" did not exist — nothing to delete.`,{skill:{ok:!0,existed:w}})}async function moveSkill(e,t){let s=resolveSkillName(t.fromName);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let g=resolveSkillName(t.toName);if(!g.ok)return textResult(`Error: ${g.error}`,!0);if(!e)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let S=await httpPost(e,`/api/skill`,{...t.scope===void 0?{}:{scope:t.scope},fromName:t.fromName,toName:t.toName,...t.summary===void 0?{}:{summary:t.summary},...agentIdentityFields(t.identity)});if(!S.ok){let e=typeof S.error==`string`?S.error:`Skill move failed`;return textPlusStructured(`Error: ${e}`,{ok:!1,kind:`skill`,error:e},!0)}let w=S.committed===!0,E=typeof S.from==`string`?S.from:t.fromName,D=typeof S.to==`string`?S.to:t.toName;return textPlusStructured(`${w?`Renamed`:`Moved`} skill ${E} → ${D}.${w?``:" (Untracked `.ok/` — moved on disk without git history.)"} Run \`install\` to re-project under the new name.`,{ok:!0,kind:`skill`,committed:w})}async function moveSkillCrossScope(e,t){let s=resolveSkillName(t.fromName);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let g=resolveSkillName(t.toName);if(!g.ok)return textResult(`Error: ${g.error}`,!0);if(!e)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let S=await fetchSkill(e,t.fromScope,t.fromName);if(!S.ok)return textPlusStructured(`Error: ${S.error}`,{ok:!1,kind:`skill`,error:S.error},!0);let w=await fetchSkill(e,t.toScope,t.toName);if(w.ok)return textPlusStructured(`Error: a ${t.toScope===`global`?`Global`:`Project`} skill named "${t.toName}" already exists — delete or rename it first (cross-level move will not overwrite it).`,{ok:!1,kind:`skill`,error:`destination already exists`},!0);if(!w.notFound)return textPlusStructured(`Error: could not verify the ${t.toScope} destination "${t.toName}" is free (${w.error}); aborting before any write so an existing skill can't be overwritten. Retry once the server is reachable.`,{ok:!1,kind:`skill`,error:w.error},!0);let E=await httpPut(e,`/api/skill`,{scope:t.toScope,name:t.toName,body:S.body,frontmatter:{name:t.toName,description:S.description},...t.summary===void 0?{}:{summary:t.summary},...agentIdentityFields(t.identity)});if(!E.ok){let e=typeof E.error==`string`?E.error:`Skill move failed`;return textPlusStructured(`Error: ${e}`,{ok:!1,kind:`skill`,error:e},!0)}let D=[];for(let s of S.files){let g=await readSkillFile(e,t.fromScope,t.fromName,s.path);if(!g.ok){if(g.status===415){D.push(s.path);continue}return textPlusStructured(`Error: copied skill "${t.toName}" into ${t.toScope} scope, but reading its bundle file "${s.path}" from the source failed (${g.error}); aborting before deleting the source. The original ${t.fromScope} skill is intact — retry or fix the file, then move again. (A partial ${t.toScope} copy may exist; delete it first.)`,{ok:!1,kind:`skill`,error:g.error},!0)}let S=await httpPut(e,`/api/skill-file`,{scope:t.toScope,name:t.toName,path:s.path,content:g.text,...t.summary===void 0?{}:{summary:t.summary},...agentIdentityFields(t.identity)});if(!S.ok){let e=typeof S.error==`string`?S.error:`bundle-file copy failed`;return textPlusStructured(`Error: copied skill "${t.toName}" into ${t.toScope} scope, but copying its bundle file "${s.path}" failed (${e}); aborting before deleting the source. The original ${t.fromScope} skill is intact — retry. (A partial ${t.toScope} copy may exist; delete it first.)`,{ok:!1,kind:`skill`,error:e},!0)}}let O=new URLSearchParams({name:t.fromName,scope:t.fromScope});t.summary!==void 0&&O.set(`summary`,t.summary),appendIdentityParams(O,t.identity);let k=await httpDelete(e,`/api/skill?${O.toString()}`);if(!k.ok){let e=typeof k.error==`string`?k.error:`source delete failed`;return textPlusStructured(`Partially moved skill "${t.fromName}" → ${t.toScope} scope as "${t.toName}", but deleting the ${t.fromScope}-scope original failed (${e}). The skill now exists in BOTH scopes — delete the ${t.fromScope} copy manually. Run \`install\` to project the new ${t.toScope} skill.`,{ok:!1,kind:`skill`,error:e,bothScopes:!0},!0)}let j=t.fromScope===`global`?`Global`:`Project`,F=t.toScope===`global`?`Global`:`Project`,L=D.length>0?` ${D.length} binary/oversize bundle file(s) were NOT copied (outside the text-only bundle contract): ${D.join(`, `)}.`:``;return textPlusStructured(`Moved skill "${t.fromName}" (${j}) → "${t.toName}" (${F}) with its references and scripts. History did not transfer — it lands as a fresh Draft in the ${F} level. Run \`install\` to project it for the new level.${L}`,{ok:!0,kind:`skill`,committed:!1,crossScope:!0,...D.length>0?{skippedBinaryFiles:D}:{}})}const DESCRIPTION$15=["Delete one thing. Pass EXACTLY ONE of `document`, `folder`, `template`, `skill`, or `asset`.",``,"- `document` — Doc path(s) to delete (a single path or an array). Inbound links become redlinks. Irreversible. [Requires: Hocuspocus server]","- `folder` — Folder path to delete (recursive). [Requires: Hocuspocus server]",'- `template` — `{ path: "<folder>/<name>" }` — a template to delete (server-routed, attributed; auto-cleans empty `.ok/`). [Requires: Hocuspocus server]','- `skill` — `{ name }` deletes a whole SKILL; `{ name, files: ["references/x.md"] }` deletes specific bundle files (server-routed, attributed; auto-cleans empty `.ok/`). [Requires: Hocuspocus server]','- `asset` — `{ path: "<folder>/<file.ext>" }` — a binary asset to delete. [Requires: Hocuspocus server]',``,'Call `links({ kind: "backlinks", document })` BEFORE deleting a doc to see what links here.'].join(`
1946
1950
  `);function parseDeletedDocNames(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}async function deleteOneDoc(e,t,s,g){let S=normalizeDocName(e);if(!S.ok)return{docName:e,ok:!1,error:S.error.replace(/^Error:\s*/,``)};let w=await httpPost(t,`/api/delete-path`,{kind:`file`,path:S.docName,...agentIdentityFields(g.identityRef?.current)});if(!w.ok)return{docName:S.docName,ok:!1,error:w.error};let E=parseDeletedDocNames(w.deletedDocNames),D=await resolvePreviewUrlForTool(S.docName,{config:g.config,resolveCwd:g.resolveCwd},s);return{docName:S.docName,ok:!0,deletedDocNames:E.length>0?E:[S.docName],...D?{previousPreviewUrl:D.url}:{}}}function register$15(e,t){e.registerTool(`delete`,{description:DESCRIPTION$15,inputSchema:{document:union([string(),array(string()).min(1),object$1({path:union([string(),array(string()).min(1)])})]).optional().describe("Doc path(s) to delete — a string, an array, or `{ path }`. Inbound links become redlinks. Irreversible."),folder:union([string(),object$1({path:string()})]).optional().describe("Folder path to delete (recursive) — a string or `{ path }`."),template:object$1({path:string().describe("Template path = `<folder>/<name>`.")}).optional().describe(`A template to delete.`),skill:object$1({name:string().describe(SKILL_NAME_DESCRIBE),files:array(string()).min(1).optional().describe("Skill-relative bundle file paths to delete (`references/...`/`scripts/...`). Omit to delete the WHOLE skill (`.ok/skills/<name>/`)."),scope:SkillScopeArg.optional()}).optional().describe("A skill to delete — the whole skill (`.ok/skills/<name>/`), or specific bundle files when `files` is set."),asset:object$1({path:string().describe(`Asset path incl. extension — the slashes are its folder. Example: "images/diagram.png".`)}).optional().describe(`A binary asset to delete.`),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({document:object$1({ok:boolean(),deletedDocNames:array(string()).optional().describe(`The single docName removed (a document delete never cascades to descendants).`),error:string().optional().describe("Present when `ok` is false.")}).optional().describe(`Single-document delete result.`),folder:object$1({ok:boolean(),deletedDocNames:array(string())}).optional().describe(`Folder delete result (docNames removed).`),template:object$1({ok:boolean(),existed:boolean()}).optional().describe(`Template delete result.`),skill:object$1({ok:boolean(),existed:boolean().optional(),files:looseObjectArray.optional().describe("Per-bundle-file delete results `{ path, ok, existed?, error? }`.")}).optional().describe(`Skill delete result (whole skill or specific bundle files).`),asset:object$1({ok:boolean(),path:string()}).optional().describe(`Asset delete result.`),documents:looseObjectArray.optional().describe(`Batch doc delete: per-doc result records.`),previousPreviewUrl:previousPreviewUrlField})},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,url:S}=s,w=typeof e.folder==`object`?e.folder.path:e.folder,E=e.document&&typeof e.document==`object`&&!Array.isArray(e.document)?e.document.path:e.document,D=exactlyOneTargetError(e,[`document`,`folder`,`template`,`skill`,`asset`]);if(D)return textResult(`Error: ${D}`,!0);if(e.skill!==void 0){let s=e.skill;if(s.files!==void 0&&s.files.length>0){for(let e of s.files){let t=resolveSkillFilePath(e);if(!t.ok)return textResult(`Error: ${t.error}`,!0)}let e=[];for(let g of s.files){let w=await deleteSkillFile(S,{name:s.name,scope:s.scope,path:g,identity:t.identityRef?.current}),E=w.structuredContent;w.isError?e.push({path:g,ok:!1,error:w.content[0]?.text??`delete failed`}):e.push({path:g,ok:!0,existed:E?.skill?.file?.existed===!0})}let g=e.filter(e=>e.ok).length,w=g===e.length,E=e.map(e=>e.ok?`${e.existed?`Deleted`:`No-op (absent)`} ${e.path}.`:`Failed ${e.path}: ${e.error}`);return textPlusStructured(`${g}/${e.length} skill file(s) processed.\n${E.join(`
1947
1951
  `)}`,{skill:{ok:w,files:e}},!w)}return deleteSkill(S,{name:s.name,scope:s.scope,identity:t.identityRef?.current})}if(e.template!==void 0){let s=resolveTemplatePath(e.template.path);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{folder:g,name:w}=s;if(!S)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let E=new URLSearchParams({folder:g,name:w});for(let[e,s]of Object.entries(agentIdentityFields(t.identityRef?.current)))typeof s==`string`&&s.length>0&&E.set(e,s);let D=await httpDelete(S,`/api/template?${E.toString()}`);if(!D.ok)return textResult(`Error: ${D.error}`,!0);let O=D.existed===!0;return textPlusStructured(O?`Deleted template "${w}" from ${g||`(root)`}.`:`Template "${w}" did not exist in ${g||`(root)`} — nothing to delete.`,{template:{ok:!0,existed:O}})}if(!S)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);if(e.folder!==void 0){let e=await httpPost(S,`/api/delete-path`,{kind:`folder`,path:w,...agentIdentityFields(t.identityRef?.current)});if(!e.ok)return textResult(`Error: ${e.error}`,!0);let s=parseDeletedDocNames(e.deletedDocNames);return textPlusStructured(`Deleted folder ${w}${s.length?` (${s.length} doc(s))`:``}.`,{folder:{ok:!0,deletedDocNames:s}})}if(e.asset!==void 0){let s=e.asset.path.replace(/^\/+/,``).replace(/\/+$/,``),g=await httpPost(S,`/api/delete-path`,{kind:`asset`,path:s,...agentIdentityFields(t.identityRef?.current)});return g.ok?textPlusStructured(`Deleted asset ${s}.`,{asset:{ok:!0,path:s}}):textResult(`Error: ${g.error}`,!0)}let O=E;if(Array.isArray(O)){let e=await Promise.all(O.map(e=>deleteOneDoc(e,S,g,t))),s=e.filter(e=>e.ok).length,w=s===e.length,E=e.map(e=>e.ok?`Deleted ${e.docName}.`:`Failed ${e.docName}: ${e.error}`);return textPlusStructured(`${s}/${e.length} deleted.\n${E.join(`
1948
- `)}`,{documents:e},!w)}let k=await deleteOneDoc(O,S,g,t);if(!k.ok)return textPlusStructured(`Error: ${k.error??`unknown error`}`,{document:{ok:!1,error:k.error}},!0);let j=k.deletedDocNames??[k.docName];return textPlusStructured(j.length===1?`Deleted ${j[0]}.`:`Deleted ${j.length} documents: ${j.join(`, `)}.`,{document:{ok:!0,deletedDocNames:j},...k.previousPreviewUrl?{previousPreviewUrl:k.previousPreviewUrl}:{}})})}function parseAdvisoryWarnings(e){if(!Array.isArray(e))return;let t=e.flatMap(e=>{let t=AdvisoryWarningSchema.safeParse(e);return t.success?[t.data]:[]});return t.length>0?t:void 0}function integrityEntries(e){return e.filter(e=>e.kind===`content-divergence`||e.kind===`disk-edit-reconciled`)}function renderEntries(e){return e.filter(e=>e.kind===`mermaid-parse-error`)}function formatAdvisoryLines(e){let t=integrityEntries(e).map(formatIntegrityLine),s=renderEntries(e);return s.length>0&&t.push(formatRenderWarningsLine(s)),t}function formatAdvisoryBriefs(e){let t=integrityEntries(e).map(formatIntegrityBrief),s=renderEntries(e);return s.length>0&&t.push(formatRenderWarningsBrief(s)),t}function formatIntegrityLine(e){return e.kind===`content-divergence`?`⚠ Content divergence: ${e.actualBytes} actual bytes vs ${e.intendedBytes} intended (byteDelta=${e.byteDelta}). ${e.hint??`currentState carries the converged content (re-read only if it is truncated).`}`:`⚠ ${e.hint??`An out-of-band edit was reconciled into this document before your edit landed on top — re-read for the combined result.`}`}function formatIntegrityBrief(e){return e.kind===`content-divergence`?`⚠ Content divergence: ${e.actualBytes} actual vs ${e.intendedBytes} intended (byteDelta=${e.byteDelta}).`:`⚠ Out-of-band disk edit reconciled before this write — re-read for the combined result.`}function formatRenderWarningsLine(e){let t=e[0];if(e.length===1&&t){let e=t.line===void 0?``:` (line ${t.line})`,s=t.fenceFirstLine===``?`(empty fence)`:`("${t.fenceFirstLine}")`;return`⚠ Mermaid fence ${t.fenceIndex} ${s} will not render${e}: ${firstMessageLine(t.message)} Fix the fence and re-edit.`}return`⚠ ${e.length>=10?`10+`:String(e.length)} mermaid fences will not render — see structuredContent.document.warnings (kind "mermaid-parse-error") for per-fence errors. Fix the fences and re-edit.`}function formatRenderWarningsBrief(e){return`⚠ ${e.length>=10?`10+`:String(e.length)} mermaid fence${e.length===1?``:`s`} will not render (see warnings).`}function firstMessageLine(e){let t=e.split(`
1952
+ `)}`,{documents:e},!w)}let k=await deleteOneDoc(O,S,g,t);if(!k.ok)return textPlusStructured(`Error: ${k.error??`unknown error`}`,{document:{ok:!1,error:k.error}},!0);let j=k.deletedDocNames??[k.docName];return textPlusStructured(j.length===1?`Deleted ${j[0]}.`:`Deleted ${j.length} documents: ${j.join(`, `)}.`,{document:{ok:!0,deletedDocNames:j},...k.previousPreviewUrl?{previousPreviewUrl:k.previousPreviewUrl}:{}})})}function parseAdvisoryWarnings(e){if(!Array.isArray(e))return;let t=e.flatMap(e=>{let t=AdvisoryWarningSchema.safeParse(e);return t.success?[t.data]:[]});return t.length>0?t:void 0}function parseBrokenLinks(e){return Array.isArray(e)?e.flatMap(e=>{let t=BrokenLinkSchema.safeParse(e);return t.success?[t.data]:[]}):[]}function formatBrokenLinkLines(e){return e.length===0?[]:[`⚠ ${e.length} broken outbound link${e.length===1?``:`s`} — fix or remove (the write still landed):`,...e.map(e=>` • ${formatBrokenLink(e)}`)]}function formatBrokenLinkBrief(e){return e.length===0?null:`⚠ ${e.length} broken outbound link${e.length===1?``:`s`} (see brokenLinks).`}function formatBrokenLink(e){return e.resolvedTo?`${e.href} → ${e.resolvedTo} (${e.reason})`:`${e.href} (${e.reason})`}function integrityEntries(e){return e.filter(e=>e.kind===`content-divergence`||e.kind===`disk-edit-reconciled`)}function renderEntries(e){return e.filter(e=>e.kind===`mermaid-parse-error`)}function formatAdvisoryLines(e){let t=integrityEntries(e).map(formatIntegrityLine),s=renderEntries(e);return s.length>0&&t.push(formatRenderWarningsLine(s)),t}function formatAdvisoryBriefs(e){let t=integrityEntries(e).map(formatIntegrityBrief),s=renderEntries(e);return s.length>0&&t.push(formatRenderWarningsBrief(s)),t}function formatIntegrityLine(e){return e.kind===`content-divergence`?`⚠ Content divergence: ${e.actualBytes} actual bytes vs ${e.intendedBytes} intended (byteDelta=${e.byteDelta}). ${e.hint??`currentState carries the converged content (re-read only if it is truncated).`}`:`⚠ ${e.hint??`An out-of-band edit was reconciled into this document before your edit landed on top — re-read for the combined result.`}`}function formatIntegrityBrief(e){return e.kind===`content-divergence`?`⚠ Content divergence: ${e.actualBytes} actual vs ${e.intendedBytes} intended (byteDelta=${e.byteDelta}).`:`⚠ Out-of-band disk edit reconciled before this write — re-read for the combined result.`}function formatRenderWarningsLine(e){let t=e[0];if(e.length===1&&t){let e=t.line===void 0?``:` (line ${t.line})`,s=t.fenceFirstLine===``?`(empty fence)`:`("${t.fenceFirstLine}")`;return`⚠ Mermaid fence ${t.fenceIndex} ${s} will not render${e}: ${firstMessageLine(t.message)} Fix the fence and re-edit.`}return`⚠ ${e.length>=10?`10+`:String(e.length)} mermaid fences will not render — see structuredContent.document.warnings (kind "mermaid-parse-error") for per-fence errors. Fix the fences and re-edit.`}function formatRenderWarningsBrief(e){return`⚠ ${e.length>=10?`10+`:String(e.length)} mermaid fence${e.length===1?``:`s`} will not render (see warnings).`}function firstMessageLine(e){let t=e.split(`
1949
1953
  `,1)[0]?.trim()??``;return t.endsWith(`.`)||t.endsWith(`:`)?t:`${t}.`}const DESCRIPTION$14=`${["Edit one thing in place. Pass EXACTLY ONE of `document`, `folder`, `template`, or `skill`. Within each: a body edit (`find` + `replace`) OR a metadata patch — not both in one call.",``,"- `document` — Edit a doc [Requires: Hocuspocus server]. Body: `{ path, find, replace, occurrence? }` (occurrence = which match, 1 = first). Metadata: `{ path, frontmatter }` (merge-patch; `null` deletes a key). Body find/replace is body-only; frontmatter-intersecting finds are rejected.","- `folder` — Edit a folder (folders have no body): `{ path, frontmatter }` (merge-patch).",'- `template` — Edit a template: `{ path: "<folder>/<name>", ... }`; body `find`/`replace`/`occurrence?` or metadata `frontmatter`.',"- `skill` — Edit a SKILL: `{ name, ... }`; body `find`/`replace`/`occurrence?` OR a `description` change (a skill's only metadata leaf). Run `install` afterward to update your editors.","- `summary` — Optional one-line user-outcome (≤80 chars) recorded in the timeline for any `document`, `folder`, `template`, or `skill` edit. Avoid secrets or PII — persisted to git history.",``,'Responses may include `structuredContent.document.warnings` — advisory entries discriminated by `kind`: `content-divergence` / `disk-edit-reconciled` (write-integrity — re-read the doc with `exec("cat <path>")`) and `mermaid-parse-error` (the edit landed but that fence will not render — fix it and re-edit).'].join(`
1950
- `)}\n${renderInventoryFooter()}`;function bodyOrFrontmatterError(e,t){let s=e.find!==void 0||e.replace!==void 0,g=e.frontmatter!==void 0;return e.find!==void 0&&e.replace===void 0?`\`find\` needs a \`replace\`. Body edit: { ${t}: { …, find, replace } }.`:e.replace!==void 0&&e.find===void 0?`\`replace\` needs a \`find\`. Body edit: { ${t}: { …, find, replace } }.`:s&&g?`Pick ONE: edit body text (find+replace) OR metadata (frontmatter), not both in one call.`:!s&&!g?`Provide either a body edit (find+replace) or a frontmatter patch for { ${t} }.`:null}function readDocFullText(e,t){for(let s of SUPPORTED_DOC_EXTENSIONS){let g=resolveWithinRoot(e,`${t}${s}`);if(g.ok&&existsSync(g.abs))try{return readFileSync(g.abs,`utf-8`)}catch(e){if(e?.code===`ENOENT`)return null;throw e}}return null}function nthOccurrenceOffset(e,t,s){let g=0;for(let S=0;S<s;S++){let w=e.indexOf(t,g);if(w===-1)return-1;if(S===s-1)return w;g=w+Math.max(1,t.length)}return-1}async function handleDocBody(e,t,s,g,S,w,E){let D=normalizeDocName(e.path);if(!D.ok)return textResult(okReservedPathRedirect(e.path)??D.error,!0);let O=w.identityRef?.current,k,j=e.occurrence??1;if(j>1){let t;try{t=readDocFullText(g,D.docName)}catch(e){return textResult(`Error: cannot read "${D.docName}" to resolve occurrence ${j}: ${e instanceof Error?e.message:String(e)}.`,!0)}if(t===null)return textResult(`Error: cannot resolve occurrence ${j} — "${D.docName}" is not on disk yet. Retry with the first match (omit \`occurrence\`).`,!0);let s=nthOccurrenceOffset(t,e.find,j);if(s===-1)return textResult(`Error: \`find\` occurs fewer than ${j} times in "${D.docName}".`,!0);k=s}let F=await httpPost(S,`/api/agent-patch`,{docName:D.docName,find:e.find,replace:e.replace,...k===void 0?{}:{offset:k},...t.summary===void 0?{}:{summary:t.summary},...agentIdentityFields(O)});if(!F.ok){let e=typeof F.detail==`string`&&F.detail.length>0?F.detail:``;return textResult(e?`Error: ${F.error} (${e})`:`Error: ${F.error}`,!0)}return composeWritePreviewResult(F,D.docName,s,E,`Edit applied successfully.`)}async function handleDocFrontmatter(e,t,s,g,S,w){let E=normalizeDocName(e.path);if(!E.ok)return textResult(okReservedPathRedirect(e.path)??E.error,!0);let D=S.identityRef?.current,O=await httpPost(g,`/api/frontmatter-patch`,{docName:E.docName,patch:e.frontmatter,...t.summary===void 0?{}:{summary:t.summary},...agentIdentityFields(D)});if(!O.ok){let e=O.error,t=O.fieldErrors&&typeof O.fieldErrors==`object`?O.fieldErrors:void 0;return textResult(t?`Error: ${e}\n${Object.entries(t).map(([e,t])=>` ${e}: ${t}`).join(`
1951
- `)}`:`Error: ${e}`,!0)}let k=[],j=[];for(let[t,s]of Object.entries(e.frontmatter))s===null?j.push(t):k.push(t);let F=[k.length?`${k.length} set`:``,j.length?`${j.length} deleted`:``].filter(Boolean).join(`, `);return composeWritePreviewResult(O,E.docName,s,w,`Frontmatter patched (${F||`${Object.keys(e.frontmatter).length} key(s)`}).`)}function composeWritePreviewResult(e,t,s,g,S){let w=resolvePreviewUrl(t,{lockDir:resolveLockDir(s)}),E=typeof e.subscriberCount==`number`?e.subscriberCount:void 0,D=(typeof e.systemSubscriberCount==`number`?e.systemSubscriberCount:void 0)===0,O=E===0,k=e.summary&&typeof e.summary==`object`?e.summary:void 0,j=typeof k?.hint==`string`?k.hint:void 0,F=parseAdvisoryWarnings(e.warnings),L=[S];D&&!w&&L.push(START_UI_TEXT_HINT),j&&L.push(j),F&&L.push(...formatAdvisoryLines(F));let B=L.join(`
1952
- `);if(!w&&!D&&!O&&!k&&!F)return textResult(B);let H={};return k&&(H.summary=k),F&&(H.warnings=F),textPlusStructured(B,nestDocResult(w,D?buildPreviewAttachWarning(w,g):void 0,H))}function templateFilePath(e,t,s){let g=resolveWithinRoot(e,`${t.replace(/\/+$/,``)}/.ok/templates/${s}.md`);return g.ok?{ok:!0,abs:g.abs}:{ok:!1}}function parseTemplateFrontmatter(e){let t=unwrapFrontmatterFences(e).trim();if(t===``)return{title:``};let s=(0,import_dist$1.parse)(t);if(typeof s!=`object`||!s||Array.isArray(s))return{title:``};let g=s;return{title:typeof g.title==`string`?g.title:``,...typeof g.description==`string`?{description:g.description}:{},...Array.isArray(g.tags)?{tags:g.tags.map(e=>String(e))}:{}}}async function handleTemplate$1(e,t,s,g,S){let w=bodyOrFrontmatterError(e,`template`);if(w)return textResult(`Error: ${w}`,!0);let E=resolveTemplatePath(e.path);if(!E.ok)return textResult(`Error: ${E.error}`,!0);let{folder:D,name:O}=E;if(!g)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let k=templateFilePath(s,D,O);if(!k.ok||!existsSync(k.abs))return textResult(`Error: template "${O}" not found in ${D||`(root)`}. Create it with \`write({ template })\` first.`,!0);let j;try{j=readFileSync(k.abs,`utf-8`)}catch(e){return textResult(`Error: could not read template: ${e.message}`,!0)}let{frontmatter:F,body:L}=stripFrontmatter(j),B=parseTemplateFrontmatter(F);if(e.frontmatter!==void 0){let s=await httpPut(g,`/api/template`,{folder:D,name:O,body:L,frontmatter:mergePatch(B,e.frontmatter),...t===void 0?{}:{summary:t},...agentIdentityFields(S.identityRef?.current)});if(!s.ok)return textResult(`Error: ${s.error}`,!0);let w=typeof s.path==`string`?s.path:void 0;return textPlusStructured(`Patched template "${O}" frontmatter${w?` (${w})`:``}.`,{template:{ok:!0,path:w}})}let H=e.occurrence??1,q=nthOccurrenceOffset(L,e.find,H);if(q===-1)return textResult(`Error: \`find\` occurs fewer than ${H} time(s) in template "${O}".`,!0);let ee=await httpPut(g,`/api/template`,{folder:D,name:O,body:L.slice(0,q)+e.replace+L.slice(q+e.find.length),frontmatter:B,...t===void 0?{}:{summary:t},...agentIdentityFields(S.identityRef?.current)});if(!ee.ok)return textResult(`Error: ${ee.error}`,!0);let J=typeof ee.path==`string`?ee.path:void 0;return textPlusStructured(`Edited template "${O}"${J?` (${J})`:``}.`,{template:{ok:!0,path:J}})}async function handleSkillFileEdit(e,t,s,g){let S=resolveSkillName(e.name);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let w=resolveSkillFilePath(e.file);if(!w.ok)return textResult(`Error: ${w.error}`,!0);if(e.description!==void 0)return textResult("Error: `description` edits SKILL.md, not a bundle file. Drop `file`, or edit the file body with find+replace.",!0);if(e.find===void 0||e.replace===void 0)return textResult("Error: a bundle-file edit needs `find` + `replace`: { skill: { name, file, find, replace } }.",!0);if(!t)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let E=e.scope??`project`,D=await readSkillFile(t,E,e.name,w.path);if(!D.ok)return textResult(`Error: skill file "${w.path}" not found in skill "${e.name}" (${E} scope). Create it with \`write({ skill: { name, files: [...] } })\` first.`,!0);let O=e.occurrence??1,k=nthOccurrenceOffset(D.text,e.find,O);if(k===-1)return textResult(`Error: \`find\` occurs fewer than ${O} time(s) in skill file "${w.path}".`,!0);let j=D.text.slice(0,k)+e.replace+D.text.slice(k+e.find.length);return writeSkillFile(t,{name:e.name,scope:E,path:w.path,content:j,summary:s,identity:g})}async function handleSkill(e,t,s,g,S){let w=resolveSkillName(e.name);if(!w.ok)return textResult(`Error: ${w.error}`,!0);if(e.file!==void 0)return handleSkillFileEdit(e,s,t,g.identityRef?.current);let E=e.find!==void 0||e.replace!==void 0,D=e.description!==void 0;if(e.find!==void 0&&e.replace===void 0)return textResult("Error: `find` needs a `replace`. Body edit: { skill: { name, find, replace } }.",!0);if(e.replace!==void 0&&e.find===void 0)return textResult("Error: `replace` needs a `find`. Body edit: { skill: { name, find, replace } }.",!0);if(E&&D)return textResult("Error: Pick ONE: edit the body (find+replace) OR the `description`, not both in one call.",!0);if(!E&&!D)return textResult("Error: Provide either a body edit (find+replace) or a `description` for { skill }.",!0);if(!s)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let O=e.scope??`project`,k=await fetchSkill(s,O,e.name);if(!k.ok)return textResult(`Error: skill "${e.name}" not found in ${O} scope. Create it with \`write({ skill })\` first.`,!0);let j=k.body,F=k.description;if(D)F=e.description;else{let t=e.occurrence??1,s=nthOccurrenceOffset(k.body,e.find,t);if(s===-1)return textResult(`Error: \`find\` occurs fewer than ${t} time(s) in skill "${e.name}".`,!0);j=k.body.slice(0,s)+e.replace+k.body.slice(s+e.find.length)}return writeSkill(s,{scope:O,name:e.name,description:F,body:j,summary:t,identity:g.identityRef?.current,lockDir:S})}async function handleFolder$1(e,t,s,g){if(!s)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let S=await httpPut(s,`/api/folder-config`,{path:e.path,frontmatter:e.frontmatter,...t===void 0?{}:{summary:t},...agentIdentityFields(g.identityRef?.current)});if(!S.ok)return textResult(`Error: ${S.error}`,!0);let w=(Array.isArray(S.applied)?S.applied:[])[0]??{},E=w.action??`written`;return textPlusStructured(`${E===`deleted`?`Cleared`:E===`noop`?`No change to`:`Updated`} folder properties for ${e.path}.`,{folder:{ok:!0,path:w.path??`${e.path}/.ok/frontmatter.yml`,action:E}})}function register$14(e,t){let s={find:string().optional().describe("Exact BODY text to find. Use WITH `replace`. For metadata, use `frontmatter` instead — not this."),replace:string().optional().describe("Replacement for the `find` match."),occurrence:number().int().positive().optional().describe(`Which match to edit (1 = first). Default: first.`)};e.registerTool(`edit`,{description:DESCRIPTION$14,inputSchema:{document:object$1({path:string().describe(`Document path, no extension — the slashes are its folder. Example: "meetings/standup".`),...s,frontmatter:FrontmatterArg.optional().describe("Metadata merge-patch (set keys; `null` deletes a key). Use INSTEAD of find/replace.")}).optional().describe(`Edit a DOCUMENT: its body (find+replace) OR its frontmatter (patch). Body: { document: { path, find, replace } }. Metadata: { document: { path, frontmatter } }.`),folder:object$1({path:string().describe(`Folder path.`),frontmatter:FrontmatterArg.describe("Update the folder's own title/description/tags (merge-patch; `null` deletes).")}).optional().describe(`Edit a FOLDER: only its frontmatter (folders have no body). Example: { folder: { path: "meetings", frontmatter: { description: "All-hands" } } }`),template:object$1({path:string().describe(TEMPLATE_PATH_DESCRIBE),...s,frontmatter:FrontmatterArg.optional().describe(`Template metadata merge-patch.`)}).optional().describe(`Edit a TEMPLATE: body (find+replace) or frontmatter (patch).`),skill:object$1({name:string().describe(SKILL_NAME_DESCRIBE),file:string().optional().describe(SKILL_FILE_DESCRIBE),...s,description:string().optional().describe(SKILL_DESCRIPTION_DESCRIBE),scope:SkillScopeArg.optional()}).optional().describe("Edit a SKILL: SKILL.md body (find+replace) OR its `description`; or pass `file` to find/replace inside ONE `references/**`+`scripts/**` bundle file."),summary:summaryArgSchema,cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({document:object$1(documentResultBaseShape).optional().describe(`Document edit result (present when there is a doc-specific signal).`),folder:object$1({ok:boolean(),path:string(),action:string().describe("`written` (created/updated) | `deleted` (cleared) | `noop`.")}).optional().describe(`Folder frontmatter edit result.`),template:object$1({ok:boolean(),path:string()}).optional().describe(`Template edit result.`),skill:object$1({ok:boolean(),path:string().optional(),created:boolean().optional().describe(`Always false for an edit (the skill already existed).`),file:object$1({path:string(),kind:string().optional(),created:boolean().optional()}).optional().describe(`Present for a bundle-file edit: the file edited.`)}).optional().describe(`Skill edit result (SKILL.md or a bundle file).`),previewUrl:previewUrlOutputField.optional(),previewUrlSource:previewUrlSourceField,warning:previewAttachWarningField})},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,config:S,url:w}=s,E=resolveContentDir(S,g),D=S.appearance.preview.autoOpen,O=exactlyOneTargetError(e,[`document`,`folder`,`template`,`skill`]);if(O)return textResult(`Error: ${O}`,!0);if(e.document!==void 0){let s=bodyOrFrontmatterError(e.document,`document`);return s?textResult(`Error: ${s}`,!0):w?e.document.frontmatter===void 0?handleDocBody(e.document,e,g,E,w,t,D):handleDocFrontmatter({path:e.document.path,frontmatter:e.document.frontmatter},e,g,w,t,D):textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0)}return e.folder===void 0?e.skill===void 0?handleTemplate$1(e.template,e.summary,g,w,t):handleSkill(e.skill,e.summary,w,t,resolveLockDir(g)):handleFolder$1(e.folder,e.summary,w,t)})}const PRODUCER_COMMANDS=new Set([`cat`,`ls`,`grep`,`find`]),PATH_FALLBACK_RE=/\b[\w./-]+\.(md|mdx)\b/g;function isWikiPath(e){return/\.(md|mdx)$/.test(e)}function normalize$1(e){let t=e.trim();return t?(t=t.replace(/\/+/g,`/`),t.startsWith(`./`)&&(t=t.slice(2)),t.endsWith(`/`)&&(t=t.slice(0,-1)),t):``}function argsOf(e){return e.args.slice(1)}function nonFlagArgs(e){return e.filter(e=>!e.startsWith(`-`))}function extractFromCat(e){return nonFlagArgs(argsOf(e)).filter(isWikiPath)}function extractFromLs(e,t){let s=nonFlagArgs(argsOf(t)),g=s.length>0?s[s.length-1]:``,S=g&&g!==`.`?normalize$1(g):``,w=[];S&&w.push(S);for(let t of e.split(`
1954
+ `)}\n${renderInventoryFooter()}`;function bodyOrFrontmatterError(e,t){let s=e.find!==void 0||e.replace!==void 0,g=e.frontmatter!==void 0;return e.find!==void 0&&e.replace===void 0?`\`find\` needs a \`replace\`. Body edit: { ${t}: { …, find, replace } }.`:e.replace!==void 0&&e.find===void 0?`\`replace\` needs a \`find\`. Body edit: { ${t}: { …, find, replace } }.`:s&&g?`Pick ONE: edit body text (find+replace) OR metadata (frontmatter), not both in one call.`:!s&&!g?`Provide either a body edit (find+replace) or a frontmatter patch for { ${t} }.`:null}function readDocFullText(e,t){for(let s of SUPPORTED_DOC_EXTENSIONS){let g=resolveWithinRoot(e,`${t}${s}`);if(g.ok&&existsSync(g.abs))try{return readFileSync(g.abs,`utf-8`)}catch(e){if(e?.code===`ENOENT`)return null;throw e}}return null}function nthOccurrenceOffset(e,t,s){let g=0;for(let S=0;S<s;S++){let w=e.indexOf(t,g);if(w===-1)return-1;if(S===s-1)return w;g=w+Math.max(1,t.length)}return-1}async function handleDocBody(e,t,s,g,S,w,E){let D=normalizeDocName(e.path);if(!D.ok)return textResult(okReservedPathRedirect(e.path)??D.error,!0);let O=w.identityRef?.current,k,j=e.occurrence??1;if(j>1){let t;try{t=readDocFullText(g,D.docName)}catch(e){return textResult(`Error: cannot read "${D.docName}" to resolve occurrence ${j}: ${e instanceof Error?e.message:String(e)}.`,!0)}if(t===null)return textResult(`Error: cannot resolve occurrence ${j} — "${D.docName}" is not on disk yet. Retry with the first match (omit \`occurrence\`).`,!0);let s=nthOccurrenceOffset(t,e.find,j);if(s===-1)return textResult(`Error: \`find\` occurs fewer than ${j} times in "${D.docName}".`,!0);k=s}let F=await httpPost(S,`/api/agent-patch`,{docName:D.docName,find:e.find,replace:e.replace,...k===void 0?{}:{offset:k},...t.summary===void 0?{}:{summary:t.summary},...agentIdentityFields(O)});if(!F.ok){let e=typeof F.detail==`string`&&F.detail.length>0?F.detail:``;return textResult(e?`Error: ${F.error} (${e})`:`Error: ${F.error}`,!0)}return composeWritePreviewResult(F,D.docName,s,g,E,`Edit applied successfully.`)}async function handleDocFrontmatter(e,t,s,g,S,w,E){let D=normalizeDocName(e.path);if(!D.ok)return textResult(okReservedPathRedirect(e.path)??D.error,!0);let O=w.identityRef?.current,k=await httpPost(S,`/api/frontmatter-patch`,{docName:D.docName,patch:e.frontmatter,...t.summary===void 0?{}:{summary:t.summary},...agentIdentityFields(O)});if(!k.ok){let e=k.error,t=k.fieldErrors&&typeof k.fieldErrors==`object`?k.fieldErrors:void 0;return textResult(t?`Error: ${e}\n${Object.entries(t).map(([e,t])=>` ${e}: ${t}`).join(`
1955
+ `)}`:`Error: ${e}`,!0)}let j=[],F=[];for(let[t,s]of Object.entries(e.frontmatter))s===null?F.push(t):j.push(t);let L=[j.length?`${j.length} set`:``,F.length?`${F.length} deleted`:``].filter(Boolean).join(`, `);return composeWritePreviewResult(k,D.docName,s,g,E,`Frontmatter patched (${L||`${Object.keys(e.frontmatter).length} key(s)`}).`)}function composeWritePreviewResult(e,t,s,g,S,w){let E=resolvePreviewUrl(t,{lockDir:resolveLockDir(s)}),D=(typeof e.systemSubscriberCount==`number`?e.systemSubscriberCount:void 0)===0,O=e.summary&&typeof e.summary==`object`?e.summary:void 0,k=typeof O?.hint==`string`?O.hint:void 0,j=parseAdvisoryWarnings(e.warnings),F=parseBrokenLinks(e.brokenLinks),L=[w];D&&!E&&L.push(START_UI_TEXT_HINT),k&&L.push(k),j&&L.push(...formatAdvisoryLines(j)),L.push(...formatBrokenLinkLines(F));let B=L.join(`
1956
+ `),H={brokenLinks:F};return O&&(H.summary=O),j&&(H.warnings=j),textPlusStructured(B,nestDocResult(E,D?buildPreviewAttachWarning(E,S):void 0,H))}function templateFilePath(e,t,s){let g=resolveWithinRoot(e,`${t.replace(/\/+$/,``)}/.ok/templates/${s}.md`);return g.ok?{ok:!0,abs:g.abs}:{ok:!1}}function parseTemplateFrontmatter(e){let t=unwrapFrontmatterFences(e).trim();if(t===``)return{title:``};let s=(0,import_dist$1.parse)(t);if(typeof s!=`object`||!s||Array.isArray(s))return{title:``};let g=s;return{title:typeof g.title==`string`?g.title:``,...typeof g.description==`string`?{description:g.description}:{},...Array.isArray(g.tags)?{tags:g.tags.map(e=>String(e))}:{}}}async function handleTemplate$1(e,t,s,g,S){let w=bodyOrFrontmatterError(e,`template`);if(w)return textResult(`Error: ${w}`,!0);let E=resolveTemplatePath(e.path);if(!E.ok)return textResult(`Error: ${E.error}`,!0);let{folder:D,name:O}=E;if(!g)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let k=templateFilePath(s,D,O);if(!k.ok||!existsSync(k.abs))return textResult(`Error: template "${O}" not found in ${D||`(root)`}. Create it with \`write({ template })\` first.`,!0);let j;try{j=readFileSync(k.abs,`utf-8`)}catch(e){return textResult(`Error: could not read template: ${e.message}`,!0)}let{frontmatter:F,body:L}=stripFrontmatter(j),B=parseTemplateFrontmatter(F);if(e.frontmatter!==void 0){let s=await httpPut(g,`/api/template`,{folder:D,name:O,body:L,frontmatter:mergePatch(B,e.frontmatter),...t===void 0?{}:{summary:t},...agentIdentityFields(S.identityRef?.current)});if(!s.ok)return textResult(`Error: ${s.error}`,!0);let w=typeof s.path==`string`?s.path:void 0;return textPlusStructured(`Patched template "${O}" frontmatter${w?` (${w})`:``}.`,{template:{ok:!0,path:w}})}let H=e.occurrence??1,q=nthOccurrenceOffset(L,e.find,H);if(q===-1)return textResult(`Error: \`find\` occurs fewer than ${H} time(s) in template "${O}".`,!0);let ee=await httpPut(g,`/api/template`,{folder:D,name:O,body:L.slice(0,q)+e.replace+L.slice(q+e.find.length),frontmatter:B,...t===void 0?{}:{summary:t},...agentIdentityFields(S.identityRef?.current)});if(!ee.ok)return textResult(`Error: ${ee.error}`,!0);let J=typeof ee.path==`string`?ee.path:void 0;return textPlusStructured(`Edited template "${O}"${J?` (${J})`:``}.`,{template:{ok:!0,path:J}})}async function handleSkillFileEdit(e,t,s,g){let S=resolveSkillName(e.name);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let w=resolveSkillFilePath(e.file);if(!w.ok)return textResult(`Error: ${w.error}`,!0);if(e.description!==void 0)return textResult("Error: `description` edits SKILL.md, not a bundle file. Drop `file`, or edit the file body with find+replace.",!0);if(e.find===void 0||e.replace===void 0)return textResult("Error: a bundle-file edit needs `find` + `replace`: { skill: { name, file, find, replace } }.",!0);if(!t)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let E=e.scope??`project`,D=await readSkillFile(t,E,e.name,w.path);if(!D.ok)return textResult(`Error: skill file "${w.path}" not found in skill "${e.name}" (${E} scope). Create it with \`write({ skill: { name, files: [...] } })\` first.`,!0);let O=e.occurrence??1,k=nthOccurrenceOffset(D.text,e.find,O);if(k===-1)return textResult(`Error: \`find\` occurs fewer than ${O} time(s) in skill file "${w.path}".`,!0);let j=D.text.slice(0,k)+e.replace+D.text.slice(k+e.find.length);return writeSkillFile(t,{name:e.name,scope:E,path:w.path,content:j,summary:s,identity:g})}async function handleSkill(e,t,s,g,S){let w=resolveSkillName(e.name);if(!w.ok)return textResult(`Error: ${w.error}`,!0);if(e.file!==void 0)return handleSkillFileEdit(e,s,t,g.identityRef?.current);let E=e.find!==void 0||e.replace!==void 0,D=e.description!==void 0;if(e.find!==void 0&&e.replace===void 0)return textResult("Error: `find` needs a `replace`. Body edit: { skill: { name, find, replace } }.",!0);if(e.replace!==void 0&&e.find===void 0)return textResult("Error: `replace` needs a `find`. Body edit: { skill: { name, find, replace } }.",!0);if(E&&D)return textResult("Error: Pick ONE: edit the body (find+replace) OR the `description`, not both in one call.",!0);if(!E&&!D)return textResult("Error: Provide either a body edit (find+replace) or a `description` for { skill }.",!0);if(!s)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let O=e.scope??`project`,k=await fetchSkill(s,O,e.name);if(!k.ok)return textResult(`Error: skill "${e.name}" not found in ${O} scope. Create it with \`write({ skill })\` first.`,!0);let j=k.body,F=k.description;if(D)F=e.description;else{let t=e.occurrence??1,s=nthOccurrenceOffset(k.body,e.find,t);if(s===-1)return textResult(`Error: \`find\` occurs fewer than ${t} time(s) in skill "${e.name}".`,!0);j=k.body.slice(0,s)+e.replace+k.body.slice(s+e.find.length)}return writeSkill(s,{scope:O,name:e.name,description:F,body:j,summary:t,identity:g.identityRef?.current,lockDir:S})}async function handleFolder$1(e,t,s,g){if(!s)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let S=await httpPut(s,`/api/folder-config`,{path:e.path,frontmatter:e.frontmatter,...t===void 0?{}:{summary:t},...agentIdentityFields(g.identityRef?.current)});if(!S.ok)return textResult(`Error: ${S.error}`,!0);let w=(Array.isArray(S.applied)?S.applied:[])[0]??{},E=w.action??`written`;return textPlusStructured(`${E===`deleted`?`Cleared`:E===`noop`?`No change to`:`Updated`} folder properties for ${e.path}.`,{folder:{ok:!0,path:w.path??`${e.path}/.ok/frontmatter.yml`,action:E}})}function register$14(e,t){let s={find:string().optional().describe("Exact BODY text to find. Use WITH `replace`. For metadata, use `frontmatter` instead — not this."),replace:string().optional().describe("Replacement for the `find` match."),occurrence:number().int().positive().optional().describe(`Which match to edit (1 = first). Default: first.`)};e.registerTool(`edit`,{description:DESCRIPTION$14,inputSchema:{document:object$1({path:string().describe(`Document path, no extension — the slashes are its folder. Example: "meetings/standup".`),...s,frontmatter:FrontmatterArg.optional().describe("Metadata merge-patch (set keys; `null` deletes a key). Use INSTEAD of find/replace.")}).optional().describe(`Edit a DOCUMENT: its body (find+replace) OR its frontmatter (patch). Body: { document: { path, find, replace } }. Metadata: { document: { path, frontmatter } }.`),folder:object$1({path:string().describe(`Folder path.`),frontmatter:FrontmatterArg.describe("Update the folder's own title/description/tags (merge-patch; `null` deletes).")}).optional().describe(`Edit a FOLDER: only its frontmatter (folders have no body). Example: { folder: { path: "meetings", frontmatter: { description: "All-hands" } } }`),template:object$1({path:string().describe(TEMPLATE_PATH_DESCRIBE),...s,frontmatter:FrontmatterArg.optional().describe(`Template metadata merge-patch.`)}).optional().describe(`Edit a TEMPLATE: body (find+replace) or frontmatter (patch).`),skill:object$1({name:string().describe(SKILL_NAME_DESCRIBE),file:string().optional().describe(SKILL_FILE_DESCRIBE),...s,description:string().optional().describe(SKILL_DESCRIPTION_DESCRIBE),scope:SkillScopeArg.optional()}).optional().describe("Edit a SKILL: SKILL.md body (find+replace) OR its `description`; or pass `file` to find/replace inside ONE `references/**`+`scripts/**` bundle file."),summary:summaryArgSchema,cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({document:object$1(documentResultBaseShape).optional().describe("Document edit result. Always present on a successful document edit (body or frontmatter) — it carries `brokenLinks` (possibly `[]`) plus any `summary`/`warnings`. Absent only for folder/template edits."),folder:object$1({ok:boolean(),path:string(),action:string().describe("`written` (created/updated) | `deleted` (cleared) | `noop`.")}).optional().describe(`Folder frontmatter edit result.`),template:object$1({ok:boolean(),path:string()}).optional().describe(`Template edit result.`),skill:object$1({ok:boolean(),path:string().optional(),created:boolean().optional().describe(`Always false for an edit (the skill already existed).`),file:object$1({path:string(),kind:string().optional(),created:boolean().optional()}).optional().describe(`Present for a bundle-file edit: the file edited.`)}).optional().describe(`Skill edit result (SKILL.md or a bundle file).`),previewUrl:previewUrlOutputField.optional(),previewUrlSource:previewUrlSourceField,warning:previewAttachWarningField})},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,config:S,url:w}=s,E=resolveContentDir(S,g),D=S.appearance.preview.autoOpen,O=exactlyOneTargetError(e,[`document`,`folder`,`template`,`skill`]);if(O)return textResult(`Error: ${O}`,!0);if(e.document!==void 0){let s=bodyOrFrontmatterError(e.document,`document`);return s?textResult(`Error: ${s}`,!0):w?e.document.frontmatter===void 0?handleDocBody(e.document,e,g,E,w,t,D):handleDocFrontmatter({path:e.document.path,frontmatter:e.document.frontmatter},e,g,E,w,t,D):textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0)}return e.folder===void 0?e.skill===void 0?handleTemplate$1(e.template,e.summary,g,w,t):handleSkill(e.skill,e.summary,w,t,resolveLockDir(g)):handleFolder$1(e.folder,e.summary,w,t)})}const PRODUCER_COMMANDS=new Set([`cat`,`ls`,`grep`,`find`]),PATH_FALLBACK_RE=/\b[\w./-]+\.(md|mdx)\b/g;function isWikiPath(e){return/\.(md|mdx)$/.test(e)}function normalize$1(e){let t=e.trim();return t?(t=t.replace(/\/+/g,`/`),t.startsWith(`./`)&&(t=t.slice(2)),t.endsWith(`/`)&&(t=t.slice(0,-1)),t):``}function argsOf(e){return e.args.slice(1)}function nonFlagArgs(e){return e.filter(e=>!e.startsWith(`-`))}function extractFromCat(e){return nonFlagArgs(argsOf(e)).filter(isWikiPath)}function extractFromLs(e,t){let s=nonFlagArgs(argsOf(t)),g=s.length>0?s[s.length-1]:``,S=g&&g!==`.`?normalize$1(g):``,w=[];S&&w.push(S);for(let t of e.split(`
1953
1957
  `)){let e=t.trim();if(!e||/\.[a-z0-9]+$/i.test(e)&&!isWikiPath(e))continue;let s=S?`${S}/${e}`:e;w.push(s)}return w}function extractFromGrep(e){let t=[];for(let s of e.split(`
1954
1958
  `)){if(!s)continue;let e=s.indexOf(`:`);if(e<0)continue;let g=normalize$1(s.slice(0,e));isWikiPath(g)&&t.push(g)}return t}function extractFromFind(e){let t=[];for(let s of e.split(`
1955
1959
  `)){let e=normalize$1(s);e&&isWikiPath(e)&&t.push(e)}return t}function extractFromHeadTail(e){return nonFlagArgs(argsOf(e)).filter(isWikiPath)}function headTailActsAsProducer(e){return nonFlagArgs(argsOf(e)).length>0}function fallback(e){let t=[],s=e.matchAll(PATH_FALLBACK_RE);for(let e of s)t.push(normalize$1(e[0]));return t}function extractReferencedPaths(e,t){let s=null;for(let e=t.length-1;e>=0;e--){let g=t[e];if(PRODUCER_COMMANDS.has(g.command)){s=g;break}if((g.command===`head`||g.command===`tail`)&&headTailActsAsProducer(g)){s=g;break}}let g;if(!s)g=fallback(e);else{switch(s.command){case`cat`:g=extractFromCat(s);break;case`ls`:g=extractFromLs(e,s);break;case`grep`:g=extractFromGrep(e);break;case`find`:g=extractFromFind(e);break;case`head`:case`tail`:g=extractFromHeadTail(s);break;default:g=fallback(e)}g.length===0&&(g=fallback(e))}let S=new Set,w=[];for(let e of g){let t=normalize$1(e);!t||S.has(t)||(S.add(t),w.push(t))}return w}function shellEscape(e){return e===``?`''`:/^[\w.\-/]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}const MAX_STDOUT_BYTES=16*1024*1024;var StdoutOverflowError=class extends Error{limitBytes;actualBytes;partial;constructor(e,t,s){super(`Output exceeded ${e} byte buffer (got ${t}); narrow the command`),this.name=`StdoutOverflowError`,this.limitBytes=e,this.actualBytes=t,this.partial=s}};function createBashInstance(e){if(!isAbsolute(e))throw Error(`createBashInstance: cwd must be absolute (got: ${e})`);return new xt({cwd:`/`,fs:new Ss({root:resolve(e),allowSymlinks:!1})})}async function execBash(e,t){let s=await e.exec(t);if(s.stdout.length>MAX_STDOUT_BYTES)throw new StdoutOverflowError(MAX_STDOUT_BYTES,s.stdout.length,{stdout:s.stdout.slice(0,MAX_STDOUT_BYTES),stderr:s.stderr,exitCode:s.exitCode});return{stdout:s.stdout,stderr:s.stderr,exitCode:s.exitCode}}const SCAN_CAP=1e3,SKIP_DIRS=new Set([`.git`,`.ok`,`node_modules`,`.changeset`,`.claude`,`.agents`,`dist`,`build`]);async function snapshotMtimes(e){let t=resolve(e),s=new Map,g=0,S=!1;async function w(e){if(S)return;let E;try{E=await readdir(e,{withFileTypes:!0})}catch{return}for(let D of E){if(S)return;if(D.isDirectory()&&SKIP_DIRS.has(D.name))continue;let E=resolve(e,D.name);if(D.isDirectory()){await w(E);continue}if(D.isFile()){if(g>=SCAN_CAP){S=!0;return}try{let e=await stat$1(E);s.set(relative(t,E),e.mtimeMs),g++}catch{}}}}return await w(t),{snapshot:s,truncated:S}}function diffMtimes(e,t){let s=[];for(let[g,S]of t){let t=e.get(g);(t===void 0||t!==S)&&s.push(g)}for(let[g]of e)t.has(g)||s.push(g);return{changed:s}}const WIKI_EXCLUDE_DIRS=[`node_modules`,`.git`,`dist`,`build`,`.next`,`.turbo`,`.nuxt`,`coverage`,`.cache`,`.parcel-cache`,`.vercel`,`.ok`,`.claude`];function isRecursiveGrepFlag(e){return e===`--recursive`||e===`--dereference-recursive`?!0:e.startsWith(`--`)||!e.startsWith(`-`)?!1:/[rR]/.test(e.slice(1))}const STRATEGIES=[{command:`grep`,applies:e=>e.slice(1).some(isRecursiveGrepFlag),hasUserExcludes:e=>e.some(e=>e===`--exclude-dir`||e.startsWith(`--exclude-dir=`)),buildExcludeArgs:e=>e.map(e=>`--exclude-dir=${e}`),insertionIndex:()=>1},{command:`find`,applies:()=>!0,hasUserExcludes:e=>e.slice(1).some(e=>e===`-not`||e===`!`||e===`-prune`),buildExcludeArgs:e=>{let t=[];for(let s of e)t.push(`-not`,`-path`,`*/${s}/*`);return t},insertionIndex:e=>{for(let t=1;t<e.length;t++)if(e[t].startsWith(`-`))return t;return e.length}}];function augmentStagesWithExcludes(e){return e.map(e=>{let t=STRATEGIES.find(t=>t.command===e.command);if(!t||!t.applies(e.args)||t.hasUserExcludes(e.args))return e;let s=t.buildExcludeArgs(WIKI_EXCLUDE_DIRS),g=t.insertionIndex(e.args);return{command:e.command,args:[...e.args.slice(0,g),...s,...e.args.slice(g)]}})}function serializeStages(e){return e.map(e=>e.args.map(shellEscape).join(` `)).join(` | `)}const ALLOWLIST=new Set([`cat`,`ls`,`grep`,`find`,`head`,`tail`,`wc`,`sort`,`uniq`,`cut`]),ALLOWLIST_HINT=`cat, ls, grep, find, head, tail, wc, sort, uniq, cut`,WRITE_OPS=new Set([`>`,`>>`,`<`,`>&`,`<&`,`|&`]),SHELL_CONSTRUCT_OPS=new Set([`&`,`;`,`;;`,`&&`,`||`,`(`,`)`,`<(`,`>(`,`<<`,`<<-`]),UNIVERSAL_FLAG_DENY=new Set([`-o`,`--output-file`,`--output`]),UNIVERSAL_FLAG_PREFIX_DENY=[`-o=`,`--output-file=`,`--output=`],FIND_FLAG_DENY=new Set([`-exec`,`-execdir`,`-delete`,`-fprint`,`-fprintf`,`-fprint0`,`-ok`,`-okdir`]),SUSPICIOUS_STRING_RE=/[`]|\$\(|\$\{|\$'/;function isOpToken(e){return typeof e==`object`&&!!e&&`op`in e}function opTokenError(e){let t=typeof e.op==`string`?e.op:`(unknown)`;return WRITE_OPS.has(t)?{category:`write_blocked`,message:`Write operation blocked: '${t}'. exec is read-only. For document changes, use the \`write\` or \`edit\` tool.`}:SHELL_CONSTRUCT_OPS.has(t)?{category:`shell_construct_blocked`,message:`Shell construct '${t}' is not supported — exec runs ONE command or a pipe (|), not a shell. Run separate exec calls, or pass multiple paths to one command (e.g. \`ls -A a b c\`, \`cat a b c\`).`}:{category:`shell_construct_blocked`,message:`Operator '${t}' is not supported.`}}function buildStageArgs(e){let t=[];for(let s of e){if(typeof s==`string`){if(SUSPICIOUS_STRING_RE.test(s))return{error:{category:`shell_construct_blocked`,message:`Argument '${s}' contains a shell-injection pattern (backtick, $(), or \${}); not supported.`}};t.push(s);continue}if(!isOpToken(s))return{error:{category:`shell_construct_blocked`,message:`Unrecognized token shape.`}};if(s.op===`glob`&&typeof s.pattern==`string`){t.push(s.pattern);continue}return typeof s.comment==`string`?{error:{category:`shell_construct_blocked`,message:`Comments are not allowed in exec commands.`}}:{error:opTokenError(s)}}return{args:t}}function checkStage(e){if(!ALLOWLIST.has(e.command))return{category:`unknown_command`,message:`Command '${e.command}' is not in the allowlist. For pattern matching try 'grep'; for file listing try 'ls' or 'find'. Allowlist: ${ALLOWLIST_HINT}.`};for(let t of e.args.slice(1)){if(UNIVERSAL_FLAG_DENY.has(t)||UNIVERSAL_FLAG_PREFIX_DENY.some(e=>t.startsWith(e)))return{category:`write_blocked`,message:`Write operation blocked: '${t}'. exec is read-only. For document changes, use the \`write\` or \`edit\` tool.`};if(e.command===`find`&&FIND_FLAG_DENY.has(t))return{category:`write_blocked`,message:`find flag '${t}' is blocked (executes commands or deletes files). Use exec for read-only discovery; chain with another allowlisted tool via '|' if you need to transform output.`}}return null}function parseCommand(e){let t=e.trim();if(!t)return{error:{category:`unknown_command`,message:`Empty command.`}};let s;try{s=import_shell_quote.parse(t)}catch{return{error:{category:`shell_construct_blocked`,message:`Failed to parse command — likely malformed quoting or an unsupported construct.`}}}let g=[],S=[];for(let e of s){if(isOpToken(e)&&e.op===`|`){g.push(S),S=[];continue}S.push(e)}g.push(S);let w=[];for(let e of g){let t=buildStageArgs(e);if(`error`in t)return t;if(t.args.length===0)return{error:{category:`shell_construct_blocked`,message:`Empty pipeline stage (trailing pipe or leading pipe).`}};let s={command:t.args[0],args:t.args},g=checkStage(s);if(g)return{error:g};w.push(s)}return{stages:w}}const SOFT_CAP_LINES=500,SOFT_CAP_BYTES=32768-8*1024,BINARY_EXT_RE=/\.(png|jpe?g|gif|webp|svg|pdf|zip|tar|gz|tgz|mp4|mov|mp3|wav|ico|bmp)$/i,DESCRIPTION$13=["**STOP — when the project has `.ok/`, do NOT use native `Read`/`Grep`/`Glob` on in-scope `.md`/`.mdx`; use `exec` (this tool).** Native tools skip the frontmatter, backlinks, shadow-repo activity, and git history `exec` returns per wiki file. Reserve native tools for source code, non-markdown, and projects without `.ok/`. (Full rule + escape hatch: the `open-knowledge` skill.)",``,`Run a read-only bash-like command against the project content directory. Returns raw stdout plus enriched metadata for every wiki file referenced (frontmatter, backlink/forward-link counts, shadow-repo activity with agent/human attribution).`,``,"Allowlist: cat, ls, grep, find, head, tail, wc, sort, uniq, cut. One command or a pipe (|) per call — NOT a shell: `&&`, `;`, redirections, subshells, and writes are rejected. To do several things, make separate exec calls or pass multiple paths to one command (e.g. `ls -A a b c`, `cat a b c`).",``,"cwd: the command runs in the explicit absolute `cwd` you pass, or in the MCP client's only advertised root when there is exactly one. If the client has zero or multiple roots, pass `cwd` explicitly. Paths inside the command resolve relative to that cwd; traversal above it is rejected.",``,"Stdout provenance headers (GNU-style): `ls <dir>/` prepends `<dir>/:`, single-file `cat`/`head`/`tail` prepends `==> <path> <==`, so the subject of the command is visible in raw output. Multi-file `cat a b` emits no header — the `enrichedPaths` array still lists every file. `head`/`tail` used as pipe trimmers (no file arg) defer to the upstream producer.",``,`Examples:`,'- `exec({ command: "cat articles/auth.md" })` — file contents + full enrichment','- `exec({ command: "ls articles/" })` — listing + per-file enrichment (slim)','- `exec({ command: "grep -rn oauth articles/ | head -5" })` — pipe with enrichment on matched files','- `exec({ command: "ls", cwd: "/abs/path/to/other-repo" })` — run in a different project'].join(`
@@ -1990,8 +1994,8 @@ $$`,guidance:"Write LaTeX in `$…$` (inline) or `$$…$$` (block) — OK auto-p
1990
1994
  `),{document:E,version:e.version,previewUrl:J?.url??null,...J?{previewUrlSource:J.source}:{},...j?{summary:j}:{},...L?{warnings:L}:{}})})}const DESCRIPTION$4=["[Requires: Hocuspocus server] Ranked retrieval across ALL non-ignored files (markdown by title/body, other file types by name/path, plus folders) — pair with `exec` `grep` for exhaustive content search. The cmd-K engine (title boost + body BM25 + recency).",``,"NAMES/paths are indexed for all files; BODY content for markdown only. Two-tier agent model: run this fast indexed `search` (all files by name/path + markdown content) IN PARALLEL with `exec` (`grep`) for exhaustive literal-string content search across every file — instant ranked hits plus full content coverage. Reach for `exec` grep when you need to match content inside code/config/data files.",``,"When semantic search is enabled for the workspace (an opt-in setting with an API key), an embeddings signal is additionally fused into `full_text` ranking, surfacing conceptually-related pages that share no keywords. This tool opts in by default; the `semantic` block in the response reports coverage. Note: with semantic enabled, the query and matching page content are sent to the configured embeddings provider (content egress). Set `semantic: false` to force pure-lexical ranking for a call.",``,"Returns scored `page`, `folder`, and name-only `file` hits, each with a `signals` breakdown (lexical / fullText / recency / vector); markdown `page` hits also carry a body snippet (`file` hits never do — name-only). `exec`-grep covers every content occurrence and needs no server.",``,'Cold start: right after the server boots, the response may carry `ready: false` with an empty `results` while the index is still building. That empty set is NOT authoritative — wait ~2-3 seconds, then retry (agents have no built-in delay, so do not retry in immediate succession). If it is still `ready: false` after 2-3 retries (e.g. a very large workspace), fall back to `exec("grep ...")` rather than polling further. Once `ready` is true/omitted the results are complete.',``,`**Parameters:**`,"- `query` — Free-form; tokenized across title, name, path segments, and (with `full_text`) body.","- `intent` (optional) — `omnibar` searches title/path/folders only (fast); `full_text` includes body. Default `full_text`.","- `scopes` (optional) — Result scope: `page` | `folder` | `file` | `content`. Defaults derive from `intent`.","- `limit` (optional) — Max rows; default 20, max 100.","- `semantic` (optional) — Set `false` to force pure-lexical ranking even when semantic search is enabled. Omit to use semantic when available.",``,'If the server is down, the tool returns a recovery hint — use `exec("grep ...")` as the server-free fallback.'].join(`
1991
1995
  `),InputSchema={query:string().describe(`Search query — title, path, or body terms.`),intent:_enum([`omnibar`,`full_text`]).optional().describe(`'omnibar' for title/path/folder only (fast); 'full_text' includes body content. Default 'full_text'.`),scopes:array(_enum([`page`,`folder`,`content`,`file`])).optional().describe(`Override the default scope set. Members: 'page', 'folder', 'file', 'content'. Defaults derive from intent.`),limit:number().int().min(1).max(100).optional().describe(`Max rows; default 20, max 100.`),semantic:boolean().optional().describe(`Set false to force pure-lexical ranking for this call even when semantic search is enabled. Omit to use semantic when available.`),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},SearchResultRowSchema=object$1({kind:_enum([`page`,`folder`,`file`]),path:string(),docName:string(),title:string().nullable(),score:number(),signals:object$1({lexical:number(),fullText:number(),recency:number(),vector:number().optional()}),snippet:string().optional(),previewUrl:string().nullable(),previewUrlSource:_enum(PREVIEW_URL_SOURCES).optional()}),SearchSemanticStatusSchema=object$1({capable:boolean(),applied:boolean(),coverage:object$1({embedded:number().int(),total:number().int()})}),OutputSchema$1=outputSchemaWithText({cwd:string(),query:string(),intent:string(),resultCount:number().int(),results:array(SearchResultRowSchema),elapsedMs:number().nullable(),semantic:SearchSemanticStatusSchema.optional(),ready:literal(!1).optional()});function isSearchKind(e){return e===`page`||e===`folder`||e===`file`}function normalizeSignals(e){return{lexical:typeof e?.lexical==`number`?e.lexical:0,fullText:typeof e?.fullText==`number`?e.fullText:0,recency:typeof e?.recency==`number`?e.recency:0,...typeof e?.vector==`number`?{vector:e.vector}:{}}}function normalizeSemanticStatus(e){if(!(!e||typeof e.capable!=`boolean`))return{capable:e.capable,applied:e.applied===!0,coverage:{embedded:typeof e.coverage?.embedded==`number`?e.coverage.embedded:0,total:typeof e.coverage?.total==`number`?e.coverage.total:0}}}function formatSemanticNote(e){if(!e)return``;if(!e.capable)return`> Semantic: enabled but not ready (no API key, or warming up) — lexical ranking only.`;let{embedded:t,total:s}=e.coverage;return e.applied?`> Semantic: on — vector signal contributed (${t}/${s} pages embedded).`:t<s?`> Semantic: on — indexing ${t}/${s} pages; vectors are still filling in, re-run for fuller coverage.`:`> Semantic: on — no page cleared the similarity threshold for this query.`}function formatResultsBlock(e){if(e.length===0)return``;let t=[];for(let s of e){let e=s.title?.trim()||s.path;t.push(`### ${e} (${s.path})`),t.push(`Score ${s.score.toFixed(2)} — kind: ${s.kind}`),s.snippet&&t.push(s.snippet),t.push(``)}return t.join(`
1992
1996
  `)}function register$4(e,t){e.registerTool(`search`,{description:DESCRIPTION$4,inputSchema:InputSchema,outputSchema:OutputSchema$1,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0}},async e=>{try{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,config:S,url:w}=s;if(!w)return textResult(`${HOCUSPOCUS_NOT_RUNNING_ERROR}\nFor server-free literal-string search, use \`exec("grep ...")\` instead — it walks the filesystem and does not need Hocuspocus.`,!0);let E=e.intent??`full_text`,D=e.limit??20,O={query:e.query,intent:E,limit:D,semantic:e.semantic??!0,source:`mcp`};e.scopes&&(O.scopes=e.scopes);let k=await httpPost(w,`/api/search`,O);if(!k.ok)return textResult(`Error: ${k.error}`,!0);let{resolve:j}=await buildListResolver({config:S,resolveCwd:async()=>g},g),F=(k.results??[]).flatMap(e=>{if(!isSearchKind(e.kind)||typeof e.path!=`string`)return[];let t=docNameFromPath(e.path),s=j(t);return[{kind:e.kind,path:e.path,docName:t,title:e.title??null,score:typeof e.score==`number`?e.score:0,signals:normalizeSignals(e.signals),...e.snippet?{snippet:e.snippet}:{},previewUrl:s?.url??null,...s?{previewUrlSource:s.source}:{}}]}),L=normalizeSemanticStatus(k.semantic),B=k.ready!==!1,H={cwd:g,query:e.query,intent:E,resultCount:F.length,results:F,elapsedMs:typeof k.elapsedMs==`number`?k.elapsedMs:null,...L?{semantic:L}:{},...B?{}:{ready:!1}},q=`## Search results for "${e.query}" (${F.length} hit${F.length===1?``:`s`}, intent: ${E})`,ee=formatSemanticNote(L),J=B?F.length===0?`No matches for "${e.query}".`:`${q}\n\n${formatResultsBlock(F)}`:`The workspace search index is still warming — results for "${e.query}" are not ready yet. Wait ~2-3 seconds, then retry; if it is still warming after 2-3 retries, use \`exec("grep ...")\` for an index-free search instead.`;return textPlusStructured(ee?`${J}\n${ee}`:J,H)}catch(e){return textResult(`Error: ${e instanceof Error?e.message:String(e)}`,!0)}})}const DESCRIPTION$3=["[Requires: Hocuspocus server] Build a shareable GitHub-substrate URL (`https://openknowledge.ai/d/...`) pinned to the project's current branch + the focused target (a doc or a folder). Read-only against the working tree — no commits, no pushes, no `git fetch`.",``,`Use this when the user asks for a share link / shareable link / URL to send to a teammate. Recipients open the link to receive the doc (or folder subtree) into their own OpenKnowledge install.`,``,"**Publishing is a user act.** Agents do NOT publish projects to GitHub from this tool. When the project has no GitHub remote, this tool returns an error pointing the user at the Share wizard (or `gh repo create` + `git push`) — it does not run those steps itself.",``,`**Parameters:**`,'- `path` — Content-dir-relative target. For a doc, extension-less (trailing `.md`/`.mdx` is stripped; the on-disk file is probed automatically). For a folder, the directory path. The empty string `""` is the content-root sentinel (folder-only).',"- `kind` (optional) — `'doc'` or `'folder'`. Omit to auto-probe disk (`.mdx` → `.md` → directory, first hit wins). REQUIRED when `path` is empty (`\"\"`), since auto-probe cannot disambiguate the root.","- `cwd` (optional) — Project root (see `cwd` description below).",``,"**Preconditions:** project on a named branch (not detached HEAD); origin set to a `github.com` remote; the branch already pushed to origin."].join(`
1993
- `);function messageForShareError(e,t){switch(e){case`no-remote`:return"This project has no GitHub remote. Ask the user to push it to GitHub first (e.g. `gh repo create` then `git push -u origin <branch>`), or use the Share button in the editor to run the Publish wizard. Agents do not publish projects from this tool.";case`detached-head`:return"HEAD is detached (no branch checked out). Ask the user to check out a branch (`git checkout <branch>`) before sharing.";case`branch-not-on-origin`:{let e=" (If the user says it is already pushed, ask them to `git fetch origin` first to refresh the local mirror, then retry.)";return t?`Branch \`${t}\` is not on origin yet. Ask the user to push it (\`git push -u origin ${t}\`), then retry.${e}`:`The current branch is not on origin yet. Ask the user to push it (\`git push -u origin <branch>\`), then retry.${e}`}case`non-github-remote`:return"Origin is not a `github.com` remote. Share links are GitHub-only in v1.";case`invalid-path`:return"The resolved share path is not shareable (escapes the project root or names the `.git` subtree). Pass a normal target path under the content directory.";default:return`Unknown share-construct-url error: ${String(e)}`}}function isExistingDirectory(e){try{return statSync(e).isDirectory()}catch{return!1}}function resolveExistingDocPath(e,t){for(let s of SUPPORTED_DOC_EXTENSIONS){let g=`${t}${s}`;if(existsSync(g)){let t=resolveWithinRoot(e,g);return t.ok?t.rel:null}}return null}function resolveShareTarget(e,t,s,g){if(s===``)return g===`folder`?{ok:!0,kind:`folder`,sharePath:``}:{ok:!1,code:`invalid-path`};let S=resolveWithinRoot(t,s);if(!S.ok)return{ok:!1,code:`target-not-found`};let w=resolveExistingDocPath(e,S.abs.replace(/\.(mdx|md)$/i,``)),E=isExistingDirectory(S.abs);if(g===`doc`)return w===null?E?{ok:!1,code:`kind-mismatch`}:{ok:!1,code:`target-not-found`}:{ok:!0,kind:`doc`,sharePath:w};if(g===`folder`){if(E){let t=resolveWithinRoot(e,S.abs);return t.ok?{ok:!0,kind:`folder`,sharePath:t.rel}:{ok:!1,code:`target-not-found`}}return w===null?{ok:!1,code:`target-not-found`}:{ok:!1,code:`kind-mismatch`}}if(w!==null)return{ok:!0,kind:`doc`,sharePath:w};if(E){let t=resolveWithinRoot(e,S.abs);return t.ok?{ok:!0,kind:`folder`,sharePath:t.rel}:{ok:!1,code:`target-not-found`}}return{ok:!1,code:`target-not-found`}}const OutputSchema=outputSchemaWithText({ok:boolean().describe(`Success discriminator.`),shareUrl:string().optional().describe(`Marketing share URL (success only).`),sharedUrl:string().optional().describe(`Unencoded GitHub blob/tree URL (success only).`),branch:string().optional().describe(`Branch the share URL pins to (success only).`),resolvedKind:_enum([`doc`,`folder`]).optional().describe(`Kind the target resolved to (success only).`),error:_enum([`no-remote`,`detached-head`,`branch-not-on-origin`,`non-github-remote`,`invalid-path`,`target-not-found`,`kind-mismatch`,`unknown`]).optional().describe(`Failure code (error path only).`),message:string().optional().describe(`Agent-actionable error message (error path only).`),previewUrl:string().nullable().optional().describe("Route-only preview URL (no host:port): `/#/<doc>` for a doc, `/#/<folder>/` for a folder, `/#/` for the content root. `null` when no UI is running."),previewUrlSource:string().optional().describe(`Internal: preview-URL provenance.`)});function register$3(e,t){e.registerTool(`share_link`,{description:DESCRIPTION$3,inputSchema:{path:string().describe('Content-dir-relative target. Doc paths are extension-less (`.md`/`.mdx` stripped). Folder paths name a directory. `""` is the content-root sentinel (folder-only).'),kind:_enum([`doc`,`folder`]).optional().describe("Target kind. Omit to auto-probe disk (`.mdx` → `.md` → directory). REQUIRED when `path` is empty."),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:OutputSchema,annotations:{readOnlyHint:!0,idempotentHint:!0}},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,config:S,url:w}=s;if(!w)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let E=resolveShareTarget(g,join(g,S.content.dir),e.path,e.kind);if(!E.ok){let t;if(E.code===`kind-mismatch`){let s=e.kind===`folder`?`folder`:`doc`;t=`\`${e.path}\` exists, but not as a ${s}. Pass \`kind: '${s===`doc`?`folder`:`doc`}'\` to share it as the other kind.`}else t=E.code===`invalid-path`?'Cannot share the content root from an empty path without `kind: "folder"`. Pass a non-empty path, or `kind: "folder"` to share the root.':`Target \`${e.path}\` does not exist under the content directory (looked for \`.md\`, \`.mdx\`, and a directory).`;let s={ok:!1,error:E.code,message:t};return textPlusStructured(`Error: ${t}`,s,!0)}let D=E.kind===`doc`?{kind:`doc`,docPath:E.sharePath}:{kind:`folder`,folderPath:E.sharePath},O;try{O=await fetch(`${w}/api/share/construct-url`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(D),signal:AbortSignal.timeout(3e4)})}catch(e){let t=`Server unreachable: ${e instanceof Error?e.message:String(e)}`;return textPlusStructured(`Error: ${t}`,{ok:!1,error:`unknown`,message:t},!0)}let k;try{k=await O.json()}catch(e){let t=`Server returned non-JSON body: ${e instanceof Error?e.message:String(e)}`;return textPlusStructured(`Error: ${t}`,{ok:!1,error:`unknown`,message:t},!0)}if(!O.ok){let e;if(k&&typeof k==`object`){let t=k,s=typeof t.title==`string`?t.title:void 0,g=typeof t.detail==`string`?t.detail:void 0;e=s&&g?`${s}: ${g}`:s||g||`HTTP ${O.status}`}else e=`HTTP ${O.status}`;return textPlusStructured(`Error: ${e}`,{ok:!1,error:`unknown`,message:e},!0)}let j=ShareConstructUrlResponseSchema.safeParse(k);if(!j.success){let e=`Server returned an unexpected share-construct-url response shape.`;return textPlusStructured(`Error: ${e}`,{ok:!1,error:`unknown`,message:e},!0)}let F=j.data;if(!F.ok){let e=messageForShareError(F.error,F.branch),t={ok:!1,error:F.error,message:e,...F.branch?{branch:F.branch}:{}};return textPlusStructured(`Error: ${e}`,t,!0)}let{shareUrl:L,sharedUrl:B,branch:H}=F,q={ok:!0,shareUrl:L,sharedUrl:B,branch:H,resolvedKind:E.kind},ee={config:t.config,resolveCwd:t.resolveCwd},J=await resolvePreviewUrlForTool(E.sharePath.replace(/\.(mdx|md)$/i,``),ee,g);if(J&&E.kind===`folder`){let e=E.sharePath.replace(/^\/+|\/+$/g,``),t=e===``?`/#/`:`/#/${encodeDocName(e)}/`;J={...J,url:t}}let Y=e.path===``?`(content root)`:e.path;return textPlusStructured(`Share link for ${E.kind} \`${Y}\` on branch \`${H}\`:\n${L}`,{...q,previewUrl:J?.url??null,...J?{previewUrlSource:J.source}:{}})})}function bundleFileKind(e){return e.replace(/\\/g,`/`).startsWith(`scripts/`)?`script`:`reference`}const SCOPE_FIELD_DESCRIBE="Which level the skill lives at. `project` = this KB's `.ok/skills/` (shared via git with everyone on the project); `global` = your user-level `~/.ok/skills/` (available in every project on this machine, not shared).",SkillListEntryOutputSchema=object$1({name:string().describe("Skill name (its identity; pass to `edit`/`move`/`delete`/`install`)."),scope:_enum([`project`,`global`]).describe(SCOPE_FIELD_DESCRIBE),description:string().optional().describe(`The skill's one-line description (when present).`),installed:boolean().describe(`True when projected into ≥1 editor; false = a Draft.`),hosts:array(string()).describe(`Editor ids the skill is installed into.`),updateAvailable:boolean().optional().describe(`Starter-pack skills only: a newer bundled version is available.`)}),SkillBundleFileEntrySchema=object$1({path:string().describe(`Skill-relative path (e.g. "references/tiers.md").`),kind:_enum([`reference`,`script`]).describe("`reference` (under references/) or `script` (under scripts/).")}),SkillReadOutputSchema=object$1({name:string().describe(`Skill name (its identity).`),scope:_enum([`project`,`global`]).describe(SCOPE_FIELD_DESCRIBE),description:string().describe(`The skill's one-line description (empty if none).`),body:string().describe(`The SKILL.md body (markdown, frontmatter stripped).`),files:array(SkillBundleFileEntrySchema).describe("Bundle files beside SKILL.md (path + kind, no inline text). Read one via `file`.")}),SkillFileReadOutputSchema=object$1({path:string().describe(`Skill-relative path read.`),kind:_enum([`reference`,`script`]).describe("`reference` or `script`."),text:string().describe(`Full text of the bundle file.`)}),DESCRIPTION$2=["[Requires: Hocuspocus server] Read-only discovery for SKILLS — the read half of the skill vocabulary (`write`/`edit`/`delete`/`move`/`install` are the mutate half).",``,"This is how you find and read skills. Skills are addressed by `name` + `scope`, NOT by path — do NOT `ls`/`cat` `.ok/skills/` or pass raw `.ok/...` paths; `.ok/` is opaque internal state.",``,`**Three modes:**`,"- **List** (omit `name`): every skill across BOTH levels — Project (this KB) and Global (user-level). Returns name, scope, description, installed/hosts, and (for starter packs) `updateAvailable`.","- **Read skill** (pass `name`): that skill's description + body + a `files` list (`{ path, kind }`, no inline text) of its `references/**`+`scripts/**` bundle files. `scope` optional — omitted, it resolves by name (preferring Project when a name exists at both levels).","- **Read file** (pass `name` + `file`): one bundle file's text — the universal read path for references + scripts (no native `cat`)."].join(`
1994
- `);function register$2(e,t){e.registerTool(`skills`,{description:DESCRIPTION$2,inputSchema:{name:string().optional().describe(`Omit to LIST all skills; pass a skill name to READ that skill.`),file:string().optional().describe("With `name`: read ONE bundle file by its skill-relative path (`references/...`/`scripts/...`)."),scope:SkillScopeArg.optional(),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({skills:array(SkillListEntryOutputSchema).optional().describe(`Present in LIST mode: every skill across Project + Global levels.`),skill:SkillReadOutputSchema.optional().describe(`Present in READ-skill mode: the named skill (description, body, files list).`),file:SkillFileReadOutputSchema.optional().describe(`Present in READ-file mode: one bundle file (path, kind, text).`)})},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{url:g}=s;if(!g)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);if(e.file!==void 0&&e.name===void 0)return textResult('Error: `file` reads ONE bundle file of a skill — pass `name` too: skills({ name, file: "references/x.md" }).',!0);if(e.file!==void 0){let t=resolveSkillFilePath(e.file);if(!t.ok)return textResult(`Error: ${t.error}`,!0)}if(e.name===void 0){let e=await httpGet(g,`/api/skills`);if(!e.ok)return textResult(`Error: ${e.error}`,!0);let{ok:t,...s}=e,S=(Array.isArray(s.skills)?s.skills:[]).map(e=>({name:e.name,scope:e.scope,...typeof e.description==`string`?{description:e.description}:{},installed:e.installed===!0,hosts:Array.isArray(e.hosts)?e.hosts:[],...typeof e.updateAvailable==`boolean`?{updateAvailable:e.updateAvailable}:{}}));return textPlusStructured(JSON.stringify({skills:S},null,2),{skills:S})}let S=e.scope;if(S===void 0){let t=await httpGet(g,`/api/skills`);if(!t.ok)return textResult(`Error: ${t.error}`,!0);let{ok:s,...w}=t,E=(Array.isArray(w.skills)?w.skills:[]).filter(t=>t.name===e.name);if(E.length===0)return textResult(`Error: no skill named "${e.name}" (Project or Global).`,!0);S=E.find(e=>e.scope===`project`)===void 0?E[0]?.scope:`project`}if(e.file!==void 0){let t=await readSkillFile(g,S,e.name,e.file);if(!t.ok)return textResult(`Error: ${t.error}`,!0);let s={path:t.path,kind:t.kind,text:t.text};return textPlusStructured(JSON.stringify({file:s},null,2),{file:s})}let w=await fetchSkill(g,S,e.name);if(!w.ok)return textResult(`Error: ${w.error}`,!0);let E={name:e.name,scope:S,description:w.description,body:w.body,files:w.files.map(e=>({path:e.path,kind:bundleFileKind(e.path)}))};return textPlusStructured(JSON.stringify({skill:E},null,2),{skill:E})})}function buildConsolidateBody(e,t){return`Promote existing research on this topic into a canonical article inside the project content directory. **Canonical, not provisional** — the output is the source of truth for future agents.
1997
+ `);function messageForShareError(e,t){switch(e){case`no-remote`:return"This project has no GitHub remote. Ask the user to push it to GitHub first (e.g. `gh repo create` then `git push -u origin <branch>`), or use the Share button in the editor to run the Publish wizard. Agents do not publish projects from this tool.";case`detached-head`:return"HEAD is detached (no branch checked out). Ask the user to check out a branch (`git checkout <branch>`) before sharing.";case`branch-not-on-origin`:{let e=" (If the user says it is already pushed, ask them to `git fetch origin` first to refresh the local mirror, then retry.)";return t?`Branch \`${t}\` is not on origin yet. Ask the user to push it (\`git push -u origin ${t}\`), then retry.${e}`:`The current branch is not on origin yet. Ask the user to push it (\`git push -u origin <branch>\`), then retry.${e}`}case`non-github-remote`:return"Origin is not a `github.com` remote. Share links are GitHub-only in v1.";case`invalid-path`:return"The resolved share path is not shareable (escapes the project root or names the `.git` subtree). Pass a normal target path under the content directory.";default:return`Unknown share-construct-url error: ${String(e)}`}}function isExistingDirectory(e){try{return statSync(e).isDirectory()}catch{return!1}}function resolveExistingDocPath(e,t){for(let s of SUPPORTED_DOC_EXTENSIONS){let g=`${t}${s}`;if(existsSync(g)){let t=resolveWithinRoot(e,g);return t.ok?t.rel:null}}return null}function resolveShareTarget(e,t,s,g){if(s===``)return g===`folder`?{ok:!0,kind:`folder`,sharePath:``}:{ok:!1,code:`invalid-path`};let S=resolveWithinRoot(t,s);if(!S.ok)return{ok:!1,code:`target-not-found`};let w=resolveExistingDocPath(e,S.abs.replace(/\.(mdx|md)$/i,``)),E=isExistingDirectory(S.abs);if(g===`doc`)return w===null?E?{ok:!1,code:`kind-mismatch`}:{ok:!1,code:`target-not-found`}:{ok:!0,kind:`doc`,sharePath:w};if(g===`folder`){if(E){let t=resolveWithinRoot(e,S.abs);return t.ok?{ok:!0,kind:`folder`,sharePath:t.rel}:{ok:!1,code:`target-not-found`}}return w===null?{ok:!1,code:`target-not-found`}:{ok:!1,code:`kind-mismatch`}}if(w!==null)return{ok:!0,kind:`doc`,sharePath:w};if(E){let t=resolveWithinRoot(e,S.abs);return t.ok?{ok:!0,kind:`folder`,sharePath:t.rel}:{ok:!1,code:`target-not-found`}}return{ok:!1,code:`target-not-found`}}const OutputSchema=outputSchemaWithText({ok:boolean().describe(`Success discriminator.`),shareUrl:string().optional().describe(`Marketing share URL (success only).`),sharedUrl:string().optional().describe(`Unencoded GitHub blob/tree URL (success only).`),branch:string().optional().describe(`Branch the share URL pins to (success only).`),resolvedKind:_enum([`doc`,`folder`]).optional().describe(`Kind the target resolved to (success only).`),error:_enum([`no-remote`,`detached-head`,`branch-not-on-origin`,`non-github-remote`,`invalid-path`,`target-not-found`,`kind-mismatch`,`unknown`]).optional().describe(`Failure code (error path only).`),message:string().optional().describe(`Agent-actionable error message (error path only).`),previewUrl:string().nullable().optional().describe("Route-only preview URL (no host:port): `/#/<doc>` for a doc, `/#/<folder>/` for a folder, `/#/` for the content root. `null` when no UI is running."),previewUrlSource:string().optional().describe(`Internal: preview-URL provenance.`)});function register$3(e,t){e.registerTool(`share_link`,{description:DESCRIPTION$3,inputSchema:{path:string().describe('Content-dir-relative target. Doc paths are extension-less (`.md`/`.mdx` stripped). Folder paths name a directory. `""` is the content-root sentinel (folder-only).'),kind:_enum([`doc`,`folder`]).optional().describe("Target kind. Omit to auto-probe disk (`.mdx` → `.md` → directory). REQUIRED when `path` is empty."),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:OutputSchema,annotations:{readOnlyHint:!0,idempotentHint:!0}},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,config:S,url:w}=s;if(!w)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let E=resolveShareTarget(g,join(g,S.content.dir),e.path,e.kind);if(!E.ok){let t;if(E.code===`kind-mismatch`){let s=e.kind===`folder`?`folder`:`doc`;t=`\`${e.path}\` exists, but not as a ${s}. Pass \`kind: '${s===`doc`?`folder`:`doc`}'\` to share it as the other kind.`}else t=E.code===`invalid-path`?'Cannot share the content root from an empty path without `kind: "folder"`. Pass a non-empty path, or `kind: "folder"` to share the root.':`Target \`${e.path}\` does not exist under the content directory (looked for \`.md\`, \`.mdx\`, and a directory).`;let s={ok:!1,error:E.code,message:t};return textPlusStructured(`Error: ${t}`,s,!0)}let D=E.kind===`doc`?{kind:`doc`,docPath:E.sharePath}:{kind:`folder`,folderPath:E.sharePath},O;try{O=await fetch(`${w}/api/share/construct-url`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(D),signal:AbortSignal.timeout(3e4)})}catch(e){let t=`Server unreachable: ${e instanceof Error?e.message:String(e)}`;return textPlusStructured(`Error: ${t}`,{ok:!1,error:`unknown`,message:t},!0)}let k;try{k=await O.json()}catch(e){let t=`Server returned non-JSON body: ${e instanceof Error?e.message:String(e)}`;return textPlusStructured(`Error: ${t}`,{ok:!1,error:`unknown`,message:t},!0)}if(!O.ok){let e;if(k&&typeof k==`object`){let t=k,s=typeof t.title==`string`?t.title:void 0,g=typeof t.detail==`string`?t.detail:void 0;e=s&&g?`${s}: ${g}`:s||g||`HTTP ${O.status}`}else e=`HTTP ${O.status}`;return textPlusStructured(`Error: ${e}`,{ok:!1,error:`unknown`,message:e},!0)}let j=ShareConstructUrlResponseSchema.safeParse(k);if(!j.success){let e=`Server returned an unexpected share-construct-url response shape.`;return textPlusStructured(`Error: ${e}`,{ok:!1,error:`unknown`,message:e},!0)}let F=j.data;if(!F.ok){let e=messageForShareError(F.error,F.branch),t={ok:!1,error:F.error,message:e,...F.branch?{branch:F.branch}:{}};return textPlusStructured(`Error: ${e}`,t,!0)}let{shareUrl:L,sharedUrl:B,branch:H}=F,q={ok:!0,shareUrl:L,sharedUrl:B,branch:H,resolvedKind:E.kind},ee={config:t.config,resolveCwd:t.resolveCwd},J=await resolvePreviewUrlForTool(E.sharePath.replace(/\.(mdx|md)$/i,``),ee,g);if(J&&E.kind===`folder`){let e=E.sharePath.replace(/^\/+|\/+$/g,``),t=e===``?`/#/`:`/#/${encodeDocName(e)}/`;J={...J,url:t}}let Y=e.path===``?`(content root)`:e.path;return textPlusStructured(`Share link for ${E.kind} \`${Y}\` on branch \`${H}\`:\n${L}`,{...q,previewUrl:J?.url??null,...J?{previewUrlSource:J.source}:{}})})}function bundleFileKind(e){return e.replace(/\\/g,`/`).startsWith(`scripts/`)?`script`:`reference`}const INTERNAL_BUNDLE_SKILL_NAMES=new Set(Object.values(BUNDLE_SKILL_NAME));function internalSkillHint(e){return[`"${e}" is one of OpenKnowledge's built-in agent skills — it is NOT managed by this tool and cannot be read or listed here.`,`It is already provided to you in your loaded skill list (a hidden runtime skill projected into your editor); don't fetch or re-load it — just follow the skill you already have.`,"The `skills` tool only covers skills authored as KB content (`.ok/skills` = project, `~/.ok/skills` = global). Built-in `open-knowledge*` skills never appear in either scope."].join(` `)}const SCOPE_FIELD_DESCRIBE="Which level the skill lives at. `project` = this KB's `.ok/skills/` (shared via git with everyone on the project); `global` = your user-level `~/.ok/skills/` (available in every project on this machine, not shared).",SkillListEntryOutputSchema=object$1({name:string().describe("Skill name (its identity; pass to `edit`/`move`/`delete`/`install`)."),scope:_enum([`project`,`global`]).describe(SCOPE_FIELD_DESCRIBE),description:string().optional().describe(`The skill's one-line description (when present).`),installed:boolean().describe(`True when projected into ≥1 editor; false = a Draft.`),hosts:array(string()).describe(`Editor ids the skill is installed into.`),updateAvailable:boolean().optional().describe(`Starter-pack skills only: a newer bundled version is available.`)}),SkillBundleFileEntrySchema=object$1({path:string().describe(`Skill-relative path (e.g. "references/tiers.md").`),kind:_enum([`reference`,`script`]).describe("`reference` (under references/) or `script` (under scripts/).")}),SkillReadOutputSchema=object$1({name:string().describe(`Skill name (its identity).`),scope:_enum([`project`,`global`]).describe(SCOPE_FIELD_DESCRIBE),description:string().describe(`The skill's one-line description (empty if none).`),body:string().describe(`The SKILL.md body (markdown, frontmatter stripped).`),files:array(SkillBundleFileEntrySchema).describe("Bundle files beside SKILL.md (path + kind, no inline text). Read one via `file`.")}),SkillFileReadOutputSchema=object$1({path:string().describe(`Skill-relative path read.`),kind:_enum([`reference`,`script`]).describe("`reference` or `script`."),text:string().describe(`Full text of the bundle file.`)}),DESCRIPTION$2=["[Requires: Hocuspocus server] Read-only discovery for SKILLS — the read half of the skill vocabulary (`write`/`edit`/`delete`/`move`/`install` are the mutate half).",``,"This is how you find and read skills. Skills are addressed by `name` + `scope`, NOT by path — do NOT `ls`/`cat` `.ok/skills/` or pass raw `.ok/...` paths; `.ok/` is opaque internal state.",``,"Covers only skills authored as KB content. OpenKnowledge's own built-in `open-knowledge*` skills (e.g. the `open-knowledge` project skill) are runtime skills already loaded in your skill list — they are NOT here, and you never fetch them through this tool.",``,`**Three modes:**`,"- **List** (omit `name`): every skill across BOTH levels — Project (this KB) and Global (user-level). Returns name, scope, description, installed/hosts, and (for starter packs) `updateAvailable`.","- **Read skill** (pass `name`): that skill's description + body + a `files` list (`{ path, kind }`, no inline text) of its `references/**`+`scripts/**` bundle files. `scope` optional — omitted, it resolves by name (preferring Project when a name exists at both levels).","- **Read file** (pass `name` + `file`): one bundle file's text — the universal read path for references + scripts (no native `cat`)."].join(`
1998
+ `);function register$2(e,t){e.registerTool(`skills`,{description:DESCRIPTION$2,inputSchema:{name:string().optional().describe(`Omit to LIST all skills; pass a skill name to READ that skill.`),file:string().optional().describe("With `name`: read ONE bundle file by its skill-relative path (`references/...`/`scripts/...`)."),scope:SkillScopeArg.optional(),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({skills:array(SkillListEntryOutputSchema).optional().describe(`Present in LIST mode: every skill across Project + Global levels.`),skill:SkillReadOutputSchema.optional().describe(`Present in READ-skill mode: the named skill (description, body, files list).`),file:SkillFileReadOutputSchema.optional().describe(`Present in READ-file mode: one bundle file (path, kind, text).`)})},async e=>{if(e.name!==void 0&&INTERNAL_BUNDLE_SKILL_NAMES.has(e.name))return textResult(`Error: ${internalSkillHint(e.name)}`,!0);let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{url:g}=s;if(!g)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);if(e.file!==void 0&&e.name===void 0)return textResult('Error: `file` reads ONE bundle file of a skill — pass `name` too: skills({ name, file: "references/x.md" }).',!0);if(e.file!==void 0){let t=resolveSkillFilePath(e.file);if(!t.ok)return textResult(`Error: ${t.error}`,!0)}if(e.name===void 0){let e=await httpGet(g,`/api/skills`);if(!e.ok)return textResult(`Error: ${e.error}`,!0);let{ok:t,...s}=e,S=(Array.isArray(s.skills)?s.skills:[]).map(e=>({name:e.name,scope:e.scope,...typeof e.description==`string`?{description:e.description}:{},installed:e.installed===!0,hosts:Array.isArray(e.hosts)?e.hosts:[],...typeof e.updateAvailable==`boolean`?{updateAvailable:e.updateAvailable}:{}}));return textPlusStructured(JSON.stringify({skills:S},null,2),{skills:S})}let S=e.scope;if(S===void 0){let t=await httpGet(g,`/api/skills`);if(!t.ok)return textResult(`Error: ${t.error}`,!0);let{ok:s,...w}=t,E=(Array.isArray(w.skills)?w.skills:[]).filter(t=>t.name===e.name);if(E.length===0)return textResult(`Error: no skill named "${e.name}" (Project or Global).`,!0);S=E.find(e=>e.scope===`project`)===void 0?E[0]?.scope:`project`}if(e.file!==void 0){let t=await readSkillFile(g,S,e.name,e.file);if(!t.ok)return textResult(`Error: ${t.error}`,!0);let s={path:t.path,kind:t.kind,text:t.text};return textPlusStructured(JSON.stringify({file:s},null,2),{file:s})}let w=await fetchSkill(g,S,e.name);if(!w.ok)return textResult(`Error: ${w.error}`,!0);let E={name:e.name,scope:S,description:w.description,body:w.body,files:w.files.map(e=>({path:e.path,kind:bundleFileKind(e.path)}))};return textPlusStructured(JSON.stringify({skill:E},null,2),{skill:E})})}function buildConsolidateBody(e,t){return`Promote existing research on this topic into a canonical article inside the project content directory. **Canonical, not provisional** — the output is the source of truth for future agents.
1995
1999
 
1996
2000
  Topic: ${e}
1997
2001
 
@@ -3084,7 +3088,7 @@ Default when the user says nothing: \`internal\` / \`standard\`.
3084
3088
  ## Source-reference convention (how wiki pages point at code)
3085
3089
 
3086
3090
  - **Intra-wiki navigation** → OK doc links (\`[Auth flow](../flows/auth.md)\`). These build the full backlink / hub / orphan graph. Link liberally — density is how the wiki stays navigable.
3087
- - **Code references, \`internal\`** → a relative markdown link to the source file plus an inline code-span for the symbol — e.g. the \`bootServer()\` symbol in [boot.ts](../../packages/server/src/boot.ts). Relative links click-open in the asset preview and produce **no dead-link noise** (the link graph only tracks \`.md\`/\`.mdx\` edges, so source links are never reported dead). A cosmetic \`#Lxx\` is fine but not navigable.
3091
+ - **Code references, \`internal\`** → a relative markdown link to the source file plus an inline code-span for the symbol — e.g. the \`bootServer()\` symbol in [boot.ts](../../packages/server/src/boot.ts). Relative source links click-open in the asset preview and stay out of the navigation graph (the \`links\` graph tracks only \`.md\`/\`.mdx\` edges, so source links never show as graph dead-links or orphans) — but the write/edit \`brokenLinks\` response DOES validate them: a wrong-depth path resolving to a missing file is reported \`no-such-file\`, and one that overshoots the content root is \`unresolvable\`. So count the \`../\` hops from the page's own folder, not the wiki root. A cosmetic \`#Lxx\` is fine but not navigable.
3088
3092
  - **Code references, \`public\`** → GitHub blob URLs (\`https://github.com/<org>/<repo>/blob/<branch>/path/to/file.ts\`) so a reader without the repo can follow them. Detect the remote with \`exec\` (or native \`git remote get-url origin\`); if there is none, fall back to relative links.
3089
3093
 
3090
3094
  Never invent paths — every source reference must point at a file you actually read.
@@ -3160,7 +3164,7 @@ Atomic pages for domain terms and core abstractions (one term each): definition,
3160
3164
  2. Run \`links({ kind: ["orphans", "hubs", "dead"] })\`:
3161
3165
  - **orphans** — pages nothing links to. Adopt each by linking it from OVERVIEW or a relevant section page (or, rarely, justify it as intentionally standalone).
3162
3166
  - **hubs** — ranks by *inbound* links. Confirm your **concept/module pages** show up here — that's the signal cross-linking actually happened. Don't expect \`OVERVIEW\`: a freshly authored nav page has almost no inbound links, so it won't appear (and that's correct — its coverage was checked in step 1).
3163
- - **dead** — fix or remove every dead link. (Source-file links never appear here — only \`.md\`/\`.mdx\` edges are tracked.)
3167
+ - **dead** — fix or remove every dead link. (Source-file links don't appear in this graph — only \`.md\`/\`.mdx\` edges are tracked — but they ARE validated by \`brokenLinks\` on each write/edit, per the code-reference rule above.)
3164
3168
  3. Append a \`wiki/log.md\` entry (see *Log discipline*).
3165
3169
  4. Tell the user the wiki is ready and surface the OVERVIEW preview URL.
3166
3170
 
@@ -3215,12 +3219,12 @@ Incremental by default — don't re-read the whole repo.
3215
3219
  - **Empty / unreadable repo** (no source detected in Phase 1) → tell the user there's nothing to document yet. Exit.
3216
3220
  `}const DESCRIPTION$1=["Procedural guides for the three-layer wiki workflow + brownfield onboarding. Returns a numbered plan (instructional text, not data) — you execute it. Dispatches on `kind`:",``,'- `kind: "ingest"` — capture an external source (URL or local file) into the KB as raw, verbatim reference material (no analysis). Requires `source`.','- `kind: "research"` — gather sources and write provisional findings for a question. Requires `topic`.','- `kind: "consolidate"` — fold provisional material into a canonical article. Requires `topic`.','- `kind: "discover"` — extract conventions from an existing repo (folder frontmatter + templates + link graph). No payload.','- `kind: "wiki"` — generate (or refresh) a navigable, diagram-rich, source-grounded wiki of this codebase into the `wiki/` knowledge base (the `codebase-wiki` pack). No payload; tune via natural-language `audience`/`depth` in your request.',``,`**Parameters:**`,"- `kind` — `ingest` | `research` | `consolidate` | `discover` | `wiki`.","- `source` — Required for `ingest`: the URL / file path / identifier to capture.","- `topic` — Required for `research` / `consolidate`: the topic, question, or anchor URL.","- `cwd` (optional) — Project root (see `cwd` description below)."].join(`
3217
3221
  `);function register$1(e,t){let s=buildWorkflowHandler(`ingest`,t,`source`,buildIngestBody),g=buildWorkflowHandler(`research`,t,`topic`,buildResearchBody),S=buildWorkflowHandler(`consolidate`,t,`topic`,buildConsolidateBody);e.registerTool(`workflow`,{description:DESCRIPTION$1,inputSchema:{kind:_enum([`ingest`,`research`,`consolidate`,`discover`,`wiki`]).describe(`Which workflow guide to return.`),source:string().optional().describe('Required for `kind: "ingest"` — the URL / file / identifier to capture.'),topic:string().optional().describe('Required for `kind: "research"` / `"consolidate"` — the topic / question / anchor URL.'),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({previewUrl:previewUrlOutputField.describe(`Always null — a workflow guide is prose, not a previewable document.`)})},async e=>{switch(e.kind){case`ingest`:return e.source?s(e):textResult('Error: workflow({ kind: "ingest" }) requires `source` — the URL / file / identifier to capture. e.g. workflow({ kind: "ingest", source: "https://example.com/spec" }).',!0);case`research`:return e.topic?g(e):textResult('Error: workflow({ kind: "research" }) requires `topic` — the question or topic to investigate. e.g. workflow({ kind: "research", topic: "rate-limit strategies" }).',!0);case`consolidate`:return e.topic?S(e):textResult('Error: workflow({ kind: "consolidate" }) requires `topic` — the topic to fold into a canonical article. e.g. workflow({ kind: "consolidate", topic: "rate-limit strategies" }).',!0);case`discover`:{let s=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);return s.ok?textPlusStructured(buildDiscoverBody(s.config.content.dir),{previewUrl:null}):textResult(`Error: ${s.error}`,!0)}case`wiki`:{let s=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);return s.ok?textPlusStructured(buildWikiBody(s.config.content.dir),{previewUrl:null}):textResult(`Error: ${s.error}`,!0)}default:return textResult(`Error: unknown workflow kind.`,!0)}})}const DESCRIPTION=`${["Create or replace one thing. Pass EXACTLY ONE of `document`, `folder`, `template`, `skill`, or `asset` (or `documents` for a batch of docs).",``,'- `document` — Create or overwrite a doc via the CRDT layer [Requires: Hocuspocus server]. `{ path, content }`, or `{ path, template }` to instantiate from a folder template (mutually exclusive with `content`). Optional `frontmatter` (its own YAML) and `position` (`replace` default for a new doc; required for an existing one) — note supplying `frontmatter` alongside literal `content` forces `position: replace` (the only position that persists a YAML block), overriding an explicit `append`/`prepend`. Example: `{ document: { path: "meetings/standup", content: "# Standup\\n..." } }`.','- `folder` — Create a NEW folder (optionally with its own properties) [Requires: Hocuspocus server]. `{ path, frontmatter? }`. To change an EXISTING folder use `edit`. Example: `{ folder: { path: "ideas" } }`.','- `template` — Create a reusable starting shape for new docs in a folder. `{ path: "<folder>/<name>", content, frontmatter: { title, description?, tags? } }`.','- `skill` — Create or overwrite an agent SKILL (`.ok/skills/<name>/SKILL.md`): reusable agent guidance you author in OK and `install` into your editors. `{ name, description, body, scope? }`. `name` is the identity (lowercase-hyphen); `description` is the trigger (when to use it). Example: `{ skill: { name: "trip-log", description: "Use when logging a fishing trip.", body: "# Steps\\n..." } }`.','- `asset` — Upload a binary (image/file) via the media route [Requires: Hocuspocus server]. `{ path: "<folder>/<file.ext>", content(base64) | source(local path) }`.',"- `documents` — Batch: `[{ path, content?|template?, frontmatter?, position?, summary? }, ...]` written in order; the response reports each.","- `summary` — Optional one-line user-outcome (≤80 chars) for the timeline, for a single `document`/`folder`/`template`/`asset` write. For a `documents` batch, give each entry its own `summary` instead (a top-level `summary` is ignored on the batch path). Avoid secrets or PII — persisted to git history.",``,"Responses may include `structuredContent.document.warnings` (batch: per-entry under `documents[]`) — advisory entries discriminated by `kind`: `content-divergence` / `disk-edit-reconciled` (write-integrity — re-read the doc) and `mermaid-parse-error` (the write landed but that fence will not render — fix it and re-edit)."].join(`
3218
- `)}\n${renderInventoryFooter()}`;function frontmatterIgnoredNote(e,t){return e!==`prepend`&&e!==`append`||!t||stripFrontmatter(t).frontmatter.trim()===``?null:`Note: a \`---\` frontmatter block in this \`${e}\` payload was ignored — frontmatter is written only with \`position: "replace"\`. To change frontmatter, use \`edit({ document: { path, frontmatter } })\` (patch) or \`write({ document: { path, content, position: "replace" } })\` (full rewrite).`}function emptyAppendNoOpNote(e,t){return e!==`prepend`&&e!==`append`||t===void 0||stripFrontmatter(t).body!==``?null:`No content to ${e} — document unchanged. To clear a document, use \`position: "replace"\` with empty \`content\`.`}function docExtensionOnDisk(e,t){for(let s of SUPPORTED_DOC_EXTENSIONS){let g=resolveWithinRoot(e,`${t}${s}`);if(g.ok&&existsSync(g.abs))return s}return null}function requestedDocExtension(e){let t=e.toLowerCase();return t.endsWith(`.mdx`)?`.mdx`:t.endsWith(`.md`)?`.md`:null}function extensionIgnoredNote(e,t,s){return e===null||t===null||e===t?null:`Note: "${s}" already exists as \`${s}${t}\`, so the requested \`${e}\` extension was not applied — the write went to \`${s}${t}\`. Changing a doc's on-disk extension in place isn't available via the MCP today.`}function composeWithFrontmatter(e,t){let{frontmatter:s,body:g}=stripFrontmatter(t),S={};if(s!==``){let e=parseFrontmatterYaml(unwrapFrontmatterFences(s));if(e.map===null)return{ok:!1,error:`EMBEDDED_FRONTMATTER_MALFORMED — \`content\` opens with a \`---\` block whose YAML failed to parse (${e.parseError}), so it can't be merged with the \`frontmatter\` param. Fix the embedded YAML, or supply the frontmatter only via the \`frontmatter\` param (not also inline in \`content\`).`};S=e.map}let w=serializeFrontmatterMap(mergePatch(S,e));return w===``?{ok:!0,markdown:g}:{ok:!0,markdown:withFences(w)+g}}async function writeOneDoc(e,t,s,g,S){let w=normalizeDocName(e.path);if(!w.ok)return{docName:e.path,ok:!1,error:okReservedPathRedirect(e.path)??w.error};let E=w.docName,D=S.identityRef?.current;if(e.template===void 0&&e.content===void 0)return{docName:E,ok:!1,error:"either `content` or `template` must be provided — omitting both would write empty content."};if(e.template!==void 0&&e.content!==void 0)return{docName:E,ok:!1,error:"TEMPLATE_AND_CONTENT_BOTH_SET — `template` and `content` are mutually exclusive. Pass one; fill placeholders via subsequent `edit` calls."};let O=e.content??``,k=e.frontmatter!==void 0&&Object.keys(e.frontmatter).length>0,j=docExtensionOnDisk(s,E),F=j!==null,L=e.extension??requestedDocExtension(e.path),B;if(e.position!==void 0)B=e.position;else if(F)return{docName:E,ok:!1,error:`"${E}" already exists — pass \`position\` (\`append\` | \`prepend\` | \`replace\`), or use \`edit\` for a targeted change.`};else B=`replace`;if(e.template!==void 0){let s=parentFolderOf(E),g=resolveTemplatesAvailable(t,s,{depth:1}),S=g.find(t=>t.name===e.template);if(!S)return{docName:E,ok:!1,error:`template "${e.template}" not found for folder "${s||`.`}". Available: ${g.length===0?`(none)`:g.map(e=>`${e.name} [${e.scope}]`).join(`, `)}. Templates are resolved by walk-up; check the parent folder's exec listing to see the menu.`};let w;try{w=readFileSync(resolve(t,S.path),`utf-8`)}catch(e){return{docName:E,ok:!1,error:`failed to read template at ${S.path}: ${e.message}`}}O=applySubstitution(instantiateDoc(w),{date:todayIsoUtc(),user:D?.displayName??``}),B=`replace`}else if(k){let t=composeWithFrontmatter(e.frontmatter,O);if(!t.ok)return{docName:E,ok:!1,error:t.error};O=t.markdown,B=`replace`}if(!F&&normalizeBridge(O)===``)return{docName:E,ok:!1,error:`"${E}" does not exist and the content is empty — provide non-empty content to create the document.`};let H=await httpPost(g,`/api/agent-write-md`,{docName:E,markdown:O,position:B,...L!==null&&!F?{extension:L}:{},...e.summary===void 0?{}:{summary:e.summary},...agentIdentityFields(D)});if(!H.ok){let e=typeof H.detail==`string`&&H.detail.length>0?H.detail:``;return{docName:E,ok:!1,error:e?`${String(H.error)} (${e})`:String(H.error)}}if(e.template!==void 0&&k){let t=await httpPost(g,`/api/frontmatter-patch`,{docName:E,patch:e.frontmatter,...agentIdentityFields(D)});if(!t.ok)return{docName:E,ok:!1,error:`document created from template but frontmatter failed: ${String(t.error)}`}}let q=extensionIgnoredNote(L,j,E);return{docName:E,ok:!0,position:B,...e.template===void 0?{}:{fromTemplate:e.template},...q?{extensionNote:q}:{},raw:H}}async function handleFolder(e,t,s,g){if(!s)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let S=g.identityRef?.current,w=await httpPost(s,`/api/create-folder`,{path:e.path,...t===void 0?{}:{summary:t},...agentIdentityFields(S)});if(!w.ok){let e=typeof w.detail==`string`&&w.detail.length>0?w.detail:``;return textResult(e?`Error: ${w.error} (${e})`:`Error: ${w.error}`,!0)}let E=[`Created folder ${e.path}.`];if(e.frontmatter!==void 0&&Object.keys(e.frontmatter).length>0){let g=await httpPut(s,`/api/folder-config`,{path:e.path,frontmatter:e.frontmatter,...t===void 0?{}:{summary:t},...agentIdentityFields(S)});if(!g.ok)return textPlusStructured(`Created folder ${e.path}, but writing its properties failed: ${g.error}. Use edit({ folder: { path: "${e.path}", frontmatter } }) to retry the properties.`,{folder:{ok:!0,path:e.path,frontmatterError:String(g.error)}});E.push(`Set folder properties (${e.path}/.ok/frontmatter.yml).`)}return textPlusStructured(E.join(`
3222
+ `)}\n${renderInventoryFooter()}`;function frontmatterIgnoredNote(e,t){return e!==`prepend`&&e!==`append`||!t||stripFrontmatter(t).frontmatter.trim()===``?null:`Note: a \`---\` frontmatter block in this \`${e}\` payload was ignored — frontmatter is written only with \`position: "replace"\`. To change frontmatter, use \`edit({ document: { path, frontmatter } })\` (patch) or \`write({ document: { path, content, position: "replace" } })\` (full rewrite).`}function emptyAppendNoOpNote(e,t){return e!==`prepend`&&e!==`append`||t===void 0||stripFrontmatter(t).body!==``?null:`No content to ${e} — document unchanged. To clear a document, use \`position: "replace"\` with empty \`content\`.`}function requestedDocExtension(e){let t=e.toLowerCase();return t.endsWith(`.mdx`)?`.mdx`:t.endsWith(`.md`)?`.md`:null}function extensionIgnoredNote(e,t,s){return e===null||t===null||e===t?null:`Note: "${s}" already exists as \`${s}${t}\`, so the requested \`${e}\` extension was not applied — the write went to \`${s}${t}\`. Changing a doc's on-disk extension in place isn't available via the MCP today.`}function composeWithFrontmatter(e,t){let{frontmatter:s,body:g}=stripFrontmatter(t),S={};if(s!==``){let e=parseFrontmatterYaml(unwrapFrontmatterFences(s));if(e.map===null)return{ok:!1,error:`EMBEDDED_FRONTMATTER_MALFORMED — \`content\` opens with a \`---\` block whose YAML failed to parse (${e.parseError}), so it can't be merged with the \`frontmatter\` param. Fix the embedded YAML, or supply the frontmatter only via the \`frontmatter\` param (not also inline in \`content\`).`};S=e.map}let w=serializeFrontmatterMap(mergePatch(S,e));return w===``?{ok:!0,markdown:g}:{ok:!0,markdown:withFences(w)+g}}async function writeOneDoc(e,t,s,g,S){let w=normalizeDocName(e.path);if(!w.ok)return{docName:e.path,ok:!1,error:okReservedPathRedirect(e.path)??w.error};let E=w.docName,D=S.identityRef?.current;if(e.template===void 0&&e.content===void 0)return{docName:E,ok:!1,error:"either `content` or `template` must be provided — omitting both would write empty content."};if(e.template!==void 0&&e.content!==void 0)return{docName:E,ok:!1,error:"TEMPLATE_AND_CONTENT_BOTH_SET — `template` and `content` are mutually exclusive. Pass one; fill placeholders via subsequent `edit` calls."};let O=e.content??``,k=e.frontmatter!==void 0&&Object.keys(e.frontmatter).length>0,j=docExtensionOnDisk(s,E)??null,F=j!==null,L=e.extension??requestedDocExtension(e.path),B;if(e.position!==void 0)B=e.position;else if(F)return{docName:E,ok:!1,error:`"${E}" already exists — pass \`position\` (\`append\` | \`prepend\` | \`replace\`), or use \`edit\` for a targeted change.`};else B=`replace`;if(e.template!==void 0){let s=parentFolderOf(E),g=resolveTemplatesAvailable(t,s,{depth:1}),S=g.find(t=>t.name===e.template);if(!S)return{docName:E,ok:!1,error:`template "${e.template}" not found for folder "${s||`.`}". Available: ${g.length===0?`(none)`:g.map(e=>`${e.name} [${e.scope}]`).join(`, `)}. Templates are resolved by walk-up; check the parent folder's exec listing to see the menu.`};let w;try{w=readFileSync(resolve(t,S.path),`utf-8`)}catch(e){return{docName:E,ok:!1,error:`failed to read template at ${S.path}: ${e.message}`}}O=applySubstitution(instantiateDoc(w),{date:todayIsoUtc(),user:D?.displayName??``}),B=`replace`}else if(k){let t=composeWithFrontmatter(e.frontmatter,O);if(!t.ok)return{docName:E,ok:!1,error:t.error};O=t.markdown,B=`replace`}if(!F&&normalizeBridge(O)===``)return{docName:E,ok:!1,error:`"${E}" does not exist and the content is empty — provide non-empty content to create the document.`};let H=await httpPost(g,`/api/agent-write-md`,{docName:E,markdown:O,position:B,...L!==null&&!F?{extension:L}:{},...e.summary===void 0?{}:{summary:e.summary},...agentIdentityFields(D)});if(!H.ok){let e=typeof H.detail==`string`&&H.detail.length>0?H.detail:``;return{docName:E,ok:!1,error:e?`${String(H.error)} (${e})`:String(H.error)}}if(e.template!==void 0&&k){let t=await httpPost(g,`/api/frontmatter-patch`,{docName:E,patch:e.frontmatter,...agentIdentityFields(D)});if(!t.ok)return{docName:E,ok:!1,error:`document created from template but frontmatter failed: ${String(t.error)}`}}let q=extensionIgnoredNote(L,j,E);return{docName:E,ok:!0,position:B,...e.template===void 0?{}:{fromTemplate:e.template},...q?{extensionNote:q}:{},raw:H}}async function handleFolder(e,t,s,g){if(!s)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let S=g.identityRef?.current,w=await httpPost(s,`/api/create-folder`,{path:e.path,...t===void 0?{}:{summary:t},...agentIdentityFields(S)});if(!w.ok){let e=typeof w.detail==`string`&&w.detail.length>0?w.detail:``;return textResult(e?`Error: ${w.error} (${e})`:`Error: ${w.error}`,!0)}let E=[`Created folder ${e.path}.`];if(e.frontmatter!==void 0&&Object.keys(e.frontmatter).length>0){let g=await httpPut(s,`/api/folder-config`,{path:e.path,frontmatter:e.frontmatter,...t===void 0?{}:{summary:t},...agentIdentityFields(S)});if(!g.ok)return textPlusStructured(`Created folder ${e.path}, but writing its properties failed: ${g.error}. Use edit({ folder: { path: "${e.path}", frontmatter } }) to retry the properties.`,{folder:{ok:!0,path:e.path,frontmatterError:String(g.error)}});E.push(`Set folder properties (${e.path}/.ok/frontmatter.yml).`)}return textPlusStructured(E.join(`
3219
3223
  `),{folder:{ok:!0,path:e.path}})}async function handleTemplate(e,t,s,g){let S=resolveTemplatePath(e.path);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{folder:w,name:E}=S;if(!s)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=await httpPut(s,`/api/template`,{folder:w,name:E,body:e.content,frontmatter:{title:e.frontmatter.title,...typeof e.frontmatter.description==`string`?{description:e.frontmatter.description}:{},...Array.isArray(e.frontmatter.tags)?{tags:e.frontmatter.tags}:{}},...t===void 0?{}:{summary:t},...agentIdentityFields(g.identityRef?.current)});if(!D.ok)return textResult(`Error: ${D.error}`,!0);let O=D.created===!0,k=typeof D.path==`string`?D.path:void 0;return textPlusStructured(`${O?`Created`:`Updated`} template "${E}" in ${w||`(root)`}${k?` (${k})`:``}.`,{template:{ok:!0,path:k,created:O}})}async function handleAsset(e,t,s,g){if(!s)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);if(e.content===void 0==(e.source===void 0))return textResult("Error: provide exactly one of `content` (base64) or `source` (local file path) for an asset.",!0);let S;try{S=e.content===void 0?readFileSync(resolve(t,e.source)):Buffer.from(e.content,`base64`)}catch(e){return textResult(`Error: could not read asset bytes: ${e.message}`,!0)}if(S.byteLength===0)return textResult(`Error: asset is empty (0 bytes).`,!0);let{folder:w,name:E}=splitTargetPath(e.path),D=w?`${w}/${E}`:E,O=g.identityRef?.current,k=new URLSearchParams;O?.connectionId&&k.set(`agentId`,O.connectionId),O?.displayName&&k.set(`agentName`,O.displayName);let j=k.toString(),F=new FormData;F.append(`parentDocName`,D),F.append(`file`,new Blob([new Uint8Array(S)]),E);let L;try{let e=await fetch(`${s}/api/upload${j?`?${j}`:``}`,{method:`POST`,body:F}),t=await e.json().catch(()=>null);L=e.ok?{ok:!0,status:e.status,data:t??{}}:{ok:!1,status:e.status,error:t&&(typeof t.title==`string`?t.title:t.error)||`Upload failed (HTTP ${e.status}).`}}catch(e){return textResult(`Error: upload request failed: ${e.message}`,!0)}if(!L.ok)return textResult(`Error: ${L.error}`,!0);let B=typeof L.data?.src==`string`?L.data.src:void 0,H=typeof L.data?.path==`string`?L.data.path:void 0,q=L.data?.deduped===!0,ee=B??H??E;return textPlusStructured([`Uploaded asset to ${D}${q?` (deduplicated — identical bytes already present)`:``}.`,`Reference it in a doc with: ![${E}](${ee})`].join(`
3220
3224
  `),{asset:{ok:!0,...B?{src:B}:{},...H?{path:H}:{},...q?{deduped:q}:{}}})}async function handleSkillWrite(e,t,s,g,S){let w=g.identityRef?.current,E=e.description!==void 0,D=e.files??[];if(!E&&D.length===0)return textResult("Error: provide `description` (to author SKILL.md) and/or `files` (to write references/scripts) — a skill write with neither does nothing.",!0);if(e.body!==void 0&&!E)return textResult('Error: `body` updates SKILL.md, so it needs a `description` too. To write a reference, use `files: [{ path: "references/...", content }]` instead.',!0);for(let e of D){let t=resolveSkillFilePath(e.path);if(!t.ok)return textResult(`Error: ${t.error}`,!0)}let O=[],k=null;if(E&&(k=await writeSkill(s,{name:e.name,scope:e.scope,description:e.description,body:e.body,summary:t,identity:w,lockDir:S}),k.isError))return k;for(let g of D){let S=await writeSkillFile(s,{name:e.name,scope:e.scope,path:g.path,content:g.content,summary:t,identity:w}),E=S.structuredContent;if(S.isError)O.push({path:g.path,ok:!1,error:S.content[0]?.text??`write failed`});else{let e=E?.skill?.file??{};O.push({path:g.path,ok:!0,...typeof e.kind==`string`?{kind:e.kind}:{},...typeof e.created==`boolean`?{created:e.created}:{}})}}let j=O.filter(e=>e.ok).length,F=O.some(e=>!e.ok),L=k?.structuredContent??{},B=L.skill??{ok:!0},H={...L,skill:{...B,...D.length>0?{files:O}:{}}},q=[];if(E&&k&&q.push(k.content[0]?.text??``),D.length>0){q.push(`${j}/${D.length} bundle file(s) written.`);for(let e of O)q.push(e.ok?` ${e.path} (${e.kind??`file`})`:` Failed ${e.path}: ${e.error}`)}return textPlusStructured(q.filter(Boolean).join(`
3221
- `),H,F)}async function handleBatch(e,t,s,g,S,w,E){let D=[];for(let w of e)D.push(await writeOneDoc(w,t,s,g,S));let O=D.map(e=>{if(!e.ok)return{docName:e.docName,ok:!1,error:e.error};let t=resolvePreviewUrl(e.docName,{lockDir:w}),s=parseAdvisoryWarnings(e.raw.warnings);return{docName:e.docName,ok:!0,position:e.position,...t?{previewUrl:t.url}:{},...s?{warnings:s}:{}}}),k=O.filter(e=>e.ok).length,j=k===O.length,F=e.map((e,t)=>{let s=D[t];if(!s?.ok)return`Failed ${e.path}: ${s?.error??`unknown error`}`;if(emptyAppendNoOpNote(s.position,e.content))return`No change to ${e.path} — empty ${s.position}, document unchanged.`;let g=O[t],S=[`Wrote ${e.path} (${s.position}).`];return g?.ok&&g.warnings&&S.push(...formatAdvisoryBriefs(g.warnings)),S.join(` `)}),L=e.flatMap((e,t)=>{let s=D[t];if(!s?.ok)return[];let g=frontmatterIgnoredNote(s.position,e.content);return[...g?[g]:[],...s.extensionNote?[s.extensionNote]:[]].map(t=>`${e.path} — ${t}`)}),B=[`${k}/${O.length} written.`,...F,...L].join(`
3222
- `),H={documents:O},q=D.find(e=>e.ok);return q&&q.raw.systemSubscriberCount===0&&(H.warning=buildPreviewAttachWarning(resolvePreviewUrl(q.docName,{lockDir:w}),E)),textPlusStructured(B,H,!j)}async function handleSingleDoc(e,t,s,g,S,w,E){let D=await writeOneDoc(e,t,s,g,S);if(!D.ok)return textResult(`Error: ${D.error}`,!0);let O=D.raw,k=resolvePreviewUrl(D.docName,{lockDir:w}),j=typeof O.subscriberCount==`number`?O.subscriberCount:void 0,F=(typeof O.systemSubscriberCount==`number`?O.systemSubscriberCount:void 0)===0,L=j===0,B=Array.isArray(O.hints)?O.hints:void 0,H=O.summary&&typeof O.summary==`object`?O.summary:void 0,q=typeof H?.hint==`string`?H.hint:void 0,ee=parseAdvisoryWarnings(O.warnings),J=[emptyAppendNoOpNote(D.position,e.content)??(D.fromTemplate===void 0?`Written successfully (${D.position}).`:`Written successfully (instantiated from template "${D.fromTemplate}").`)],Y=frontmatterIgnoredNote(D.position,e.content);if(Y&&J.push(Y),D.extensionNote&&J.push(D.extensionNote),F&&!k&&J.push(START_UI_TEXT_HINT),q&&J.push(q),B)for(let e of B)e.message&&J.push(e.message);ee&&J.push(...formatAdvisoryLines(ee));let te=J.join(`
3223
- `);if(!k&&!F&&!L&&!B&&!H&&!ee)return textResult(te);let ne={};return B&&(ne.hints=B),H&&(ne.summary=H),ee&&(ne.warnings=ee),textPlusStructured(te,nestDocResult(k,F?buildPreviewAttachWarning(k,E):void 0,ne))}function register(e,t){let s={path:string().describe('Document path. The slashes are the folder it lands in; missing parent folders are created. Example: "meetings/2026-06-03-standup". An optional `.md`/`.mdx` suffix selects the file format (default `.md`); prefer the `extension` field for that. The docName itself is always extension-less.'),content:string().optional().describe("The full Markdown body. Mutually exclusive with `template`."),extension:DocExtensionArg.optional(),template:string().min(1).optional().describe("Instantiate the new doc from a folder template (resolved against the parent folder's templates_available, leaf→root walk-up; closest-wins). Mutually exclusive with `content`. Inspect the menu with an `exec` listing of the folder."),frontmatter:FrontmatterArg.optional().describe("The doc's OWN frontmatter (YAML). Written inline on create; for an existing doc prefer `edit`."),position:PositionArg.optional()};e.registerTool(`write`,{description:DESCRIPTION,inputSchema:{document:object$1(s).optional().describe(`Create or overwrite a DOCUMENT. Example: { document: { path: "meetings/standup", content: "# Standup\\n..." } }`),folder:object$1({path:string().describe(`Folder path. Example: "meetings".`),frontmatter:FrontmatterArg.optional().describe("The folder's OWN frontmatter (open-shape; `title`/`description`/`tags` are the conventional keys). Describes the folder only — does NOT flow into docs inside it.")}).optional().describe('Create a NEW folder (errors with 409 if it exists — use `edit` to change an existing folder). Example: { folder: { path: "ideas" } }'),template:object$1({path:string().describe(TEMPLATE_PATH_DESCRIBE),content:string().describe(TEMPLATE_CONTENT_DESCRIBE),frontmatter:object$1({title:string().min(1).describe(`Required — the label shown when an agent picks this template.`),description:string().optional().describe(`Optional — shown beside the title in the template menu.`),tags:array(string()).optional().describe(`Optional — tags for the template.`)}).describe("Template metadata. Only `title` (required), `description`, and `tags` are persisted (unlike open-shape doc/folder frontmatter).")}).optional().describe(`Create a TEMPLATE (a reusable starting shape for new docs in a folder). Example: { template: { path: "fishing-log/trip-log", content: "# {{date}}\\n", frontmatter: { title: "Trip Log" } } }`),skill:object$1({name:string().describe(SKILL_NAME_DESCRIBE),description:string().optional().describe(`${SKILL_DESCRIPTION_DESCRIBE} Optional when writing ONLY \`files\` into an existing skill (omit to leave SKILL.md untouched).`),body:string().optional().describe(SKILL_BODY_DESCRIBE),files:array(object$1({path:string().describe("Skill-relative path under `references/` or `scripts/`."),content:string().describe(`Full text of the bundle file.`)})).optional().describe(SKILL_FILES_DESCRIBE),scope:SkillScopeArg.optional()}).optional().describe('Create or overwrite an agent SKILL bundle (`.ok/skills/<name>/`). SKILL.md is authored via `description`+`body`; `references/**` and `scripts/**` via the `files` array. Example: { skill: { name: "trip-log", description: "Use when logging a fishing trip.", body: "# Steps\\n...", files: [{ path: "references/gear.md", content: "..." }] } }'),asset:object$1({path:string().describe(`Asset path incl. extension — the slashes are the folder. Example: "images/diagram.png".`),content:string().optional().describe(`Base64 of the binary. Use for small files.`),source:string().optional().describe(`Local filesystem path the server reads. Use for large files.`)}).optional().describe("Upload a binary asset (image/file) via the media route. Exactly one of `content` | `source`."),documents:array(object$1({...s,summary:summaryArgSchema})).min(1).optional().describe("Batch: documents to write in one call. Mutually exclusive with the single targets. Each entry may carry its own `summary`."),summary:summaryArgSchema,cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({document:object$1({hints:looseObjectArray.optional().describe(`Server-provided write hints, when any.`),...documentResultBaseShape}).optional().describe(`Single-document write result (present when there is a doc-specific signal).`),folder:object$1({ok:boolean(),path:string(),frontmatterError:string().optional().describe("Present when the folder was created but its frontmatter write failed — retry only the properties via `edit({ folder: { frontmatter } })`.")}).optional().describe(`Folder-create result.`),template:object$1({ok:boolean(),path:string(),created:boolean().describe(`true if created, false if an existing template updated.`)}).optional().describe(`Template-create result.`),skill:object$1({ok:boolean(),path:string().optional(),created:boolean().optional().describe(`true if created, false if an existing skill was overwritten.`),files:looseObjectArray.optional().describe("Per-bundle-file results `{ path, kind, created, ok, error? }`.")}).optional().describe(`Skill-create result (SKILL.md and/or bundle files).`),asset:object$1({ok:boolean(),src:string().optional().describe(`The reference src to embed in a doc.`),path:string().optional(),deduped:boolean().optional().describe(`true when identical bytes already existed (no new file written).`)}).optional().describe(`Asset-upload result.`),documents:looseObjectArray.optional().describe("Batch write: per-doc result `{ docName, ok, position?, previewUrl?, warnings?, error? }`."),previewUrl:previewUrlOutputField.optional(),previewUrlSource:previewUrlSourceField,warning:previewAttachWarningField})},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,config:S,url:w}=s,E=resolveLockDir(g),D=resolveContentDir(S,g),O=S.appearance.preview.autoOpen;if(e.documents!==void 0){let s=exactlyOneTargetError(e,[`document`,`folder`,`template`,`skill`,`asset`,`documents`]);return s?textResult(`Error: ${s}`,!0):w?handleBatch(e.documents,g,D,w,t,E,O):textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0)}let k=exactlyOneTargetError(e,[`document`,`folder`,`template`,`skill`,`asset`]);return k?textResult(`Error: ${k}`,!0):e.document===void 0?e.folder===void 0?e.template===void 0?e.skill===void 0?handleAsset(e.asset,g,w,t):handleSkillWrite(e.skill,e.summary,w,t,E):handleTemplate(e.template,e.summary,w,t):handleFolder(e.folder,e.summary,w,t):w?handleSingleDoc({...e.document,summary:e.summary},g,D,w,t,E,O):textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0)})}function registerAllTools(e,t){let s=t.logger,g=createLoggedServer(e,{logger:t.logger,identityRef:t.identityRef}),S=e=>async g=>{try{let S=await t.resolveCwd(g);return(getCurrentMcpLogger()??s)?.debug(`tool cwd resolved`,{tool:e,cwd:S,...g?{explicit:g}:{}}),S}catch(t){throw(getCurrentMcpLogger()??s)?.warn(`tool call failed`,{tool:e,error:t instanceof Error?t.message:String(t),...g?{explicit:g}:{}}),t}};register$13(g,{resolveCwd:S(`exec`),serverUrl:t.serverUrl,config:t.config}),register$1(g,{config:t.config,resolveCwd:S(`workflow`)}),register$4(g,{resolveCwd:S(`search`),config:t.config,serverUrl:t.serverUrl}),register$9(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`links`)}),register(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`write`),identityRef:t.identityRef}),register$14(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`edit`),identityRef:t.identityRef}),register$15(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`delete`),identityRef:t.identityRef}),register$8(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`move`),identityRef:t.identityRef}),register$10(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`install`),identityRef:t.identityRef}),register$11(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`history`)}),register$2(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`skills`)}),register$18(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`checkpoint`),identityRef:t.identityRef}),register$5(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`restore_version`),identityRef:t.identityRef}),register$7(g,{resolveCwd:S(`palette`),config:t.config}),register$17(g,{config:t.config,resolveCwd:S(`config`)}),register$12(g,{config:t.config,resolveCwd:S(`preview_url`),serverUrl:t.serverUrl}),register$16(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`conflicts`)}),register$6(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`resolve_conflict`)}),register$3(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`share_link`)})}function firstHeader(e){return Array.isArray(e)?e[0]:e}function writePlain(e,t,s){e.writableEnded||(e.statusCode=t,e.setHeader(`Content-Type`,`text/plain; charset=utf-8`),e.end(s))}function createSessionServer(e,t,s){let g=e.config,S=new McpServer({name:MCP_SERVER_NAME,version:RUNTIME_VERSION});installPrettyZodErrors(S);let w=s??randomUUID$1(),E={current:{connectionId:w,displayName:w,colorSeed:w}};S.server.oninitialized=()=>{let e=S.server.getClientVersion(),t=sanitizeClientName(e?.name,w);E.current={connectionId:w,clientInfo:e?{name:t,version:e.version}:void 0,displayName:displayNameFromClientName(t),colorSeed:t}};let D=e.projectDir??e.contentDir;return registerAllTools(S,{serverUrl:async()=>e.getServerUrl(),resolveCwd:async e=>{if(e===void 0)return D;let t=resolveWithinRoot(D,e);if(!t.ok)throw Error(`cwd "${e}" is not within the configured project root: ${t.reason}`);return t.abs},config:g,identityRef:E}),{server:S,transport:t}}function createMcpHttpHandler(e){let t=new Map,s=e.sessionTtlMs??1800*1e3,g=e.maxSessions??100;async function S(s,g){let S=t.get(s);if(!S)return;t.delete(s),S.ttlTimer!==void 0&&clearTimeout(S.ttlTimer);let w=await Promise.allSettled([S.server.close(),S.transport.close()]);for(let t of w)t.status===`rejected`&&e.log?.warn?.({err:t.reason,sessionId:s,reason:g},`MCP HTTP session close failed`);e.log?.info?.({sessionId:s,reason:g},`MCP HTTP session closed`)}function w(t,g){g.ttlTimer!==void 0&&clearTimeout(g.ttlTimer),g.ttlTimer=setTimeout(()=>{S(t,`ttl-expired`).catch(s=>{e.log?.warn?.({err:s,sessionId:t},`MCP HTTP session TTL cleanup failed`)})},s),g.ttlTimer.unref?.()}return{async handle(s,E){let D=firstHeader(s.headers[`mcp-session-id`]);if(D){let e=t.get(D);if(!e){writePlain(E,404,`MCP session not found`);return}w(D,e),await e.transport.handleRequest(s,E);return}if(s.method!==`POST`){writePlain(E,400,`Missing MCP session. Initialize with POST /mcp first.`);return}if(t.size>=g){e.log?.warn?.({activeSessions:t.size,maxSessions:g},`MCP HTTP session cap reached`),writePlain(E,503,`Too many active MCP sessions`);return}let O=firstHeader(s.headers[MCP_CONNECTION_ID_HEADER]),k=validateAgentId(O)??void 0;O!==void 0&&k===void 0&&e.log?.warn?.({headerLength:O.length},`MCP HTTP forwarded connectionId header failed validation; falling back to randomUUID`);let j=new StreamableHTTPServerTransport({sessionIdGenerator:()=>randomUUID$1(),enableJsonResponse:!0,onsessioninitialized:async s=>{try{let g=createSessionServer(e,j,k);await g.server.connect(j),t.set(s,g),w(s,g),e.log?.info?.({sessionId:s},`MCP HTTP session initialized`)}catch(g){throw t.delete(s),e.log?.error?.({err:g,sessionId:s},`MCP HTTP session initialization failed`),g}}});j.onerror=t=>{e.log?.warn?.({err:t},`MCP HTTP transport error`)},j.onclose=()=>{let t=j.sessionId;if(!t){e.log?.info?.({sessionId:t,reason:`transport-closed`},`MCP HTTP session closed`);return}S(t,`transport-closed`).catch(s=>{e.log?.warn?.({err:s,sessionId:t},`MCP HTTP transport-close cleanup failed`)})},await j.handleRequest(s,E)},async close(){let e=[...t.entries()];await Promise.allSettled(e.map(([e])=>S(e,`handler-close`)))}}}const DEFAULT_KEEPALIVE_GRACE_MS=1e4,MAX_COLLAB_MESSAGE_BYTES=1024*1024,MCP_CORS_HEADERS={"Access-Control-Allow-Methods":`GET, POST, DELETE, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type, Authorization, traceparent, tracestate, baggage, mcp-session-id, mcp-protocol-version`,"Access-Control-Max-Age":`86400`};function mountMcpAndApi(e){let{httpServer:t,hocuspocus:s,mcpHttpHandler:g,log:S,sessionManager:w,agentFocusBroadcaster:E,agentPresenceBroadcaster:D,maintenanceCoordinator:O,contentAssetMiddleware:k,reactShellMiddleware:j,ephemeral:F}=e,L=e.keepaliveGraceMs??DEFAULT_KEEPALIVE_GRACE_MS,B=new import_websocket_server$1.default({noServer:!0,maxPayload:MAX_COLLAB_MESSAGE_BYTES});B.on(`error`,e=>{S.error({err:e},`WebSocketServer error`)});let H=new Map,q=new Set,ee=!1;return t.on(`request`,(e,t)=>{let w=e.url?.split(`?`)[0];if(g!==void 0&&w===`/mcp`){let s=e.headers.origin,w=Array.isArray(e.headers[`mcp-session-id`])?e.headers[`mcp-session-id`][0]:e.headers[`mcp-session-id`];if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback access required.`,{handler:`mcp`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`mcp`});return}if(s!==void 0&&!isAllowedApiOrigin(s)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`mcp`});return}s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`));for(let[e,s]of Object.entries(MCP_CORS_HEADERS))t.setHeader(e,s);if(e.method===`OPTIONS`){t.writeHead(204),t.end();return}g.handle(e,t).catch(e=>{S.error({err:e,sessionId:w},`Unhandled MCP HTTP error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp`,cause:e}):t.writableEnded||t.end()});return}if(w?.startsWith(`/api/`)){s.hooks(`onRequest`,{request:e,response:t}).then(()=>{t.writableEnded||t.headersSent||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`mcp-mount`,detail:`No handler for ${e.method??`GET`} ${w}`})}).catch(e=>{S.error({err:e},`Unhandled onRequest error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()});return}let E=(s,g,w)=>{if(s===void 0){w();return}try{s(e,t,()=>{t.writableEnded||t.headersSent||w()})}catch(e){S.error({err:e},`Unhandled ${g} middleware error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()}},D=s=>{if(F===!0&&k!==void 0&&(!isLoopbackAddress(e.socket.remoteAddress)||!isAllowedWorkspaceHostHeader(e.headers.host))){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback access required.`,{handler:`content-asset`});return}E(k,`content-asset`,s)},O=e=>E(j,`react-shell`,e),L=()=>{t.writableEnded||t.headersSent||errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`No handler for ${w??`/`}`})};if(j!==void 0&&w?.startsWith(`/assets/`)){O(()=>D(L));return}if(k!==void 0||j!==void 0){D(()=>O(L));return}errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`The React UI is served by \`ok ui\` (run \`ok ui\` and check \`ui.lock.port\`). No handler for ${w??`/`}`})}),t.on(`upgrade`,(e,t,g)=>{if(e.url?.startsWith(`/collab/keepalive`)){if(!isLoopbackAddress(e.socket.remoteAddress)||!isAllowedWorkspaceHostHeader(e.headers.host)){t.destroy();return}t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`MCP keepalive socket error`)}),B.handleUpgrade(e,t,g,t=>{let s=parseKeepaliveConnectionId(e.url);if(s){let e=H.get(s);e!==void 0&&(clearTimeout(e),H.delete(s),S.info({connectionId:s},`[keepalive] reconnect during grace — timer cancelled`))}if(s&&D){let t=parseKeepaliveIdentity(e.url);if(t)try{let e=iconFromClientName(t.clientName),g=AGENT_ICON_COLORS[e]??colorFromSeed(t.colorSeed);D.setPresence(toBroadcasterKey(s),{displayName:t.displayName,icon:e,color:g,currentDoc:`(connected)`,mode:`idle`,ts:Date.now()})}catch(e){S.error({err:e,connectionId:s},`[keepalive] presence bootstrap failed`)}}let g=setInterval(()=>{try{t.ping()}catch{}},3e4);g.unref?.();let k=s?setInterval(()=>{D?.bumpPresenceTs(toBroadcasterKey(s))},3e3):null;k?.unref?.(),t.on(`close`,()=>{if(clearInterval(g),k!==null&&clearInterval(k),!s)return;let e=setTimeout(()=>{if(H.delete(s),ee)return;let e=(async()=>{S.info({connectionId:s},`[keepalive] grace expired — cleaning up sessions`);try{await w?.closeAllForAgent(s)}catch(e){S.error({err:e,connectionId:s},`[keepalive] closeAllForAgent failed`)}try{E?.clearFocus(s)}catch(e){S.error({err:e,connectionId:s},`[keepalive] clearFocus failed`)}try{D?.clearPresence(toBroadcasterKey(s))}catch(e){S.error({err:e,connectionId:s},`[keepalive] clearPresence failed`)}try{await O?.onSessionClose()}catch(e){S.error({err:e,connectionId:s},`[keepalive] maintenance onSessionClose failed`)}})();q.add(e),e.finally(()=>q.delete(e))},L);e.unref?.(),H.set(s,e),S.info({connectionId:s,graceMs:L},`[keepalive] disconnected — grace timer started`)}),t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`MCP keepalive WS error`),t.terminate()})});return}if(e.url?.startsWith(`/collab`)){t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`Upgrade socket error`)}),B.handleUpgrade(e,t,g,t=>{let g=s.handleConnection(t,e),w=!1;t.on(`message`,e=>{if(w)return;let s=e.byteLength;if(s>MAX_COLLAB_MESSAGE_BYTES){w=!0,incrementCollabMessageTooLarge(),S.warn({event:`collab-message-too-large`,bytes:s,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket message rejected before Yjs processing`),t.close(1009,`Message Too Big`);return}g.handleMessage(new Uint8Array(e))}),t.on(`close`,(e,t)=>{g.handleClose({code:e,reason:t.toString()})}),t.on(`error`,e=>{if(e.code===`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`){incrementCollabMessageTooLarge(),S.warn({event:`collab-message-too-large`,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket frame rejected by ws maxPayload before Yjs processing`),t.terminate();return}handleCollabSocketError(e)||S.error({err:e},`WebSocket error`),t.terminate()})});return}t.destroy()}),{wss:B,shutdown:async()=>{if(!ee){ee=!0;for(let e of H.values())clearTimeout(e);H.clear(),q.size>0&&await Promise.allSettled(q)}}}}function parseKeepaliveConnectionId(e){if(!e)return null;try{return validateAgentId(new URL(e,`http://localhost`).searchParams.get(`connectionId`))}catch{return null}}const MAX_KEEPALIVE_IDENTITY_LEN=256;function sanitizeIdentityField(e){return e===null||e.length===0||e.length>MAX_KEEPALIVE_IDENTITY_LEN||/[-]/.test(e)?null:e}function parseKeepaliveIdentity(e){if(!e)return null;try{let t=new URL(e,`http://localhost`),s=sanitizeIdentityField(t.searchParams.get(`displayName`)),g=sanitizeIdentityField(t.searchParams.get(`clientName`)),S=sanitizeIdentityField(t.searchParams.get(`colorSeed`));return s===null||g===null||S===null?null:{displayName:s,clientName:g,colorSeed:S}}catch{return null}}const MISSING_OK_CONFIG_MESSAGE=`OpenKnowledge config not found at .ok/config.yml. Run ok init to scaffold OK in this directory.`;var MissingOkConfigError=class extends Error{kind;projectDir;constructor(e,t,s){super(MISSING_OK_CONFIG_MESSAGE,s),this.name=`MissingOkConfigError`,this.kind=e,this.projectDir=t}};async function startConfigFileWatcher(e,t){let s=getLogger(`config-file-watcher`),{watch:g}=await import(`./chokidar-Bu9Rdqzq.mjs`),S=dirname(e);try{tracedMkdirSync(S,{recursive:!0})}catch(e){e.code!==`EEXIST`&&s.warn({err:e,watchDir:S},`failed to create watch directory; watcher may be inert`)}let w=g(S,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:t=>t!==S&&t!==e});await new Promise(e=>{w.once(`ready`,e)});let E=null;try{E=readFileSync(e,`utf-8`)}catch{}let D=(g,S=!0)=>{if(g!==e)return;let w;try{w=readFileSync(g,`utf-8`)}catch(e){if(e.code===`ENOENT`){S&&s.debug({path:g},`config file disappeared between event and read; dropping`);return}s.warn({err:e,path:g},`config file read failed; dropping event`);return}if(w!==E){E=w;try{t(w)}catch(e){s.warn({err:e,path:g},`config file change handler threw`)}}},O=e=>D(e);w.on(`add`,O),w.on(`change`,O),w.on(`unlink`,t=>{t===e&&s.debug({path:t},`config file unlinked; Y.Text retained at current state`)}),w.on(`error`,t=>{s.warn({err:t,watchDir:S,absPath:e},`[config-file-watcher] chokidar error while watching ${e}`)});let k=0,j=setInterval(()=>{k++,D(e,!1),k>=20&&clearInterval(j)},500);j.unref?.();let F=!1;return async()=>{F||(F=!0,clearInterval(j),await w.close())}}async function startMultiPathConfigFileWatcher(e,t){if(e.length===0)throw Error(`startMultiPathConfigFileWatcher requires at least one absolute path`);let s=getLogger(`config-file-watcher`),{watch:g}=await import(`./chokidar-Bu9Rdqzq.mjs`),S=new Set(e),w=Array.from(new Set(Array.from(S,e=>dirname(e))));for(let e of w)try{tracedMkdirSync(e,{recursive:!0})}catch(t){t.code!==`EEXIST`&&s.warn({err:t,dir:e},`failed to create watch directory; watcher may be inert`)}let E=g(w,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:e=>!S.has(e)&&!w.includes(e)});await new Promise(e=>{E.once(`ready`,e)});let D=new Map;for(let e of S)try{D.set(e,readFileSync(e,`utf-8`))}catch{D.set(e,null)}let O=(e,g=!0)=>{if(!S.has(e))return;let w;try{w=readFileSync(e,`utf-8`)}catch(t){if(t.code===`ENOENT`){g&&s.debug({path:e},`config file disappeared between event and read; dropping`);return}s.warn({err:t,path:e},`config file read failed; dropping event`);return}if(w!==D.get(e)){D.set(e,w);try{t(e,w)}catch(t){s.warn({err:t,path:e},`config file change handler threw`)}}},k=e=>O(e);E.on(`add`,k),E.on(`change`,k),E.on(`unlink`,e=>{S.has(e)&&s.debug({path:e},`config file unlinked; downstream state retained`)}),E.on(`error`,e=>{s.warn({err:e,watchDirs:w,paths:Array.from(S)},`[config-file-watcher] chokidar error in multi-path watcher`)});let j=0,F=setInterval(()=>{j++;for(let e of S)O(e,!1);j>=20&&clearInterval(F)},500);F.unref?.();let L=!1;return async()=>{L||(L=!0,clearInterval(F),await E.close())}}function entryMatchesDocName(e,t,s,g){let S=toPosix(relative(g,join(s,e.file)));return S.startsWith(`..`)?!1:stripDocExtension(S)===t}function createConflictLifecycleSeedExtension(e){let{getSyncEngine:t,projectDir:s,contentDir:g}=e;return{async afterLoadDocument({documentName:e,document:S}){if(!(isSystemDoc(e)||isConfigDoc(e)))try{let w=t();if(!w)return;let E=w.getConflicts();if(E.length===0||!E.some(t=>entryMatchesDocName(t,e,s,g)))return;let D=S.getMap(`lifecycle`);if(D.get(`status`)===`conflict`)return;D.set(`status`,`conflict`),D.set(`reason`,`conflict-markers`),console.warn(JSON.stringify({event:`lifecycle-seeded-on-load-from-conflict-store`,"doc.name":e}))}catch(t){console.warn(`[conflict-lifecycle-seed] failed to seed lifecycle on load (doc=${e}):`,t instanceof Error?t:String(t))}}}}const execFileAsync$1=promisify(execFile),BUILTIN_SKIP_DIRS=new Set(`node_modules,.venv,venv,env,__pycache__,vendor,dist,build,out,output,.next,.nuxt,.svelte-kit,.astro,.turbo,.cache,.parcel-cache,coverage,.git,.ok,.open-knowledge,.openknowledge,.claude,.cursor,.codex,.agents,.opencode,Library,Applications,.Trash`.split(`,`)),ALWAYS_SKIP_DIRS=new Set([`.git`,`node_modules`,`.ok`,`.open-knowledge`,`.openknowledge`,`.claude`,`.cursor`,`.codex`,`.agents`,`.opencode`]);function pathHasAlwaysSkipSegment(e){for(let t of e.split(`/`))if(ALWAYS_SKIP_DIRS.has(t))return!0;return!1}function isSkillContentFile(e){return e.startsWith(`${SKILL_CONTENT_ROOT}/`)}function isSkillContentAncestorDir(e){return e===`.ok`||e===`.ok/skills`||e.startsWith(`.ok/skills/`)}function globBlocksSkillContent(e){let t=e.replace(/^\/+/,``).replace(/\/+$/,``).trim();return t===`.ok`||t===`.ok/**`||t===`**/.ok`||t===`**/.ok/**`}const BUILTIN_SKIP_FILES=new Set([`.DS_Store`,`.localized`]);function isAlwaysSkipFile(e){return BUILTIN_SKIP_FILES.has(e.slice(e.lastIndexOf(`/`)+1))}const SECRET_BEARING_DIRS=new Set([`.ssh`,`.aws`,`.gnupg`,`.kube`,`.docker`]);function pathHasSecretBearingDirSegment(e){for(let t of e.split(`/`))if(SECRET_BEARING_DIRS.has(t.toLowerCase()))return!0;return!1}const SECRET_CREDENTIAL_BASENAMES=new Set([`credentials`,`.netrc`,`.npmrc`,`.pgpass`,`.git-credentials`]),SECRET_KEY_SUFFIXES=[`.pem`,`.key`,`.p12`,`.pfx`,`.keystore`,`.jks`,`.ppk`];function isSecretBearingFile(e){let t=e.slice(e.lastIndexOf(`/`)+1).toLowerCase();if(t===`.env`||t.startsWith(`.env.`)||SECRET_CREDENTIAL_BASENAMES.has(t)||t.startsWith(`id_rsa`)||t.startsWith(`id_ed25519`)||t.startsWith(`id_ecdsa`)||t.startsWith(`id_dsa`))return!0;for(let e of SECRET_KEY_SUFFIXES)if(t.endsWith(e))return!0;return!1}function isSingleDocAncestorDir(e,t){return t===e||t.startsWith(`${e}/`)}const IGNORE_FILE_NAMES=[`.gitignore`,`.okignore`];function loadGitExcludeSources(e,t){let s=readGitCommonDirSync(e);if(s===null)return[];let g=[];appendExcludeFileIfExists(join(s,`info`,`exclude`),t,g,`info/exclude`);let S=resolveGlobalExcludesfileSync(e);return S&&appendExcludeFileIfExists(S,t,g,`global excludesfile`),g}async function loadGitExcludeSourcesAsync(e,t){let s=await readGitCommonDirAsync(e);if(s===null)return[];let g=[];await appendExcludeFileIfExistsAsync(join(s,`info`,`exclude`),t,g,`info/exclude`);let S=await resolveGlobalExcludesfileAsync(e);return S&&await appendExcludeFileIfExistsAsync(S,t,g,`global excludesfile`),g}function readGitCommonDirSync(e){let t=spawnSync(`git`,[`rev-parse`,`--git-common-dir`],{cwd:e,encoding:`utf-8`,timeout:5e3});return t.status!==0||!t.stdout?null:resolve(e,t.stdout.trim())}async function readGitCommonDirAsync(e){try{let{stdout:t}=await execFileAsync$1(`git`,[`rev-parse`,`--git-common-dir`],{cwd:e,encoding:`utf-8`,timeout:5e3});return t?resolve(e,t.trim()):null}catch{return null}}function resolveGlobalExcludesfileSync(e){let t=spawnSync(`git`,[`config`,`--get`,`--type=path`,`core.excludesfile`],{cwd:e,encoding:`utf-8`,timeout:5e3});if(t.status===0&&t.stdout){let e=t.stdout.trim();if(e)return e}return xdgGlobalIgnoreDefault()}async function resolveGlobalExcludesfileAsync(e){try{let{stdout:t}=await execFileAsync$1(`git`,[`config`,`--get`,`--type=path`,`core.excludesfile`],{cwd:e,encoding:`utf-8`,timeout:5e3}),s=t.trim();if(s)return s}catch{}return xdgGlobalIgnoreDefault()}function xdgGlobalIgnoreDefault(){let e=process.env.XDG_CONFIG_HOME?.trim();return join(e&&e.length>0?e:join(homedir(),`.config`),`git`,`ignore`)}function appendExcludeFileIfExists(e,t,s,g){if(existsSync(e))try{let g=readFileSync(e,`utf-8`);t.value+=g.length,s.push(...parseIgnorePatterns(g))}catch(t){console.warn(`[content-filter] Failed to read ${g} at ${e}:`,t)}}async function appendExcludeFileIfExistsAsync(e,t,s,g){if(existsSync(e))try{let g=await readFile$1(e,`utf-8`);t.value+=g.length,s.push(...parseIgnorePatterns(g))}catch(t){console.warn(`[content-filter] Failed to read ${g} at ${e}:`,t)}}function createContentFilter(e){let{projectDir:t,contentDir:s,onAfterRebuild:g,singleDocRelPath:S}=e,w=toPosix(relative(t,s)),E=w.startsWith(`..`),D,O,k,j=0,F=0,L=0;function B(){let e=(0,import_ignore.default)();e.add(`.git`);let g=[],S=0,B=0;for(let s of IGNORE_FILE_NAMES){let w=join(t,s);if(existsSync(w))try{let t=readFileSync(w,`utf-8`);S+=t.length;let s=parseIgnorePatterns(t);g.push(...s),e.add(s)}catch(e){console.warn(`[content-filter] Failed to read ${s} at ${w}:`,e)}}if(w&&!E)for(let t of IGNORE_FILE_NAMES){let g=join(s,t);if(existsSync(g))try{let t=readFileSync(g,`utf-8`);S+=t.length,B++;let s=parseIgnorePatterns(t).map(e=>prefixPattern(e,w));e.add(s)}catch(e){console.warn(`[content-filter] Failed to read ${t} at ${g}:`,e)}}let H={value:S};B+=loadNestedIgnoreFiles(s,t,e,H),S=H.value;let q=loadGitExcludeSources(t,H);S=H.value,q.length>0&&(g.push(...q),e.add(q));let ee=g.filter(e=>e.length>0&&!e.startsWith(`!`)&&!e.startsWith(`#`)&&!globBlocksSkillContent(e));return D=e,O=g,k=ee,j=g.length,F=B,L=S,{patternCount:j,nestedFileCount:F,bytes:L}}B();let H=new Map;function q(e){if(E)return!1;let t=w?`${w}/${e}`:e;return D.ignores(t)}let ee=()=>{S===void 0&&populateDirCount(s,``,q,H)};ee();function J(e){return isReservedForUserTree(stripDocExtension(e))}function Y(e){for(let t of e.split(`/`))if(BUILTIN_SKIP_DIRS.has(t))return!0;return E?!1:q(e)}return{isExcluded(e,t){if(J(e)||isSecretBearingFile(e)||pathHasSecretBearingDirSegment(e))return!0;if(!t?.bypassFilters&&isSkillContentFile(e)){if(S!==void 0)return e!==S;if(isSupportedDocFile(e))return!1;let t=extname(e).slice(1).toLowerCase();return!LINKABLE_ASSET_EXTENSIONS.has(t)}if(pathHasAlwaysSkipSegment(e)||isAlwaysSkipFile(e))return!0;if(S!==void 0)return e!==S;if(t?.bypassFilters)return!1;if(Y(e))return!0;if(isSupportedDocFile(e))return!1;let s=extname(e).slice(1).toLowerCase();if(LINKABLE_ASSET_EXTENSIONS.has(s)){let t=dirname(e),s=t===`.`?``:t;if((H.get(s)??0)>0)return!1}return!0},isDirExcluded(e,t){if(pathHasSecretBearingDirSegment(e))return!0;if(!t?.bypassFilters&&isSkillContentAncestorDir(e))return!1;if(pathHasAlwaysSkipSegment(e))return!0;if(S!==void 0)return!isSingleDocAncestorDir(e,S);if(t?.bypassFilters)return!1;for(let t of e.split(`/`))if(BUILTIN_SKIP_DIRS.has(t))return!0;if(E)return!1;let s=w?`${w}/${e}`:e;return D.ignores(s)||D.ignores(`${s}/`)},isPathIgnored(e,t){return J(e)||isSecretBearingFile(e)||pathHasSecretBearingDirSegment(e)?!0:isSkillContentFile(e)?!1:pathHasAlwaysSkipSegment(e)||isAlwaysSkipFile(e)?!0:t?.bypassFilters?!1:Y(e)},getWatcherIgnoreGlobs(){return k},incrementMdDir(e){let t=e===`.`?``:e;H.set(t,(H.get(t)??0)+1)},decrementMdDir(e){let t=e===`.`?``:e,s=H.get(t)??0;s<=1?H.delete(t):H.set(t,s-1)},rebuildDirCount(){let e=new Map(H);H.clear();try{ee()}catch(t){for(let[t,s]of e)H.set(t,s);getLogger(`content-filter`).warn({err:t instanceof Error?t:Error(String(t))},`content-filter rebuildDirCount walk failed — retaining previous counts`)}},async rebuildIgnorePatterns(){let e=getLogger(`content-filter`),t=D,s=O,S=k,w=j,E=F,q=L,J=Date.now();return withSpan(`config.ignore.rebuild`,{attributes:{}},async Y=>{try{let t=B();H.clear(),ee();let s=Date.now()-J;if(Y.setAttributes({"ok.ignore.pattern_count":t.patternCount,"ok.ignore.nested_file_count":t.nestedFileCount,"ok.ignore.bytes":t.bytes}),e.info({patternCount:t.patternCount,nestedFileCount:t.nestedFileCount,bytes:t.bytes,durationMs:s},`content-filter rebuild succeeded`),g)try{g()}catch(t){e.warn({err:t instanceof Error?t:Error(String(t))},`content-filter onAfterRebuild callback threw — derived views may be stale`)}return{ok:!0,patternCount:t.patternCount,nestedFileCount:t.nestedFileCount,bytes:t.bytes,durationMs:s}}catch(g){D=t,O=s,k=S,j=w,F=E,L=q,H.clear();try{ee()}catch(t){e.warn({err:t instanceof Error?t:Error(String(t))},`content-filter rollback dirCount re-walk failed — sibling-asset counts may be stale until next rebuild`)}let B=g instanceof Error?g.message:String(g);return e.warn({err:g instanceof Error?g:Error(B)},`content-filter rebuild failed — rolled back to previous state`),{ok:!1,error:{message:B}}}})}}}function populateDirCount(e,t,s,g){let S;try{S=readdirSync(e,{withFileTypes:!0})}catch(t){console.warn(`[content-filter] Failed to read directory for dir-count: ${e}`,t);return}for(let w of S){let S=t?`${t}/${w.name}`:w.name;if(w.isDirectory()){if(BUILTIN_SKIP_DIRS.has(w.name)||s(S)||s(`${S}/`))continue;populateDirCount(join(e,w.name),S,s,g)}else w.isFile()&&isSupportedDocFile(w.name)&&!s(S)&&g.set(t,(g.get(t)??0)+1)}}function parseIgnorePatterns(e){return e.split(`
3225
+ `),H,F)}async function handleBatch(e,t,s,g,S,w,E){let D=[];for(let w of e)D.push(await writeOneDoc(w,t,s,g,S));let O=D.map(e=>{if(!e.ok)return{docName:e.docName,ok:!1,error:e.error};let t=resolvePreviewUrl(e.docName,{lockDir:w}),s=parseAdvisoryWarnings(e.raw.warnings),g=parseBrokenLinks(e.raw.brokenLinks);return{docName:e.docName,ok:!0,position:e.position,...t?{previewUrl:t.url}:{},...s?{warnings:s}:{},brokenLinks:g}}),k=O.filter(e=>e.ok).length,j=k===O.length,F=e.map((e,t)=>{let s=D[t];if(!s?.ok)return`Failed ${e.path}: ${s?.error??`unknown error`}`;if(emptyAppendNoOpNote(s.position,e.content))return`No change to ${e.path} — empty ${s.position}, document unchanged.`;let g=O[t],S=[`Wrote ${e.path} (${s.position}).`];if(g?.ok&&g.warnings&&S.push(...formatAdvisoryBriefs(g.warnings)),g?.ok){let e=formatBrokenLinkBrief(g.brokenLinks);e&&S.push(e)}return S.join(` `)}),L=e.flatMap((e,t)=>{let s=D[t];if(!s?.ok)return[];let g=frontmatterIgnoredNote(s.position,e.content);return[...g?[g]:[],...s.extensionNote?[s.extensionNote]:[]].map(t=>`${e.path} — ${t}`)}),B=[`${k}/${O.length} written.`,...F,...L].join(`
3226
+ `),H={documents:O},q=D.find(e=>e.ok);return q&&q.raw.systemSubscriberCount===0&&(H.warning=buildPreviewAttachWarning(resolvePreviewUrl(q.docName,{lockDir:w}),E)),textPlusStructured(B,H,!j)}async function handleSingleDoc(e,t,s,g,S,w,E){let D=await writeOneDoc(e,t,s,g,S);if(!D.ok)return textResult(`Error: ${D.error}`,!0);let O=D.raw,k=resolvePreviewUrl(D.docName,{lockDir:w}),j=(typeof O.systemSubscriberCount==`number`?O.systemSubscriberCount:void 0)===0,F=Array.isArray(O.hints)?O.hints:void 0,L=O.summary&&typeof O.summary==`object`?O.summary:void 0,B=typeof L?.hint==`string`?L.hint:void 0,H=parseAdvisoryWarnings(O.warnings),q=parseBrokenLinks(O.brokenLinks),ee=[emptyAppendNoOpNote(D.position,e.content)??(D.fromTemplate===void 0?`Written successfully (${D.position}).`:`Written successfully (instantiated from template "${D.fromTemplate}").`)],J=frontmatterIgnoredNote(D.position,e.content);if(J&&ee.push(J),D.extensionNote&&ee.push(D.extensionNote),j&&!k&&ee.push(START_UI_TEXT_HINT),B&&ee.push(B),F)for(let e of F)e.message&&ee.push(e.message);H&&ee.push(...formatAdvisoryLines(H)),ee.push(...formatBrokenLinkLines(q));let Y=ee.join(`
3227
+ `),te={brokenLinks:q};return F&&(te.hints=F),L&&(te.summary=L),H&&(te.warnings=H),textPlusStructured(Y,nestDocResult(k,j?buildPreviewAttachWarning(k,E):void 0,te))}function register(e,t){let s={path:string().describe('Document path. The slashes are the folder it lands in; missing parent folders are created. Example: "meetings/2026-06-03-standup". An optional `.md`/`.mdx` suffix selects the file format (default `.md`); prefer the `extension` field for that. The docName itself is always extension-less.'),content:string().optional().describe("The full Markdown body. Mutually exclusive with `template`."),extension:DocExtensionArg.optional(),template:string().min(1).optional().describe("Instantiate the new doc from a folder template (resolved against the parent folder's templates_available, leaf→root walk-up; closest-wins). Mutually exclusive with `content`. Inspect the menu with an `exec` listing of the folder."),frontmatter:FrontmatterArg.optional().describe("The doc's OWN frontmatter (YAML). Written inline on create; for an existing doc prefer `edit`."),position:PositionArg.optional()};e.registerTool(`write`,{description:DESCRIPTION,inputSchema:{document:object$1(s).optional().describe(`Create or overwrite a DOCUMENT. Example: { document: { path: "meetings/standup", content: "# Standup\\n..." } }`),folder:object$1({path:string().describe(`Folder path. Example: "meetings".`),frontmatter:FrontmatterArg.optional().describe("The folder's OWN frontmatter (open-shape; `title`/`description`/`tags` are the conventional keys). Describes the folder only — does NOT flow into docs inside it.")}).optional().describe('Create a NEW folder (errors with 409 if it exists — use `edit` to change an existing folder). Example: { folder: { path: "ideas" } }'),template:object$1({path:string().describe(TEMPLATE_PATH_DESCRIBE),content:string().describe(TEMPLATE_CONTENT_DESCRIBE),frontmatter:object$1({title:string().min(1).describe(`Required — the label shown when an agent picks this template.`),description:string().optional().describe(`Optional — shown beside the title in the template menu.`),tags:array(string()).optional().describe(`Optional — tags for the template.`)}).describe("Template metadata. Only `title` (required), `description`, and `tags` are persisted (unlike open-shape doc/folder frontmatter).")}).optional().describe(`Create a TEMPLATE (a reusable starting shape for new docs in a folder). Example: { template: { path: "fishing-log/trip-log", content: "# {{date}}\\n", frontmatter: { title: "Trip Log" } } }`),skill:object$1({name:string().describe(SKILL_NAME_DESCRIBE),description:string().optional().describe(`${SKILL_DESCRIPTION_DESCRIBE} Optional when writing ONLY \`files\` into an existing skill (omit to leave SKILL.md untouched).`),body:string().optional().describe(SKILL_BODY_DESCRIBE),files:array(object$1({path:string().describe("Skill-relative path under `references/` or `scripts/`."),content:string().describe(`Full text of the bundle file.`)})).optional().describe(SKILL_FILES_DESCRIBE),scope:SkillScopeArg.optional()}).optional().describe('Create or overwrite an agent SKILL bundle (`.ok/skills/<name>/`). SKILL.md is authored via `description`+`body`; `references/**` and `scripts/**` via the `files` array. Example: { skill: { name: "trip-log", description: "Use when logging a fishing trip.", body: "# Steps\\n...", files: [{ path: "references/gear.md", content: "..." }] } }'),asset:object$1({path:string().describe(`Asset path incl. extension — the slashes are the folder. Example: "images/diagram.png".`),content:string().optional().describe(`Base64 of the binary. Use for small files.`),source:string().optional().describe(`Local filesystem path the server reads. Use for large files.`)}).optional().describe("Upload a binary asset (image/file) via the media route. Exactly one of `content` | `source`."),documents:array(object$1({...s,summary:summaryArgSchema})).min(1).optional().describe("Batch: documents to write in one call. Mutually exclusive with the single targets. Each entry may carry its own `summary`."),summary:summaryArgSchema,cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:outputSchemaWithText({document:object$1({hints:looseObjectArray.optional().describe(`Server-provided write hints, when any.`),...documentResultBaseShape}).optional().describe("Single-document write result. Always present on a successful single-doc write — it carries `brokenLinks` (possibly `[]`) plus any `summary`/`hints`/`warnings`."),folder:object$1({ok:boolean(),path:string(),frontmatterError:string().optional().describe("Present when the folder was created but its frontmatter write failed — retry only the properties via `edit({ folder: { frontmatter } })`.")}).optional().describe(`Folder-create result.`),template:object$1({ok:boolean(),path:string(),created:boolean().describe(`true if created, false if an existing template updated.`)}).optional().describe(`Template-create result.`),skill:object$1({ok:boolean(),path:string().optional(),created:boolean().optional().describe(`true if created, false if an existing skill was overwritten.`),files:looseObjectArray.optional().describe("Per-bundle-file results `{ path, kind, created, ok, error? }`.")}).optional().describe(`Skill-create result (SKILL.md and/or bundle files).`),asset:object$1({ok:boolean(),src:string().optional().describe(`The reference src to embed in a doc.`),path:string().optional(),deduped:boolean().optional().describe(`true when identical bytes already existed (no new file written).`)}).optional().describe(`Asset-upload result.`),documents:looseObjectArray.optional().describe("Batch write: per-doc result `{ docName, ok, position?, previewUrl?, warnings?, brokenLinks, error? }`. `brokenLinks` (possibly `[]`) is present on each successful entry, same as a single-doc write."),previewUrl:previewUrlOutputField.optional(),previewUrlSource:previewUrlSourceField,warning:previewAttachWarningField})},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,config:S,url:w}=s,E=resolveLockDir(g),D=resolveContentDir(S,g),O=S.appearance.preview.autoOpen;if(e.documents!==void 0){let s=exactlyOneTargetError(e,[`document`,`folder`,`template`,`skill`,`asset`,`documents`]);return s?textResult(`Error: ${s}`,!0):w?handleBatch(e.documents,g,D,w,t,E,O):textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0)}let k=exactlyOneTargetError(e,[`document`,`folder`,`template`,`skill`,`asset`]);return k?textResult(`Error: ${k}`,!0):e.document===void 0?e.folder===void 0?e.template===void 0?e.skill===void 0?handleAsset(e.asset,g,w,t):handleSkillWrite(e.skill,e.summary,w,t,E):handleTemplate(e.template,e.summary,w,t):handleFolder(e.folder,e.summary,w,t):w?handleSingleDoc({...e.document,summary:e.summary},g,D,w,t,E,O):textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0)})}function registerAllTools(e,t){let s=t.logger,g=createLoggedServer(e,{logger:t.logger,identityRef:t.identityRef}),S=e=>async g=>{try{let S=await t.resolveCwd(g);return(getCurrentMcpLogger()??s)?.debug(`tool cwd resolved`,{tool:e,cwd:S,...g?{explicit:g}:{}}),S}catch(t){throw(getCurrentMcpLogger()??s)?.warn(`tool call failed`,{tool:e,error:t instanceof Error?t.message:String(t),...g?{explicit:g}:{}}),t}};register$13(g,{resolveCwd:S(`exec`),serverUrl:t.serverUrl,config:t.config}),register$1(g,{config:t.config,resolveCwd:S(`workflow`)}),register$4(g,{resolveCwd:S(`search`),config:t.config,serverUrl:t.serverUrl}),register$9(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`links`)}),register(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`write`),identityRef:t.identityRef}),register$14(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`edit`),identityRef:t.identityRef}),register$15(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`delete`),identityRef:t.identityRef}),register$8(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`move`),identityRef:t.identityRef}),register$10(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`install`),identityRef:t.identityRef}),register$11(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`history`)}),register$2(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`skills`)}),register$18(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`checkpoint`),identityRef:t.identityRef}),register$5(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`restore_version`),identityRef:t.identityRef}),register$7(g,{resolveCwd:S(`palette`),config:t.config}),register$17(g,{config:t.config,resolveCwd:S(`config`)}),register$12(g,{config:t.config,resolveCwd:S(`preview_url`),serverUrl:t.serverUrl}),register$16(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`conflicts`)}),register$6(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`resolve_conflict`)}),register$3(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`share_link`)})}function firstHeader(e){return Array.isArray(e)?e[0]:e}function writePlain(e,t,s){e.writableEnded||(e.statusCode=t,e.setHeader(`Content-Type`,`text/plain; charset=utf-8`),e.end(s))}function createSessionServer(e,t,s){let g=e.config,S=new McpServer({name:MCP_SERVER_NAME,version:RUNTIME_VERSION});installPrettyZodErrors(S);let w=s??randomUUID$1(),E={current:{connectionId:w,displayName:w,colorSeed:w}};S.server.oninitialized=()=>{let e=S.server.getClientVersion(),t=sanitizeClientName(e?.name,w);E.current={connectionId:w,clientInfo:e?{name:t,version:e.version}:void 0,displayName:displayNameFromClientName(t),colorSeed:t}};let D=e.projectDir??e.contentDir;return registerAllTools(S,{serverUrl:async()=>e.getServerUrl(),resolveCwd:async e=>{if(e===void 0)return D;let t=resolveWithinRoot(D,e);if(!t.ok)throw Error(`cwd "${e}" is not within the configured project root: ${t.reason}`);return t.abs},config:g,identityRef:E}),{server:S,transport:t}}function createMcpHttpHandler(e){let t=new Map,s=e.sessionTtlMs??1800*1e3,g=e.maxSessions??100;async function S(s,g){let S=t.get(s);if(!S)return;t.delete(s),S.ttlTimer!==void 0&&clearTimeout(S.ttlTimer);let w=await Promise.allSettled([S.server.close(),S.transport.close()]);for(let t of w)t.status===`rejected`&&e.log?.warn?.({err:t.reason,sessionId:s,reason:g},`MCP HTTP session close failed`);e.log?.info?.({sessionId:s,reason:g},`MCP HTTP session closed`)}function w(t,g){g.ttlTimer!==void 0&&clearTimeout(g.ttlTimer),g.ttlTimer=setTimeout(()=>{S(t,`ttl-expired`).catch(s=>{e.log?.warn?.({err:s,sessionId:t},`MCP HTTP session TTL cleanup failed`)})},s),g.ttlTimer.unref?.()}return{async handle(s,E){let D=firstHeader(s.headers[`mcp-session-id`]);if(D){let e=t.get(D);if(!e){writePlain(E,404,`MCP session not found`);return}w(D,e),await e.transport.handleRequest(s,E);return}if(s.method!==`POST`){writePlain(E,400,`Missing MCP session. Initialize with POST /mcp first.`);return}if(t.size>=g){e.log?.warn?.({activeSessions:t.size,maxSessions:g},`MCP HTTP session cap reached`),writePlain(E,503,`Too many active MCP sessions`);return}let O=firstHeader(s.headers[MCP_CONNECTION_ID_HEADER]),k=validateAgentId(O)??void 0;O!==void 0&&k===void 0&&e.log?.warn?.({headerLength:O.length},`MCP HTTP forwarded connectionId header failed validation; falling back to randomUUID`);let j=new StreamableHTTPServerTransport({sessionIdGenerator:()=>randomUUID$1(),enableJsonResponse:!0,onsessioninitialized:async s=>{try{let g=createSessionServer(e,j,k);await g.server.connect(j),t.set(s,g),w(s,g),e.log?.info?.({sessionId:s},`MCP HTTP session initialized`)}catch(g){throw t.delete(s),e.log?.error?.({err:g,sessionId:s},`MCP HTTP session initialization failed`),g}}});j.onerror=t=>{e.log?.warn?.({err:t},`MCP HTTP transport error`)},j.onclose=()=>{let t=j.sessionId;if(!t){e.log?.info?.({sessionId:t,reason:`transport-closed`},`MCP HTTP session closed`);return}S(t,`transport-closed`).catch(s=>{e.log?.warn?.({err:s,sessionId:t},`MCP HTTP transport-close cleanup failed`)})},await j.handleRequest(s,E)},async close(){let e=[...t.entries()];await Promise.allSettled(e.map(([e])=>S(e,`handler-close`)))}}}const DEFAULT_KEEPALIVE_GRACE_MS=1e4,MAX_COLLAB_MESSAGE_BYTES=1024*1024,MCP_CORS_HEADERS={"Access-Control-Allow-Methods":`GET, POST, DELETE, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type, Authorization, traceparent, tracestate, baggage, mcp-session-id, mcp-protocol-version`,"Access-Control-Max-Age":`86400`};function mountMcpAndApi(e){let{httpServer:t,hocuspocus:s,mcpHttpHandler:g,log:S,sessionManager:w,agentFocusBroadcaster:E,agentPresenceBroadcaster:D,maintenanceCoordinator:O,contentAssetMiddleware:k,reactShellMiddleware:j,ephemeral:F}=e,L=e.keepaliveGraceMs??DEFAULT_KEEPALIVE_GRACE_MS,B=new import_websocket_server$1.default({noServer:!0,maxPayload:MAX_COLLAB_MESSAGE_BYTES});B.on(`error`,e=>{S.error({err:e},`WebSocketServer error`)});let H=new Map,q=new Set,ee=new Set,J=!1;return t.on(`request`,(e,t)=>{let w=e.url?.split(`?`)[0];if(g!==void 0&&w===`/mcp`){let s=e.headers.origin,w=Array.isArray(e.headers[`mcp-session-id`])?e.headers[`mcp-session-id`][0]:e.headers[`mcp-session-id`];if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback access required.`,{handler:`mcp`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`mcp`});return}if(s!==void 0&&!isAllowedApiOrigin(s)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`mcp`});return}s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`));for(let[e,s]of Object.entries(MCP_CORS_HEADERS))t.setHeader(e,s);if(e.method===`OPTIONS`){t.writeHead(204),t.end();return}g.handle(e,t).catch(e=>{S.error({err:e,sessionId:w},`Unhandled MCP HTTP error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp`,cause:e}):t.writableEnded||t.end()});return}if(w?.startsWith(`/api/`)){s.hooks(`onRequest`,{request:e,response:t}).then(()=>{t.writableEnded||t.headersSent||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`mcp-mount`,detail:`No handler for ${e.method??`GET`} ${w}`})}).catch(e=>{S.error({err:e},`Unhandled onRequest error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()});return}let E=(s,g,w)=>{if(s===void 0){w();return}try{s(e,t,()=>{t.writableEnded||t.headersSent||w()})}catch(e){S.error({err:e},`Unhandled ${g} middleware error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()}},D=s=>{if(F===!0&&k!==void 0&&(!isLoopbackAddress(e.socket.remoteAddress)||!isAllowedWorkspaceHostHeader(e.headers.host))){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback access required.`,{handler:`content-asset`});return}E(k,`content-asset`,s)},O=e=>E(j,`react-shell`,e),L=()=>{t.writableEnded||t.headersSent||errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`No handler for ${w??`/`}`})};if(j!==void 0&&w?.startsWith(`/assets/`)){O(()=>D(L));return}if(k!==void 0||j!==void 0){D(()=>O(L));return}errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`The React UI is served by \`ok ui\` (run \`ok ui\` and check \`ui.lock.port\`). No handler for ${w??`/`}`})}),t.on(`upgrade`,(e,t,g)=>{if(e.url?.startsWith(`/collab/keepalive`)){if(!isLoopbackAddress(e.socket.remoteAddress)||!isAllowedWorkspaceHostHeader(e.headers.host)){t.destroy();return}t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`MCP keepalive socket error`)}),ee.add(t),t.once(`close`,()=>ee.delete(t)),B.handleUpgrade(e,t,g,t=>{let s=parseKeepaliveConnectionId(e.url);if(s){let e=H.get(s);e!==void 0&&(clearTimeout(e),H.delete(s),S.info({connectionId:s},`[keepalive] reconnect during grace — timer cancelled`))}if(s&&D){let t=parseKeepaliveIdentity(e.url);if(t)try{let e=iconFromClientName(t.clientName),g=AGENT_ICON_COLORS[e]??colorFromSeed(t.colorSeed);D.setPresence(toBroadcasterKey(s),{displayName:t.displayName,icon:e,color:g,currentDoc:`(connected)`,mode:`idle`,ts:Date.now()})}catch(e){S.error({err:e,connectionId:s},`[keepalive] presence bootstrap failed`)}}let g=setInterval(()=>{try{t.ping()}catch{}},3e4);g.unref?.();let k=s?setInterval(()=>{D?.bumpPresenceTs(toBroadcasterKey(s))},3e3):null;k?.unref?.(),t.on(`close`,()=>{if(clearInterval(g),k!==null&&clearInterval(k),!s)return;let e=setTimeout(()=>{if(H.delete(s),J)return;let e=(async()=>{S.info({connectionId:s},`[keepalive] grace expired — cleaning up sessions`);try{await w?.closeAllForAgent(s)}catch(e){S.error({err:e,connectionId:s},`[keepalive] closeAllForAgent failed`)}try{E?.clearFocus(s)}catch(e){S.error({err:e,connectionId:s},`[keepalive] clearFocus failed`)}try{D?.clearPresence(toBroadcasterKey(s))}catch(e){S.error({err:e,connectionId:s},`[keepalive] clearPresence failed`)}try{await O?.onSessionClose()}catch(e){S.error({err:e,connectionId:s},`[keepalive] maintenance onSessionClose failed`)}})();q.add(e),e.finally(()=>q.delete(e))},L);e.unref?.(),H.set(s,e),S.info({connectionId:s,graceMs:L},`[keepalive] disconnected — grace timer started`)}),t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`MCP keepalive WS error`),t.terminate()})});return}if(e.url?.startsWith(`/collab`)){t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`Upgrade socket error`)}),ee.add(t),t.once(`close`,()=>ee.delete(t)),B.handleUpgrade(e,t,g,t=>{let g=s.handleConnection(t,e),w=!1;t.on(`message`,e=>{if(w)return;let s=e.byteLength;if(s>MAX_COLLAB_MESSAGE_BYTES){w=!0,incrementCollabMessageTooLarge(),S.warn({event:`collab-message-too-large`,bytes:s,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket message rejected before Yjs processing`),t.close(1009,`Message Too Big`);return}g.handleMessage(new Uint8Array(e))}),t.on(`close`,(e,t)=>{g.handleClose({code:e,reason:t.toString()})}),t.on(`error`,e=>{if(e.code===`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`){incrementCollabMessageTooLarge(),S.warn({event:`collab-message-too-large`,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket frame rejected by ws maxPayload before Yjs processing`),t.terminate();return}handleCollabSocketError(e)||S.error({err:e},`WebSocket error`),t.terminate()})});return}t.destroy()}),{wss:B,shutdown:async()=>{if(!J){J=!0;for(let e of ee)try{e.destroy()}catch{}ee.clear();for(let e of H.values())clearTimeout(e);H.clear(),q.size>0&&await Promise.allSettled(q)}}}}function parseKeepaliveConnectionId(e){if(!e)return null;try{return validateAgentId(new URL(e,`http://localhost`).searchParams.get(`connectionId`))}catch{return null}}const MAX_KEEPALIVE_IDENTITY_LEN=256;function sanitizeIdentityField(e){return e===null||e.length===0||e.length>MAX_KEEPALIVE_IDENTITY_LEN||/[-]/.test(e)?null:e}function parseKeepaliveIdentity(e){if(!e)return null;try{let t=new URL(e,`http://localhost`),s=sanitizeIdentityField(t.searchParams.get(`displayName`)),g=sanitizeIdentityField(t.searchParams.get(`clientName`)),S=sanitizeIdentityField(t.searchParams.get(`colorSeed`));return s===null||g===null||S===null?null:{displayName:s,clientName:g,colorSeed:S}}catch{return null}}const MISSING_OK_CONFIG_MESSAGE=`OpenKnowledge config not found at .ok/config.yml. Run ok init to scaffold OK in this directory.`;var MissingOkConfigError=class extends Error{kind;projectDir;constructor(e,t,s){super(MISSING_OK_CONFIG_MESSAGE,s),this.name=`MissingOkConfigError`,this.kind=e,this.projectDir=t}};async function startConfigFileWatcher(e,t){let s=getLogger(`config-file-watcher`),{watch:g}=await import(`./chokidar-Bu9Rdqzq.mjs`),S=dirname(e);try{tracedMkdirSync(S,{recursive:!0})}catch(e){e.code!==`EEXIST`&&s.warn({err:e,watchDir:S},`failed to create watch directory; watcher may be inert`)}let w=g(S,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:t=>t!==S&&t!==e});await new Promise(e=>{w.once(`ready`,e)});let E=null;try{E=readFileSync(e,`utf-8`)}catch{}let D=(g,S=!0)=>{if(g!==e)return;let w;try{w=readFileSync(g,`utf-8`)}catch(e){if(e.code===`ENOENT`){S&&s.debug({path:g},`config file disappeared between event and read; dropping`);return}s.warn({err:e,path:g},`config file read failed; dropping event`);return}if(w!==E){E=w;try{t(w)}catch(e){s.warn({err:e,path:g},`config file change handler threw`)}}},O=e=>D(e);w.on(`add`,O),w.on(`change`,O),w.on(`unlink`,t=>{t===e&&s.debug({path:t},`config file unlinked; Y.Text retained at current state`)}),w.on(`error`,t=>{s.warn({err:t,watchDir:S,absPath:e},`[config-file-watcher] chokidar error while watching ${e}`)});let k=0,j=setInterval(()=>{k++,D(e,!1),k>=20&&clearInterval(j)},500);j.unref?.();let F=!1;return async()=>{F||(F=!0,clearInterval(j),await w.close())}}async function startMultiPathConfigFileWatcher(e,t){if(e.length===0)throw Error(`startMultiPathConfigFileWatcher requires at least one absolute path`);let s=getLogger(`config-file-watcher`),{watch:g}=await import(`./chokidar-Bu9Rdqzq.mjs`),S=new Set(e),w=Array.from(new Set(Array.from(S,e=>dirname(e))));for(let e of w)try{tracedMkdirSync(e,{recursive:!0})}catch(t){t.code!==`EEXIST`&&s.warn({err:t,dir:e},`failed to create watch directory; watcher may be inert`)}let E=g(w,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:e=>!S.has(e)&&!w.includes(e)});await new Promise(e=>{E.once(`ready`,e)});let D=new Map;for(let e of S)try{D.set(e,readFileSync(e,`utf-8`))}catch{D.set(e,null)}let O=(e,g=!0)=>{if(!S.has(e))return;let w;try{w=readFileSync(e,`utf-8`)}catch(t){if(t.code===`ENOENT`){g&&s.debug({path:e},`config file disappeared between event and read; dropping`);return}s.warn({err:t,path:e},`config file read failed; dropping event`);return}if(w!==D.get(e)){D.set(e,w);try{t(e,w)}catch(t){s.warn({err:t,path:e},`config file change handler threw`)}}},k=e=>O(e);E.on(`add`,k),E.on(`change`,k),E.on(`unlink`,e=>{S.has(e)&&s.debug({path:e},`config file unlinked; downstream state retained`)}),E.on(`error`,e=>{s.warn({err:e,watchDirs:w,paths:Array.from(S)},`[config-file-watcher] chokidar error in multi-path watcher`)});let j=0,F=setInterval(()=>{j++;for(let e of S)O(e,!1);j>=20&&clearInterval(F)},500);F.unref?.();let L=!1;return async()=>{L||(L=!0,clearInterval(F),await E.close())}}function entryMatchesDocName(e,t,s,g){let S=toPosix(relative(g,join(s,e.file)));return S.startsWith(`..`)?!1:stripDocExtension(S)===t}function createConflictLifecycleSeedExtension(e){let{getSyncEngine:t,projectDir:s,contentDir:g}=e;return{async afterLoadDocument({documentName:e,document:S}){if(!(isSystemDoc(e)||isConfigDoc(e)))try{let w=t();if(!w)return;let E=w.getConflicts();if(E.length===0||!E.some(t=>entryMatchesDocName(t,e,s,g)))return;let D=S.getMap(`lifecycle`);if(D.get(`status`)===`conflict`)return;D.set(`status`,`conflict`),D.set(`reason`,`conflict-markers`),console.warn(JSON.stringify({event:`lifecycle-seeded-on-load-from-conflict-store`,"doc.name":e}))}catch(t){console.warn(`[conflict-lifecycle-seed] failed to seed lifecycle on load (doc=${e}):`,t instanceof Error?t:String(t))}}}}const execFileAsync$1=promisify(execFile),BUILTIN_SKIP_DIRS=new Set(`node_modules,.venv,venv,env,__pycache__,vendor,dist,build,out,output,.next,.nuxt,.svelte-kit,.astro,.turbo,.cache,.parcel-cache,coverage,.git,.ok,.open-knowledge,.openknowledge,.claude,.cursor,.codex,.agents,.opencode,Library,Applications,.Trash`.split(`,`)),ALWAYS_SKIP_DIRS=new Set([`.git`,`node_modules`,`.ok`,`.open-knowledge`,`.openknowledge`,`.claude`,`.cursor`,`.codex`,`.agents`,`.opencode`]);function pathHasAlwaysSkipSegment(e){for(let t of e.split(`/`))if(ALWAYS_SKIP_DIRS.has(t))return!0;return!1}function isSkillContentFile(e){return e.startsWith(`${SKILL_CONTENT_ROOT}/`)}function isSkillContentAncestorDir(e){return e===`.ok`||e===`.ok/skills`||e.startsWith(`.ok/skills/`)}function globBlocksSkillContent(e){let t=e.replace(/^\/+/,``).replace(/\/+$/,``).trim();return t===`.ok`||t===`.ok/**`||t===`**/.ok`||t===`**/.ok/**`}const BUILTIN_SKIP_FILES=new Set([`.DS_Store`,`.localized`]);function isAlwaysSkipFile(e){return BUILTIN_SKIP_FILES.has(e.slice(e.lastIndexOf(`/`)+1))}const SECRET_BEARING_DIRS=new Set([`.ssh`,`.aws`,`.gnupg`,`.kube`,`.docker`]);function pathHasSecretBearingDirSegment(e){for(let t of e.split(`/`))if(SECRET_BEARING_DIRS.has(t.toLowerCase()))return!0;return!1}const SECRET_CREDENTIAL_BASENAMES=new Set([`credentials`,`.netrc`,`.npmrc`,`.pgpass`,`.git-credentials`]),SECRET_KEY_SUFFIXES=[`.pem`,`.key`,`.p12`,`.pfx`,`.keystore`,`.jks`,`.ppk`];function isSecretBearingFile(e){let t=e.slice(e.lastIndexOf(`/`)+1).toLowerCase();if(t===`.env`||t.startsWith(`.env.`)||SECRET_CREDENTIAL_BASENAMES.has(t)||t.startsWith(`id_rsa`)||t.startsWith(`id_ed25519`)||t.startsWith(`id_ecdsa`)||t.startsWith(`id_dsa`))return!0;for(let e of SECRET_KEY_SUFFIXES)if(t.endsWith(e))return!0;return!1}function isSingleDocAncestorDir(e,t){return t===e||t.startsWith(`${e}/`)}const IGNORE_FILE_NAMES=[`.gitignore`,`.okignore`];function loadGitExcludeSources(e,t){let s=readGitCommonDirSync(e);if(s===null)return[];let g=[];appendExcludeFileIfExists(join(s,`info`,`exclude`),t,g,`info/exclude`);let S=resolveGlobalExcludesfileSync(e);return S&&appendExcludeFileIfExists(S,t,g,`global excludesfile`),g}async function loadGitExcludeSourcesAsync(e,t){let s=await readGitCommonDirAsync(e);if(s===null)return[];let g=[];await appendExcludeFileIfExistsAsync(join(s,`info`,`exclude`),t,g,`info/exclude`);let S=await resolveGlobalExcludesfileAsync(e);return S&&await appendExcludeFileIfExistsAsync(S,t,g,`global excludesfile`),g}function readGitCommonDirSync(e){let t=spawnSync(`git`,[`rev-parse`,`--git-common-dir`],{cwd:e,encoding:`utf-8`,timeout:5e3});return t.status!==0||!t.stdout?null:resolve(e,t.stdout.trim())}async function readGitCommonDirAsync(e){try{let{stdout:t}=await execFileAsync$1(`git`,[`rev-parse`,`--git-common-dir`],{cwd:e,encoding:`utf-8`,timeout:5e3});return t?resolve(e,t.trim()):null}catch{return null}}function resolveGlobalExcludesfileSync(e){let t=spawnSync(`git`,[`config`,`--get`,`--type=path`,`core.excludesfile`],{cwd:e,encoding:`utf-8`,timeout:5e3});if(t.status===0&&t.stdout){let e=t.stdout.trim();if(e)return e}return xdgGlobalIgnoreDefault()}async function resolveGlobalExcludesfileAsync(e){try{let{stdout:t}=await execFileAsync$1(`git`,[`config`,`--get`,`--type=path`,`core.excludesfile`],{cwd:e,encoding:`utf-8`,timeout:5e3}),s=t.trim();if(s)return s}catch{}return xdgGlobalIgnoreDefault()}function xdgGlobalIgnoreDefault(){let e=process.env.XDG_CONFIG_HOME?.trim();return join(e&&e.length>0?e:join(homedir(),`.config`),`git`,`ignore`)}function appendExcludeFileIfExists(e,t,s,g){if(existsSync(e))try{let g=readFileSync(e,`utf-8`);t.value+=g.length,s.push(...parseIgnorePatterns(g))}catch(t){console.warn(`[content-filter] Failed to read ${g} at ${e}:`,t)}}async function appendExcludeFileIfExistsAsync(e,t,s,g){if(existsSync(e))try{let g=await readFile$1(e,`utf-8`);t.value+=g.length,s.push(...parseIgnorePatterns(g))}catch(t){console.warn(`[content-filter] Failed to read ${g} at ${e}:`,t)}}function createContentFilter(e){let{projectDir:t,contentDir:s,onAfterRebuild:g,singleDocRelPath:S}=e,w=toPosix(relative(t,s)),E=w.startsWith(`..`),D,O,k,j=0,F=0,L=0;function B(){let e=(0,import_ignore.default)();e.add(`.git`);let g=[],S=0,B=0;for(let s of IGNORE_FILE_NAMES){let w=join(t,s);if(existsSync(w))try{let t=readFileSync(w,`utf-8`);S+=t.length;let s=parseIgnorePatterns(t);g.push(...s),e.add(s)}catch(e){console.warn(`[content-filter] Failed to read ${s} at ${w}:`,e)}}if(w&&!E)for(let t of IGNORE_FILE_NAMES){let g=join(s,t);if(existsSync(g))try{let t=readFileSync(g,`utf-8`);S+=t.length,B++;let s=parseIgnorePatterns(t).map(e=>prefixPattern(e,w));e.add(s)}catch(e){console.warn(`[content-filter] Failed to read ${t} at ${g}:`,e)}}let H={value:S};B+=loadNestedIgnoreFiles(s,t,e,H),S=H.value;let q=loadGitExcludeSources(t,H);S=H.value,q.length>0&&(g.push(...q),e.add(q));let ee=g.filter(e=>e.length>0&&!e.startsWith(`!`)&&!e.startsWith(`#`)&&!globBlocksSkillContent(e));return D=e,O=g,k=ee,j=g.length,F=B,L=S,{patternCount:j,nestedFileCount:F,bytes:L}}B();let H=new Map;function q(e){if(E)return!1;let t=w?`${w}/${e}`:e;return D.ignores(t)}let ee=()=>{S===void 0&&populateDirCount(s,``,q,H)};ee();function J(e){return isReservedForUserTree(stripDocExtension(e))}function Y(e){for(let t of e.split(`/`))if(BUILTIN_SKIP_DIRS.has(t))return!0;return E?!1:q(e)}return{isExcluded(e,t){if(J(e)||isSecretBearingFile(e)||pathHasSecretBearingDirSegment(e))return!0;if(!t?.bypassFilters&&isSkillContentFile(e)){if(S!==void 0)return e!==S;if(isSupportedDocFile(e))return!1;let t=extname(e).slice(1).toLowerCase();return!LINKABLE_ASSET_EXTENSIONS.has(t)}if(pathHasAlwaysSkipSegment(e)||isAlwaysSkipFile(e))return!0;if(S!==void 0)return e!==S;if(t?.bypassFilters)return!1;if(Y(e))return!0;if(isSupportedDocFile(e))return!1;let s=extname(e).slice(1).toLowerCase();if(LINKABLE_ASSET_EXTENSIONS.has(s)){let t=dirname(e),s=t===`.`?``:t;if((H.get(s)??0)>0)return!1}return!0},isDirExcluded(e,t){if(pathHasSecretBearingDirSegment(e))return!0;if(!t?.bypassFilters&&isSkillContentAncestorDir(e))return!1;if(pathHasAlwaysSkipSegment(e))return!0;if(S!==void 0)return!isSingleDocAncestorDir(e,S);if(t?.bypassFilters)return!1;for(let t of e.split(`/`))if(BUILTIN_SKIP_DIRS.has(t))return!0;if(E)return!1;let s=w?`${w}/${e}`:e;return D.ignores(s)||D.ignores(`${s}/`)},isPathIgnored(e,t){return J(e)||isSecretBearingFile(e)||pathHasSecretBearingDirSegment(e)?!0:isSkillContentFile(e)?!1:pathHasAlwaysSkipSegment(e)||isAlwaysSkipFile(e)?!0:t?.bypassFilters?!1:Y(e)},getWatcherIgnoreGlobs(){return k},incrementMdDir(e){let t=e===`.`?``:e;H.set(t,(H.get(t)??0)+1)},decrementMdDir(e){let t=e===`.`?``:e,s=H.get(t)??0;s<=1?H.delete(t):H.set(t,s-1)},rebuildDirCount(){let e=new Map(H);H.clear();try{ee()}catch(t){for(let[t,s]of e)H.set(t,s);getLogger(`content-filter`).warn({err:t instanceof Error?t:Error(String(t))},`content-filter rebuildDirCount walk failed — retaining previous counts`)}},async rebuildIgnorePatterns(){let e=getLogger(`content-filter`),t=D,s=O,S=k,w=j,E=F,q=L,J=Date.now();return withSpan(`config.ignore.rebuild`,{attributes:{}},async Y=>{try{let t=B();H.clear(),ee();let s=Date.now()-J;if(Y.setAttributes({"ok.ignore.pattern_count":t.patternCount,"ok.ignore.nested_file_count":t.nestedFileCount,"ok.ignore.bytes":t.bytes}),e.info({patternCount:t.patternCount,nestedFileCount:t.nestedFileCount,bytes:t.bytes,durationMs:s},`content-filter rebuild succeeded`),g)try{g()}catch(t){e.warn({err:t instanceof Error?t:Error(String(t))},`content-filter onAfterRebuild callback threw — derived views may be stale`)}return{ok:!0,patternCount:t.patternCount,nestedFileCount:t.nestedFileCount,bytes:t.bytes,durationMs:s}}catch(g){D=t,O=s,k=S,j=w,F=E,L=q,H.clear();try{ee()}catch(t){e.warn({err:t instanceof Error?t:Error(String(t))},`content-filter rollback dirCount re-walk failed — sibling-asset counts may be stale until next rebuild`)}let B=g instanceof Error?g.message:String(g);return e.warn({err:g instanceof Error?g:Error(B)},`content-filter rebuild failed — rolled back to previous state`),{ok:!1,error:{message:B}}}})}}}function populateDirCount(e,t,s,g){let S;try{S=readdirSync(e,{withFileTypes:!0})}catch(t){console.warn(`[content-filter] Failed to read directory for dir-count: ${e}`,t);return}for(let w of S){let S=t?`${t}/${w.name}`:w.name;if(w.isDirectory()){if(BUILTIN_SKIP_DIRS.has(w.name)||s(S)||s(`${S}/`))continue;populateDirCount(join(e,w.name),S,s,g)}else w.isFile()&&isSupportedDocFile(w.name)&&!s(S)&&g.set(t,(g.get(t)??0)+1)}}function parseIgnorePatterns(e){return e.split(`
3224
3228
  `).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`#`))}function prefixPattern(e,t){let s=e.startsWith(`!`),g=s?e.slice(1):e,S=g.startsWith(`/`)?g.slice(1):g,w=S.endsWith(`/`)?S.slice(0,-1):S,E=g.startsWith(`/`)||w.includes(`/`)?`${t}/${S}`:`${t}/**/${S}`;return s?`!${E}`:E}function loadNestedIgnoreFiles(e,t,s,g){let S;try{S=readdirSync(e,{withFileTypes:!0})}catch(t){return console.warn(`[content-filter] Failed to read directory ${e}:`,t),0}let w=0;for(let E of S){if(!E.isDirectory()||BUILTIN_SKIP_DIRS.has(E.name))continue;let S=join(e,E.name),D=toPosix(relative(t,S));if(!D.startsWith(`..`)&&!(s.ignores(D)||s.ignores(`${D}/`))){for(let e of IGNORE_FILE_NAMES){let t=join(S,e);if(existsSync(t))try{let e=readFileSync(t,`utf-8`);g.value+=e.length;let S=parseIgnorePatterns(e).map(e=>prefixPattern(e,D));s.add(S),w++}catch(s){console.warn(`[content-filter] Failed to read nested ${e} at ${t}:`,s)}}w+=loadNestedIgnoreFiles(S,t,s,g)}}return w}async function initContentDirStateAsync(e,t,s,g,S,w,E){let D;try{D=await readdir(e,{withFileTypes:!0})}catch(t){console.warn(`[content-filter] Failed to read directory ${e}:`,t);return}for(let O of D){let D=t?`${t}/${O.name}`:O.name;if(O.isDirectory()){if(BUILTIN_SKIP_DIRS.has(O.name))continue;let t=join(e,O.name);if(!w){let e=toPosix(relative(s,t));if(e.startsWith(`..`)||g.ignores(e)||g.ignores(`${e}/`))continue;for(let s of IGNORE_FILE_NAMES){let S=join(t,s);if(existsSync(S))try{let t=parseIgnorePatterns(await readFile$1(S,`utf-8`));g.add(t.map(t=>prefixPattern(t,e)))}catch(e){console.warn(`[content-filter] Failed to read nested ${s} at ${S}:`,e)}}}await initContentDirStateAsync(t,D,s,g,S,w,E)}else if(O.isFile()&&isSupportedDocFile(O.name)){if(!w){let e=S?`${S}/${D}`:D;if(g.ignores(e))continue}E.set(t,(E.get(t)??0)+1)}}}async function createContentFilterAsync(e){let{projectDir:t,contentDir:s,onAfterRebuild:g,singleDocRelPath:S}=e,w=toPosix(relative(t,s)),E=w.startsWith(`..`),D=(0,import_ignore.default)(),O=[],k=new Map,j=()=>{S===void 0&&populateDirCount(s,``,F,k)};function F(e){if(E)return!1;let t=w?`${w}/${e}`:e;return D.ignores(t)}function L(e){return isReservedForUserTree(stripDocExtension(e))}function B(e){for(let t of e.split(`/`))if(BUILTIN_SKIP_DIRS.has(t))return!0;return E?!1:F(e)}async function H(){let e=(0,import_ignore.default)();e.add(`.git`);let g=[];for(let s of IGNORE_FILE_NAMES){let S=join(t,s);if(existsSync(S))try{let t=parseIgnorePatterns(await readFile$1(S,`utf-8`));g.push(...t),e.add(t)}catch(e){console.warn(`[content-filter] Failed to read ${s} at ${S}:`,e)}}if(w&&!E)for(let t of IGNORE_FILE_NAMES){let g=join(s,t);if(existsSync(g))try{let t=parseIgnorePatterns(await readFile$1(g,`utf-8`));e.add(t.map(e=>prefixPattern(e,w)))}catch(e){console.warn(`[content-filter] Failed to read ${t} at ${g}:`,e)}}let j=await loadGitExcludeSourcesAsync(t,{value:0});j.length>0&&(g.push(...j),e.add(j));let F=new Map;S===void 0&&await initContentDirStateAsync(s,``,t,e,w,E,F),D=e,O=g.filter(e=>e.length>0&&!e.startsWith(`!`)&&!e.startsWith(`#`)&&!globBlocksSkillContent(e)),k.clear();for(let[e,t]of F)k.set(e,t)}return await H(),{isExcluded(e,t){if(L(e)||isSecretBearingFile(e)||pathHasSecretBearingDirSegment(e))return!0;if(!t?.bypassFilters&&isSkillContentFile(e)){if(S!==void 0)return e!==S;if(isSupportedDocFile(e))return!1;let t=extname(e).slice(1).toLowerCase();return!LINKABLE_ASSET_EXTENSIONS.has(t)}if(pathHasAlwaysSkipSegment(e)||isAlwaysSkipFile(e))return!0;if(S!==void 0)return e!==S;if(t?.bypassFilters)return!1;if(B(e))return!0;if(isSupportedDocFile(e))return!1;let s=extname(e).slice(1).toLowerCase();if(LINKABLE_ASSET_EXTENSIONS.has(s)){let t=dirname(e),s=t===`.`?``:t;if((k.get(s)??0)>0)return!1}return!0},isDirExcluded(e,t){if(pathHasSecretBearingDirSegment(e))return!0;if(!t?.bypassFilters&&isSkillContentAncestorDir(e))return!1;if(pathHasAlwaysSkipSegment(e))return!0;if(S!==void 0)return!isSingleDocAncestorDir(e,S);if(t?.bypassFilters)return!1;for(let t of e.split(`/`))if(BUILTIN_SKIP_DIRS.has(t))return!0;if(E)return!1;let s=w?`${w}/${e}`:e;return D.ignores(s)||D.ignores(`${s}/`)},isPathIgnored(e,t){return L(e)||isSecretBearingFile(e)||pathHasSecretBearingDirSegment(e)?!0:isSkillContentFile(e)?!1:pathHasAlwaysSkipSegment(e)||isAlwaysSkipFile(e)?!0:t?.bypassFilters?!1:B(e)},getWatcherIgnoreGlobs(){return O},incrementMdDir(e){let t=e===`.`?``:e;k.set(t,(k.get(t)??0)+1)},decrementMdDir(e){let t=e===`.`?``:e,s=k.get(t)??0;s<=1?k.delete(t):k.set(t,s-1)},rebuildDirCount(){let e=new Map(k);k.clear();try{j()}catch(t){for(let[t,s]of e)k.set(t,s);getLogger(`content-filter`).warn({err:t instanceof Error?t:Error(String(t))},`content-filter rebuildDirCount walk failed — retaining previous counts`)}},async rebuildIgnorePatterns(){let e=getLogger(`content-filter`),t=D,s=O,S=new Map(k),w=Date.now();return withSpan(`config.ignore.rebuild`,{attributes:{}},async E=>{try{await H();let t=Date.now()-w;if(E.setAttributes({"ok.ignore.pattern_count":O.length,"ok.ignore.nested_file_count":0,"ok.ignore.bytes":0}),e.info({durationMs:t},`content-filter async rebuild succeeded`),g)try{g()}catch(t){e.warn({err:t instanceof Error?t:Error(String(t))},`content-filter onAfterRebuild callback threw — derived views may be stale`)}return{ok:!0,patternCount:O.length,nestedFileCount:0,bytes:0,durationMs:t}}catch(g){D=t,O=s,k.clear();for(let[e,t]of S)k.set(e,t);let w=g instanceof Error?g.message:String(g);return e.warn({err:g instanceof Error?g:Error(w)},`content-filter async rebuild failed — rolled back`),{ok:!1,error:{message:w}}}})}}}function runDocLineageGuard(e,t,s){try{if(typeof t!=`string`||t.length===0||isSystemDoc(e)||isConfigDoc(e))return;let g=s.getLoadedDoc(e);if(g===void 0)throw incrementAuthDocLineageMismatch(),setActiveSpanAttributes({"auth.reason":`doc-lineage-mismatch`}),new HocuspocusAuthRejection(`doc-lineage-mismatch`,`doc lineage mismatch: claim against unloaded ${e} is stale by construction`);let S=g.getMap(`lifecycle`).get(LINEAGE_EPOCH_KEY);if(typeof S!=`string`||S.length===0||S!==t)throw incrementAuthDocLineageMismatch(),setActiveSpanAttributes({"auth.reason":`doc-lineage-mismatch`}),new HocuspocusAuthRejection(`doc-lineage-mismatch`,`doc lineage mismatch for ${e}: claimed epoch does not match the live lineage`)}catch(t){if(t instanceof HocuspocusAuthRejection)throw t;incrementAuthDocLineageGuardError(),console.warn(JSON.stringify({event:`doc-lineage-guard-error`,documentName:e,errorName:t instanceof Error?t.name:typeof t,message:t instanceof Error?t.message:String(t)}))}}const QUIET_WINDOW_MS=100,BATCH_TIMEOUT_MS=3e4,WATCHED_FILES=new Set([`HEAD`,`MERGE_HEAD`,`ORIG_HEAD`,`index.lock`]);function readHeadSha(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();if(t.startsWith(`ref: `)){let s=resolve(e,t.slice(5));try{return readFileSync(s,`utf-8`).trim()}catch{try{let s=readFileSync(resolve(e,`packed-refs`),`utf-8`),g=t.slice(5),S=s.split(`
3225
3229
  `).find(e=>e.endsWith(` ${g}`));if(S)return S.split(` `)[0]}catch{}return null}}return t.length>=40?t.slice(0,40):null}catch{return null}}function readBranchFromHead(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();return t.startsWith(`ref: refs/heads/`)?t.slice(16):t.length>=40?`detached-${t.slice(0,12)}`:null}catch{return null}}function watchedGitFile(e){let t=e.split(`/`).pop()??``;return WATCHED_FILES.has(t)?t:null}async function tryStartParcelHeadWatcher(e,t){let s;try{s=await import(`@parcel/watcher`)}catch(e){return getLogger(`head-watcher`).debug({err:e instanceof Error?e.message:String(e)},`[head-watcher] @parcel/watcher unavailable; falling back to chokidar`),null}try{let g=await s.subscribe(e,(e,s)=>{if(e){getLogger(`head-watcher`).warn({err:e},`[head-watcher] parcel subscription error`);return}for(let e of s)t(e.path)});return()=>g.unsubscribe()}catch(e){return getLogger(`head-watcher`).debug({err:e instanceof Error?e.message:String(e)},`[head-watcher] @parcel/watcher subscribe failed; falling back to chokidar`),null}}async function startChokidarHeadWatcher(e,t){let{watch:s}=await import(`./chokidar-Bu9Rdqzq.mjs`),g=s(e,{ignoreInitial:!0,depth:0,followSymlinks:!1});return g.on(`all`,(e,s)=>t(s)),g.on(`error`,e=>{getLogger(`head-watcher`).warn({err:e},`[head-watcher] chokidar watcher error`)}),()=>g.close()}async function startHeadWatcher(e,t,s,g={}){let S=resolveGitDir(e);if(!S)return{unsubscribe:async()=>{},getLastKnownBranch:()=>null};let w=S,E=!1,D=null,O=null,k=null,j=null;async function F(e){if(B&&await B,!E)return;D&&=(clearTimeout(D),null),O&&=(clearTimeout(O),null);let t=readHeadSha(w),g=k!==t,S=readBranchFromHead(w),F;F=S?.startsWith(`detached-`)?`detached-head`:j===S?`within-branch`:`cross-branch`;let L=j;try{await s({headMoved:g,oldHead:k,newHead:t,timeout:e,batchKind:F,oldBranch:L,newBranch:S})}catch(e){console.error(`[head-watcher] onBatchEnd callback failed:`,e)}finally{E=!1,k=t,j=S}}function L(){D&&clearTimeout(D),D=setTimeout(()=>{D=null,F(!1)},QUIET_WINDOW_MS)}let B=null;async function H(e){if(!E){E=!0,k=readHeadSha(w);let s=(async()=>{try{await t({trigger:e})}catch(e){console.error(`[head-watcher] onBatchBegin callback failed:`,e)}})();B=s,await s,B=null,O=setTimeout(()=>{O=null,F(!0)},BATCH_TIMEOUT_MS)}L()}let q=e=>{let t=watchedGitFile(e);t!==null&&H(t)},ee=null,J=`chokidar`;if(g.forceBackend!==`chokidar`&&(ee=await tryStartParcelHeadWatcher(w,q),ee&&(J=`parcel`)),!ee){if(g.forceBackend===`parcel`)throw Error(`@parcel/watcher unavailable for HEAD watching (forced backend)`);ee=await startChokidarHeadWatcher(w,q),J=`chokidar`}let Y=ee;return k=readHeadSha(w),j=readBranchFromHead(w),getLogger(`head-watcher`).info({gitDir:w,backend:J},`watching for HEAD changes`),{unsubscribe:async()=>{E&&await F(!1),D&&clearTimeout(D),O&&clearTimeout(O),await Y()},getLastKnownBranch:()=>j}}const LIVE_DERIVED_INDEX_DEBOUNCE_MS=100;function isLocalOriginLike(e){return typeof e!=`object`||!e?!1:e.source===`local`}function serializeLiveDocument(e){return e.getText(`source`).toString()}function createLiveDerivedIndexExtension(e){let{backlinkIndex:t,tagIndex:s,signalChannel:g,debounceMs:S=100}=e,w=new Map;function E(e){let t=w.get(e);t&&(clearTimeout(t),w.delete(e))}function D(e,D){E(e),w.set(e,setTimeout(()=>{w.delete(e);try{let S=serializeLiveDocument(D);t.updateDocumentFromMarkdown(e,S),g?.(`backlinks`),g?.(`graph`),s&&(s.updateDocumentFromMarkdown(e,S),g?.(`tags`))}catch(t){console.error(`[live-derived-index] Failed to update derived views for ${e}:`,t)}},S))}return{async onChange({documentName:e,document:t,transactionOrigin:s}){isLinkIndexExcludedDoc(e)||isLocalOriginLike(s)&&s.context?.origin===`file-watcher`||D(e,t)},async beforeUnloadDocument({documentName:e}){E(e)},async onDestroy(){for(let e of w.values())clearTimeout(e);w.clear()}}}const log$4=getLogger(`shadow-gc`),GC_GRACE_PERIOD_MS=1440*60*1e3,SESSION_WRITER_TTL_MS=720*60*60*1e3;function extractBranchNames(e){let t=new Set;for(let s of e){let e=s.replace(/^refs\/wip\//,``),g=e.lastIndexOf(`/`);if(g<=0)continue;let S=e.slice(0,g);parseWriterId(e.slice(g+1)).classification!==`unknown`&&t.add(S)}return t}async function getProjectBranchSha(e,t){try{return(await esm_default().env({GIT_DIR:e}).raw(`rev-parse`,`refs/heads/${t}`)).trim()}catch{return null}}async function listProjectBranches(e){let t=new Set;try{let s=(await esm_default().env({GIT_DIR:e}).raw(`for-each-ref`,`refs/heads/`,`--format=%(refname:short)`)).trim();if(s)for(let e of s.split(`
3226
3230
  `))e&&t.add(e)}catch(e){log$4.warn({err:e},`[shadow-gc] listProjectBranches failed; treating as no project branches`)}return t}async function gcShadowBranches(e,t,s=DEFAULT_CHECKPOINT_RETENTION,g=`.`){let S={deletedBranches:[],renamedBranches:[],retainedBranches:[],checkpointGc:{},deletedStaleSessionRefs:0},w=shadowGit(e,{timeoutMs:MAINTENANCE_GIT_TIMEOUT_MS}),E;try{E=(await w.raw(`for-each-ref`,`refs/wip/`,`--format=%(refname)`)).trim()}catch{return S}if(!E)return S;let D=E.split(`
@@ -3239,7 +3243,7 @@ Incremental by default — don't re-read the whole repo.
3239
3243
  `,`
3240
3244
  `).split(`
3241
3245
  `),s=[],g=!1,S=``;for(let e of t){let t=/^\s{0,3}([`~]{3,})/.exec(e);if(t){g?RegExp(`^\\s{0,3}${S[0]==="`"?"`":`~`}{${S.length},}\\s*$`).test(e)&&(g=!1,S=``):(g=!0,S=t[1]);continue}if(g)continue;let w=stripInlineCodeSpans(e);for(TAG_VALUE_RE.lastIndex=0;;){let e=TAG_VALUE_RE.exec(w);if(e===null)break;let t=e[2];t&&s.push(t)}}return s}var TagIndex=class{contentDir;contentFilter;state=createEmptyState();initChain=Promise.resolve();constructor(e){this.contentDir=e.contentDir,this.contentFilter=e.contentFilter}updateDocumentFromMarkdown(e,t){if(!isLinkIndexExcludedDoc(e))try{let{frontmatter:s,body:g}=stripFrontmatter(t),S=extractFrontmatterTags(s?unwrapFrontmatterFences(s):``),w=extractInlineTagsFromBody(g),E=new Set([...S,...w]),D=new Set;for(let e of E)for(let t of expandTagToHierarchy(e))D.add(t);this.applyDocSnapshot(e,E,D)}catch(t){console.warn(`[tag-index] Failed to scan ${e} for tag extraction:`,t),this.deleteDocument(e)}}deleteDocument(e){if(isLinkIndexExcludedDoc(e))return;let t=this.state.byDoc.get(e);if(t){for(let s of t){let t=this.state.byTag.get(s);t&&(t.delete(e),t.size===0&&this.state.byTag.delete(s))}this.state.byDoc.delete(e),this.state.byDocLiteral.delete(e)}}renameDocument(e,t,s){this.deleteDocument(e),this.updateDocumentFromMarkdown(t,s)}getDocsForTag(e){let t=this.state.byTag.get(e);return t?[...t].sort((e,t)=>e.localeCompare(t)):[]}getDocsForTagWithMatches(e){let t=this.state.byTag.get(e);if(!t)return[];let s=[];for(let g of t){let t=this.state.byDocLiteral.get(g);if(!t)continue;let S=tagsMatchingPrefix(t,e);s.push({docName:g,matchingTags:[...S].sort((e,t)=>e.localeCompare(t))})}return s.sort((e,t)=>e.docName.localeCompare(t.docName))}getAllTags(){let e=[...this.state.byTag.entries()],t=e.map(([e])=>e),s=new Set;for(let e of t){let t=e.indexOf(`/`);t>0&&s.add(e.slice(0,t));let g=t;for(;g>0;)s.add(e.slice(0,g)),g=e.indexOf(`/`,g+1)}return e.map(([e,t])=>({name:e,count:t.size,isLeaf:!s.has(e)})).sort((e,t)=>e.name.localeCompare(t.name))}init(){let e=this.initChain.then(()=>this.initOnce());return this.initChain=e.catch(e=>{console.warn(`[tag-index] init failed (chain cleared for next init):`,e)}),e}async initOnce(){if(this.state=createEmptyState(),!existsSync(this.contentDir))return;let e=await this.listDocsWithPaths(),t=50;for(let t=0;t<e.length;t+=50){let s=e.slice(t,t+50),g=await Promise.all(s.map(async({docName:e,filePath:t})=>{try{return{docName:e,markdown:await readFile$1(t,`utf-8`)}}catch(t){return console.warn(`[tag-index] Failed to read ${e} during init:`,t),null}}));for(let e of g)if(e)try{this.updateDocumentFromMarkdown(e.docName,e.markdown)}catch(t){console.warn(`[tag-index] Failed to index ${e.docName} during init:`,t)}}}applyDocSnapshot(e,t,s){let g=this.state.byDoc.get(e)??new Set;for(let t of g){if(s.has(t))continue;let g=this.state.byTag.get(t);g&&(g.delete(e),g.size===0&&this.state.byTag.delete(t))}for(let t of s){let s=this.state.byTag.get(t);s||(s=new Set,this.state.byTag.set(t,s)),s.add(e)}s.size===0?(this.state.byDoc.delete(e),this.state.byDocLiteral.delete(e)):(this.state.byDoc.set(e,s),this.state.byDocLiteral.set(e,t))}async listDocsWithPaths(){let e=[];await this.walkContentDir(this.contentDir,e),e.sort((e,t)=>e.docName===t.docName?t.filePath.localeCompare(e.filePath):e.docName.localeCompare(t.docName));let t=new Set;return e.filter(({docName:e})=>t.has(e)?!1:(t.add(e),!0))}async walkContentDir(e,t){let s;try{s=await readdir(e,{withFileTypes:!0})}catch(t){console.warn(`[tag-index] Failed to read directory ${e}:`,t);return}for(let g of s){let s=join(e,g.name);if(g.isDirectory()){let e=toPosix(relative(this.contentDir,s));if(this.contentFilter&&e&&this.contentFilter.isDirExcluded(e))continue;await this.walkContentDir(s,t);continue}if(!g.isFile()||!isSupportedDocFile(g.name))continue;let S=toPosix(relative(this.contentDir,s));this.contentFilter?.isExcluded(S)||t.push({docName:stripDocExtension(S),filePath:s})}}};const PARK_SNAPSHOT_ORIGIN=(()=>{let e=Object.freeze({origin:`park-snapshot`,paired:!0});return Object.freeze({source:`local`,skipStoreHooks:!1,context:e})})();function buildSyncCredentialArgs(e){return[`-c`,`credential.helper=!${(e&&e.length>0?e:[`open-knowledge`]).map(shellEscape).join(` `)} auth git-credential`]}function createServer$1(e){let{contentDir:t,projectDir:s=t,quiet:g=!0,debounce:S=2e3,maxDebounce:w=1e4,gitEnabled:E=!0,commitDebounceMs:D=3e4,wipRef:O=`refs/wip/main`,configHomedirOverride:k,enableTestRoutes:j=!1,shadowRepo:F,contentRoot:L,destroyTimeoutMs:B=1e4,localOpCliArgs:H,skipStateManifestCheck:q=!1,singleDocRelPath:ee,ephemeral:J=!1}=e,Y=getLogger(`server`);function te(){let e=readConfigSafely({absPath:resolveConfigPath(`project-local`,s),sideline:!1,warn:e=>Y.warn({message:e},`[config] could not read project-local config`)}),t=e.value.autoSync?.enabled;if(t!=null)return t===!0;e.valid||Y.warn({},`[config] project-local autoSync.enabled unavailable (config invalid) — falling back to the committed project default`);let g=readConfigSafely({absPath:resolveConfigPath(`project`,s),sideline:!1,warn:e=>Y.warn({message:e},`[config] could not read project config`)});return g.valid||Y.warn({},`[config] committed autoSync.default unavailable (project config invalid) — defaulting to disabled`),g.value.autoSync?.default===!0}function ne(){return readProjectLocalSemanticConfig(s,{configHomedirOverride:k,onWarn:e=>Y.warn({message:e},`[config] could not read project-local config`)})}function ae(e){return`${normalizeProviderId(e.baseUrl)}|${e.model}|${e.dimensions??1536}`}initTelemetry();let oe=randomUUID$1(),se=getLocalDir(s);if(acquireServerLock(se,{port:e.port??0,worktreeRoot:s,kind:e.lockKind??`interactive`,capabilities:[`http`,`ws`]}),!q)try{assertCompatibleStateManifest({lockDir:se,shadowRepoDir:resolveShadowDir(s)})}catch(e){throw releaseServerLock(se),e}let ce=createBasenameIndex(),ue=(e,t)=>ce.resolveEmbed(e,t),de=(e,s)=>{let g=ce.resolveEmbed(e,s);if(!g&&e.includes(`/`)&&(g=e.replace(/^\.?\//,``)),!g)return null;let S=resolve(t,g);if(!isWithinDir(S,resolve(t)))return null;try{let e=statSync(S);return e.isFile()?e.size:null}catch{return null}},fe,me,ge,_e,ve,ye,Ce,we,Te=null,De=null,je=null,Me=null,Pe=ne(),Ie=new SemanticSearchService({loadEmbedder:e.embedderLoader??(()=>{let t=ne();return loadOpenAiEmbedder({keyStore:e.embeddingsKeyStore??null,config:{baseUrl:t.baseUrl,model:t.model,dimensions:t.dimensions}})}),cacheDir:join(getLocalDir(s),`embeddings`),enabled:Pe.enabled,providerFingerprint:ae(Pe)}),Re=null,ze=new Set,Be=!1,Ve,Ue,We,Ge=new Promise((e,t)=>{Ue=e,We=t});function Ke(e){Te?.signal(e)}let Xe=2e3,$e=null;function nt(){$e!==null&&clearTimeout($e),$e=setTimeout(()=>{$e=null,me.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist debounced cache:`,e)})},2e3)}let rt=new RecentlyRemovedDocs(void 0,{onEviction:()=>incrementRecentlyRemovedDocsEviction(),onSizeChange:e=>setRecentlyRemovedDocsSize(e)}),it=(e,t)=>{isReservedForUserTree(e)||rt.setRenamed(e,t)},at=e=>{if(!isReservedForUserTree(e)){if(rt.peek(e)?.kind===`renamed`){console.info(JSON.stringify({event:`recently-removed-docs-unpaired-delete-suppressed`,docName:e,source:`watcher-delete`}));return}rt.setDeleted(e)}},st=e=>{isReservedForUserTree(e)||rt.delete(e)};try{fe=createContentFilter({projectDir:s,contentDir:t,singleDocRelPath:ee,onAfterRebuild:()=>{me.rebuildFromDisk(getActiveBranch()).catch(e=>{getLogger(`server-factory`).warn({err:e},`[content-filter] backlink-index rebuild failed after onAfterRebuild`)}),ge.init().catch(e=>{getLogger(`server-factory`).warn({err:e},`[content-filter] tag-index rebuild failed after onAfterRebuild`)}),reconcileFileIndexAfterFilterRebuild(Wt).then(({prunedFiles:e,prunedFolders:t})=>{let s=e+t;s>0?getLogger(`server-factory`).info({pruned:s,prunedFiles:e,prunedFolders:t},`[content-filter] reconciled file indexes after onAfterRebuild`):getLogger(`server-factory`).debug({prunedFiles:e,prunedFolders:t},`[content-filter] file index reconcile completed after onAfterRebuild (no entries pruned; rescan may have added entries)`)}).catch(e=>{getLogger(`server-factory`).warn({err:e},`[content-filter] file index reconcile failed after onAfterRebuild`)})}}),me=new BacklinkIndex({projectDir:s,contentDir:t,contentFilter:fe}),ge=new TagIndex({contentDir:t,contentFilter:fe}),ge.init().catch(e=>{getLogger(`server-factory`).warn({err:e},`[server-factory] tag-index init failed; continuing with empty index`)}),_e={current:F},ve=E?createMaintenanceCoordinator({getShadow:()=>_e.current??null,getCurrentBranch:()=>Kt?.getLastKnownBranch()??null,contentRoot:L??``,projectGitDir:resolveGitDir(s)??void 0,isWriterLive:e=>{if(!je&&!we)return getLogger(`server-factory`).debug({writerId:e},`[server-factory] isWriterLive called before liveness deps populated — treating writer as dead`),!1;if(je?.getPresenceMap()[e])return!0;let t=e.startsWith(`agent-`)?e.slice(6):e;for(let e of we?.sessionsForConnection(t)??[])return!0;return!1}}):void 0,ye=createPersistenceExtension({contentDir:t,projectDir:s,gitEnabled:E,commitDebounceMs:D,wipRef:O,shadowRef:_e,ephemeral:J,contentRoot:L,backlinkIndex:me,configHomedirOverride:k,getCurrentBranch:()=>Kt?.getLastKnownBranch()??null,resolveEmbed:ue,resolveSize:de,getPrincipal:()=>Re,onAgentCommit:()=>Te?.signal(`session-activity`),onFlushCommit:()=>ve?.noteFlushCommit(),onDiskFlush:(e,t,s,g)=>{Te?.emitDiskAck(e,t),!isReservedForUserTree(e)&&assetReferencesChanged(g,s)&&(Me?.(),Ke(`files`))},onConfigRejected:(e,t)=>Te?.emitConfigValidationRejected(e,t),mdManager:e.mdManager}),Ce=new Hocuspocus({quiet:g,debounce:S,maxDebounce:w,extensions:[ye.extension]});let B=Ce.shouldUnloadDocument.bind(Ce);Ce.shouldUnloadDocument=e=>{if(ze.has(e)||Be&&B(e))return!0;let t=e.name;return isReservedForUserTree(t)||getReconciledBase(t)!==void 0||e.getXmlFragment(`default`).length!==0||e.getText(`source`).length!==0?!1:B(e)},Ve=async e=>{ze.add(e);try{await Ce.unloadDocument(e)}finally{ze.delete(e)}},Te=new CC1Broadcaster(Ce),De=new AgentFocusBroadcaster(Ce),je=new AgentPresenceBroadcaster(Ce),we=new AgentSessionManager(Ce);let q=createLiveDerivedIndexExtension({backlinkIndex:me,tagIndex:ge,signalChannel:Ke});Ce.configuration.extensions.push(q),Ce.configuration.extensions.push({__kind:`principal-auth`,async onAuthenticate(e){let t=e.token,s=parseHocuspocusAuthToken(t),g=s?.expectedServerInstanceId;if(typeof g==`string`&&g.length>0&&g!==oe)throw new HocuspocusAuthRejection(`server-instance-mismatch`,`server instance mismatch: client claimed ${g}, this server is ${oe}`);let S=s?.expectedBranch,w=getActiveBranch();if(typeof S==`string`&&S.length>0&&S!==w)throw new HocuspocusAuthRejection(`branch-mismatch`,`branch mismatch: client claimed ${S}, server is on ${w}`);if(!s)return;let E=e.context;typeof s.principalId==`string`&&(Re&&s.principalId===Re.id?E.principalId=Re.id:Re?console.warn(JSON.stringify({event:`principal-token-mismatch`,claimed:s.principalId,loaded:Re.id})):E.principalId=s.principalId),typeof s.tabSessionId==`string`&&(E.tabSessionId=s.tabSessionId),E.kind=`human`}}),Ce.configuration.extensions.push({__kind:`config-doc-admission-guard`,async onAuthenticate(e){if(!isConfigDoc(e.documentName)&&!isManagedArtifactDoc(e.documentName))return;let t=e.request,s=t.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s))throw Error(`config-doc admission requires loopback peer (peer=${s}, doc=${e.documentName})`);let g=e.requestHeaders,S=(g&&typeof g.get==`function`?g.get(`host`):null)??t.headers?.host??void 0;if(!isAllowedWorkspaceHostHeader(S))throw Error(`config-doc admission requires loopback Host header (host=${S??`<absent>`}, doc=${e.documentName})`)}});let Y=resolve(t);function te(e){if(!isSafeDocName(e))return null;let t=resolve(Y,`${e}${getDocExtension(e)}`);return isWithinDir(t,Y)?t:null}Ce.configuration.extensions.push({__kind:`removal-redirect-guard`,async onAuthenticate(e){await runRemovalRedirectGuard(e.documentName,{recentlyRemovedDocs:rt,resolveFilePath:te,fileExists:existsSync})}}),Ce.configuration.extensions.push({__kind:`doc-lineage-guard`,async onAuthenticate(e){let t=parseHocuspocusAuthToken(e.token);runDocLineageGuard(e.documentName,t?.expectedDocLineageEpoch,{getLoadedDoc:e=>Ce.documents.get(e)})}}),Ce.configuration.extensions.push({__kind:`system-doc-broadcast-guard`,async beforeHandleMessage(e){if(e.documentName!==`__system__`)return;let t=new IncomingMessage(e.update);if(t.readVarString(),t.readVarUint()===MessageType.BroadcastStateless)throw Error(`inbound BroadcastStateless on ${SYSTEM_DOC_NAME} rejected — server-only channel`)}});let ae=createApiExtension({hocuspocus:Ce,sessionManager:we,contentDir:t,contentFilter:fe,serverInstanceId:oe,getFileIndex:()=>Wt?Wt.getFileIndex():new Map,getAllFilesIndex:()=>Wt?Wt.getAllFilesIndex():new Map,getFileIndexGeneration:()=>Wt?.getFileIndexGeneration()??0,mutateFileIndex:e=>Wt?.mutateFileIndex(e),getFolderIndex:()=>Wt?Wt.getFolderIndex():new Map,getAliasMap:()=>Wt?Wt.getAliasMap():new Map,getFolderAliasIndex:()=>Wt?Wt.getFolderAliasIndex():new Map,rescanFiles:()=>Wt?.rescanFromDisk(),enableTestRoutes:j,shadowRef:_e,flushGitCommit:()=>ye.flushPendingGitCommit(),flushContributors:()=>ye.flushContributors(),takeStoreFailure:e=>ye.takeStoreFailure(e),takeStoreDivergence:e=>ye.takeStoreDivergence(e),markAgentWriteStore:e=>ye.markAgentWriteStore(e),getCurrentBranch:()=>Kt?.getLastKnownBranch()??null,getDiskAckSVs:()=>Te?.getLatestDiskAckSVsAsBase64()??{},contentRoot:L,backlinkIndex:me,tagIndex:ge,signalChannel:Ke,agentFocusBroadcaster:De,agentPresenceBroadcaster:je,onAgentWrite:e.onAgentWrite,getSyncEngine:()=>$t,localOpCliArgs:H,projectDir:s,resolveEmbed:ue,getPrincipal:()=>Re,homeDirOverride:k,forceUnloadDocument:Ve,ready:Ge,recentlyRemovedDocs:rt,serializeDoc:jt,evictManagedArtifactLkg:e=>{ye.managedArtifactCtx.lkgCache.delete(e)},semanticSearch:Ie,getSemanticSimilarityFloor:()=>ne().similarityFloor,embeddingsSecretsFile:secretsFilePath(k),ephemeral:J,onReferencedAssetsCacheInvalidator:e=>{Me=e}});Ce.configuration.extensions.push(ae),Ce.configuration.extensions.push(createServerObserverExtension({mdManager,schema,shadowRef:_e,contentRoot:L,getCurrentBranch:()=>Kt?.getLastKnownBranch()??null,resolveEmbed:ue,resolveSize:de})),Ce.configuration.extensions.push(createSyncHandshakeSpanExtension()),Ce.configuration.extensions.push(createConflictLifecycleSeedExtension({getSyncEngine:()=>$t,projectDir:s,contentDir:t}))}catch(e){throw releaseServerLock(se),e}let vt=null,Tt=new Map,Et=[];function Dt(e,t){let s=resolve(e,`rescue`),g=resolve(s,`${t}${getDocExtension(t)}`);return isWithinDir(g,s)?g:null}function jt(e){let t=Ce.documents.get(e);return t?serializeYDocSource(t):null}let Mt=(e,t)=>applyExternalChange(Ce,e,t,ue,de);function Ft(e){if(!isDocInConflict(e))return;let t=e.getMap(`lifecycle`);t.delete(`status`),t.delete(`reason`)}let It=e=>{if(!e)return;let t=`[[${e}]]`;for(let[s]of Ce.documents){if(isReservedForUserTree(s))continue;let g=Ce.documents.get(s);if(!g)continue;let S=g.getText(`source`).toString();if(S.includes(t))try{g.transact(()=>{applyDiskContentToDoc(g,S,ue,s)},FILE_WATCHER_ORIGIN)}catch(t){Y.error({err:t,docName:s,assetBasename:e},`[asset-event] failed to re-render ${s} for asset basename ${e}`)}}},Lt=null,Rt=e=>{e&&(Lt===null&&(Lt=new Set,setImmediate(()=>{let e=Lt;if(Lt=null,e)try{for(let t of e)It(t)}catch(t){Y.error({err:t,basenames:[...e]},`[asset-event] dedup rerender pass crashed`)}})),Lt.add(e))};function zt(e){switch(e.kind){case`rename`:return e.newDocName;case`asset-create`:case`asset-delete`:case`folder-create`:case`folder-delete`:case`file-create`:case`file-update`:case`file-delete`:return e.relativePath;case`create`:case`update`:case`delete`:case`conflict`:return e.docName;default:return assertNeverDiskEvent(e)}}async function Bt(e){try{switch(e.kind){case`create`:Y.info({docName:e.docName},`[reconcile] create: ${e.docName}`),me.updateDocumentFromMarkdown(e.docName,e.content),nt(),ge.updateDocumentFromMarkdown(e.docName,e.content),Ke(`files`),Ke(`backlinks`),Ke(`graph`),Ke(`tags`),st(e.docName);break;case`update`:{let{docName:t,content:s}=e,g=Ce.documents.get(t);if(!g){me.updateDocumentFromMarkdown(t,s),nt(),ge.updateDocumentFromMarkdown(t,s),Ke(`backlinks`),Ke(`graph`),Ke(`tags`);return}let S=getReconciledBase(t)??``,w=jt(t)??S,E=reconcile({docName:t,base:S,ours:w,theirs:s}),D=contentHash(S).slice(0,6),O=contentHash(w).slice(0,6),k=contentHash(s).slice(0,6);switch(Y.info({docName:t,base:D,ours:O,theirs:k,result:E.kind},`[reconcile] ${t} base=${D} ours=${O} theirs=${k} result=${E.kind}`),E.kind){case`noop`:Ft(g),me.updateDocumentFromMarkdown(t,s),nt(),ge.updateDocumentFromMarkdown(t,s),Ke(`backlinks`),Ke(`graph`),Ke(`tags`);break;case`clean`:try{Mt(t,E.newContent),setReconciledBase(t,E.newContent),incrementReconcile(),Ft(g),me.updateDocumentFromMarkdown(t,s),nt(),ge.updateDocumentFromMarkdown(t,s),Ke(`backlinks`),Ke(`graph`),Ke(`tags`)}catch(e){Y.error({err:e,docName:t},`[reconcile] failed to apply clean content to Y.Doc for ${t}`),setReconciledBase(t,s),Ft(g)}break;case`merged`:try{Mt(t,E.newContent),setReconciledBase(t,s),incrementReconcile(),Ft(g),me.updateDocumentFromMarkdown(t,s),nt(),ge.updateDocumentFromMarkdown(t,s),Ke(`backlinks`),Ke(`graph`),Ke(`tags`)}catch(e){Y.error({err:e,docName:t},`[reconcile] failed to apply merged content to Y.Doc for ${t}`),setReconciledBase(t,s),Ft(g)}break;case`conflicts`:try{Mt(t,E.newContent),setReconciledBase(t,E.newContent),incrementReconcile(),incrementConflict(),me.updateDocumentFromMarkdown(t,s),nt(),ge.updateDocumentFromMarkdown(t,s),Ke(`backlinks`),Ke(`graph`),Ke(`tags`)}catch(e){Y.error({err:e,docName:t},`[reconcile] failed to apply conflict content to Y.Doc for ${t}`),setReconciledBase(t,s)}{let e=g.getMap(`lifecycle`);e.set(`status`,`conflict`),e.set(`reason`,`merged-with-markers`)}break;case`refused`:{incrementConflict();let e=g.getMap(`lifecycle`);e.set(`status`,`conflict`),e.set(`reason`,E.reason);break}}break}case`delete`:{let{docName:t}=e,s=Ce.documents.get(t);if(!s){me.deleteDocument(t),nt(),ge.deleteDocument(t),Ke(`files`),Ke(`backlinks`),Ke(`graph`),Ke(`tags`),at(t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:t,kind:`deleted`,source:`watcher-delete`}));return}let g=getReconciledBase(t)??``,S=jt(t)??``,w=S!==g;if(w&&_e.current){let e=_e.current,s=Kt?.getLastKnownBranch()??`main`;queueMicrotask(()=>{saveInMemoryCheckpoint(e,L??``,{kind:`external-change-rescue`,docName:t,contents:S,label:`External change recovered @ ${new Date().toISOString()}`,branch:s,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),Y.info({docName:t},`[reconcile] rescue checkpoint saved (delete): ${t}`)}).catch(e=>{Y.error({docName:t,err:e},`[reconcile] rescue checkpoint write failed: ${t}`)})})}s.getMap(`lifecycle`).set(`status`,`deleted-upstream`),deleteReconciledBase(t),me.deleteDocument(t),nt(),ge.deleteDocument(t),Y.info({docName:t,isDirty:w},`[reconcile] delete: ${t} (dirty=${w})`),Ce.closeConnections(t),await Ve(s),Ke(`files`),Ke(`backlinks`),Ke(`graph`),Ke(`tags`),at(t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:t,kind:`deleted`,source:`watcher-delete`}));break}case`rename`:{let{oldDocName:t,newDocName:s,content:g}=e,S=Ce.documents.get(t);if(deleteReconciledBase(t),setReconciledBase(s,g),me.renameDocument(t,s,g),nt(),ge.renameDocument(t,s,g),S){let e=S.getMap(`lifecycle`);e.set(`status`,`renamed`),e.set(`newPath`,s)}Y.info({oldDocName:t,newDocName:s},`[reconcile] rename: ${t} → ${s}`),Ke(`files`),Ke(`backlinks`),Ke(`graph`),Ke(`tags`),it(t,s),console.info(JSON.stringify({event:`recently-removed-docs-populate`,from:t,to:s,kind:`renamed`,source:`watcher-rename`}));break}case`conflict`:{let{docName:t}=e,s=Ce.documents.get(t);if(!s)return;let g=jt(t);g===null?Y.warn({docName:t},`[reconcile] case 'conflict': serializeDoc returned null for ${t}; reconciledBase snapshot skipped — post-resolution reconcile may degrade to 3-way merge`):setReconciledBase(t,g);let S=s.getMap(`lifecycle`);S.set(`status`,`conflict`),S.set(`reason`,`conflict-markers`),Y.info({docName:t},`[reconcile] conflict markers detected: ${t}`);break}case`asset-create`:ce.add(e.relativePath),Ke(`files`),Rt(basename(e.relativePath));break;case`asset-delete`:ce.remove(e.relativePath),Ke(`files`),Rt(basename(e.relativePath));break;case`folder-create`:case`folder-delete`:Ke(`files`);break;case`file-create`:case`file-update`:case`file-delete`:Ke(`files`);break;default:assertNeverDiskEvent(e)}}catch(t){let s=zt(e);Y.error({err:t,kind:e.kind,label:s},`[reconcile] failed to handle ${e.kind} for ${s}`)}}let Vt=[];async function Ht(e){if(isBatchInProgress()){Vt.push(e);return}await Bt(e)}async function Ut(){let e=Vt.splice(0,Vt.length);for(let t of e)await Bt(t)}let Wt=null,Kt=null,$t=null,en=null;async function jr(e){if(Ce.documents.size===0)return;let t=!1,s=new Promise(e=>{Ce.configuration.extensions.push({async afterUnloadDocument({instance:s}){!t&&s.getDocumentsCount()===0&&(t=!0,e())}})}),g=Array.from(Ce.documents.keys());Ce.closeConnections(),Ce.flushPendingStores();for(let e of Ce.documents.values())e.getConnectionsCount()===0&&Ce.unloadDocument(e).catch(t=>{console.warn(JSON.stringify({event:`ok-shutdown-unload-document-failed`,docName:e.name,reason:t instanceof Error?t.message:String(t)}))});let S,w=new Promise((s,w)=>{S=setTimeout(()=>{t=!0;let s=Array.from(Ce.documents.keys()),S=[],E=[];if(_e.current){for(let e of s)if(!isReservedForUserTree(e))try{let t=jt(e);if(t===null){Y.warn({docName:e},`[rescue] skipping ${e} — document dropped from map mid-rescue`),E.push(e);continue}let s=Dt(_e.current.gitDir,e);if(!s){Y.warn({docName:e,gitDir:_e.current.gitDir},`[rescue] path-traversal guard rejected docName: ${e}`),E.push(e);continue}mkdirSync(dirname(s),{recursive:!0}),writeFileSync(s,t,`utf-8`),incrementRescueBuffer(),S.push(e),Y.info({docName:e},`[rescue] rescue buffer saved on flush timeout: ${e}`)}catch(t){E.push(e),Y.error({err:t,docName:e},`[rescue] failed to write rescue buffer for ${e}`)}}else Y.warn({stillLoadedCount:s.length},`[rescue] shadow repo unavailable at flush timeout — ${s.length} doc(s) will be lost: [${s.join(`, `)}]`),E.push(...s);let D=S.length>0||E.length>0?` — rescued [${S.join(`, `)}]${E.length>0?`, lost [${E.join(`, `)}]`:``}`:``;w(Error(`flushAllStoresAndWait timeout after ${e}ms — ${s.length}/${g.length} docs did not unload: [${s.join(`, `)}]${D}`))},e)});try{await Promise.race([s,w])}finally{S!==void 0&&clearTimeout(S)}}async function Mr(){return en||(en=(async()=>{let e=Date.now(),t=[];Be=!0,$e!==null&&(clearTimeout($e),$e=null);let g,S=await Promise.race([Ge.then(()=>`completed`,e=>(Y.debug({err:e},`[server] init incomplete during shutdown`),`failed`)),new Promise(e=>{g=setTimeout(()=>e(`timeout`),5e3)})]);g!==void 0&&clearTimeout(g),S===`timeout`&&Y.warn({},`[server] init did not complete within 5s during shutdown`);let w=Ce.documents.size;ve?.destroy();try{try{try{Kt&&=(await Kt.unsubscribe(),null),Wt&&=(await Wt.unsubscribe(),null);for(let{docName:e,cleanup:t}of Et)try{await t()}catch(t){Y.warn({err:t,docName:e},`[server] failed to stop config-file-watcher for ${e}`)}Et.length=0}catch(e){t.push({phase:`watcher-unsubscribe`,error:e instanceof Error?e.message:String(e)}),Y.error({err:e},`[server] shutdown phase-1 watcher unsubscribe failed`)}try{Te?.destroy(),je?.destroy(),vt&&=(await vt.disconnect(),null);for(let[e,t]of Tt)try{await t.disconnect()}catch(t){Y.warn({err:t,docName:e},`[server] failed to disconnect ${e} during shutdown`)}Tt.clear()}catch(e){t.push({phase:`cc1-teardown`,error:e instanceof Error?e.message:String(e)}),Y.error({err:e},`[server] shutdown phase-1b CC1 teardown failed`)}try{await we.closeAll()}catch(e){t.push({phase:`agent-session-drain`,error:e instanceof Error?e.message:String(e)}),Y.error({err:e},`[server] shutdown phase-2 agent session drain failed`)}try{await jr(B)}catch(e){t.push({phase:`flush-all-stores`,error:e instanceof Error?e.message:String(e)}),Y.error({err:e},`[server] shutdown phase-3 flush failed`)}let e;try{await Promise.race([(async()=>{await ye.flushPendingGitCommit(),await ye.waitForPendingCommits()})(),new Promise((t,s)=>{e=setTimeout(()=>s(Error(`L2 git flush timeout`)),B)})])}catch(e){t.push({phase:`git-commit-flush`,error:e instanceof Error?e.message:String(e)}),Y.error({err:e},`[server] shutdown phase-4 git commit flush failed`)}finally{e!==void 0&&clearTimeout(e)}try{$t&&=(await $t.destroy(),null)}catch(e){t.push({phase:`sync-engine-stop`,error:e instanceof Error?e.message:String(e)}),Y.error({err:e},`[server] shutdown sync-engine-stop failed`)}}finally{if(_e.current){try{let e=(await esm_default({baseDir:s,timeout:{block:5e3}}).revparse(`HEAD`)).trim();e&&writeFileSync(resolve(_e.current.gitDir,`last-known-head`),e,`utf-8`)}catch{}try{destroyShadowRepo(_e.current)}catch(e){t.push({phase:`shadow-repo-release`,error:e instanceof Error?e.message:String(e)}),Y.error({err:e},`[server] shutdown phase-5 destroyShadowRepo failed`)}}let g=Date.now()-e;t.length===0?Y.info({documentCount:w,durationMs:g},`[server] shutdown flushed ${w} documents in ${g}ms`):Y.warn({documentCount:w,durationMs:g,phaseErrors:t},`[server] shutdown flushed ${w} documents in ${g}ms with ${t.length} phase error(s)`)}}finally{try{releaseServerLock(se)}catch(e){t.push({phase:`server-lock-release`,error:e instanceof Error?e.message:String(e)}),Y.error({err:e},`[server] shutdown phase-6 releaseServerLock failed`)}try{await shutdownTelemetry()}catch(e){t.push({phase:`telemetry-shutdown`,error:e instanceof Error?e.message:String(e)})}}})(),en)}let Fr=[];async function Ir(){try{Re=await loadPrincipal(s),Y.info({principalId:Re.id},`[server] principal loaded`)}catch(e){Y.warn({err:e},`[server] principal load failed — browser writes will use SERVICE_WRITER`)}if(!_e.current)try{_e.current=await initShadowRepo(s),Y.info({gitDir:_e.current.gitDir},`[server] history repo initialized at ${_e.current.gitDir}`)}catch(e){Y.error({err:e},`[server] history repo init failed`),Fr.push(`shadow-repo`)}if(_e.current){let e=null;try{e=loadRenameLogIndex(_e.current.gitDir),sweepLazyPopOrphans(_e.current.gitDir,e),setRenameLogIndex(_e.current.gitDir,e),Y.info({entries:e.byTo.size},`[server] rename log loaded (${e.byTo.size} entries)`)}catch(e){Y.warn({err:e},`[rename-log] boot-time load/sweep failed; rename history unavailable`)}if(e){let t=1e4;try{await Promise.race([gcRenameLog(_e.current,e,{rebuild:!0}),new Promise((e,s)=>setTimeout(()=>s(Error(`boot-time GC exceeded ${t}ms`)),t))])}catch(e){Y.warn({err:e},`[rename-log] boot-time GC/rebuild failed; index loaded without GC`)}}try{await ve?.runBootMaintenance()}catch(e){Y.warn({err:e},`[shadow-maintenance] boot maintenance failed (non-fatal)`)}}if(_e.current)try{await shadowGit(_e.current).raw(`rev-parse`,`--git-dir`)}catch(e){let t=e instanceof Error?e.message:String(e);if(t.includes(`not a git repository`)||t.includes(`invalid object`)){Y.warn({},`[server] history repo appears corrupted — reinitializing`);try{_e.current=await initShadowRepo(s)}catch(e){Y.error({err:e},`[server] history repo reinit failed`),_e.current=void 0,Fr.includes(`shadow-repo`)||Fr.push(`shadow-repo`)}}else Y.error({err:e},`[server] history repo check failed (transient?)`)}if(_e.current)try{let e=resolve(_e.current.gitDir,`last-known-head`),t=null;try{t=readFileSync(e,`utf-8`).trim()||null}catch{}let g=null;try{g=(await esm_default({baseDir:s,timeout:{block:1e4}}).revparse(`HEAD`)).trim()||null}catch{}if(g!==null){if(g!==t){let e=`main`;try{let t=(await esm_default({baseDir:s,timeout:{block:1e4}}).raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();t&&t!==`HEAD`&&(e=t)}catch{}Y.info({lastKnownHead:t,currentHead:g,branch:e},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${g}, action=import`);try{await commitUpstreamImport(_e.current,L??``,t,g,e),incrementUpstreamImport()}catch(e){Y.warn({err:e},`[head-drift] commitUpstreamImport failed — continuing`)}}else Y.info({currentHead:g},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${g}, action=noop`);try{writeFileSync(e,g,`utf-8`)}catch(e){Y.warn({err:e},`[head-drift] failed to write last-known-head`)}}}catch(e){Y.warn({err:e},`[head-drift] check failed — continuing`)}try{let e=recoverPendingManagedRename(t,s);if(e.recovered&&e.journal){let t=e.journal.version===2?e.journal.fromPath:e.journal.sourceDocName,s=e.journal.version===2?e.journal.toPath:e.journal.destinationDocName;Y.warn({journalVersion:e.journal.version,fromPath:t,toPath:s,restoredDocNames:e.restoredDocNames},`[managed-rename] recovered pending rename ${t} -> ${s}`)}}catch(e){Y.error({err:e},`[server] managed rename recovery failed`),Fr.push(`managed-rename-recovery`)}try{let e=cleanupOrphanUploadTempfiles(s);(e.deleted>0||e.errors>0)&&Y.info({scanned:e.scanned,deleted:e.deleted,errors:e.errors},`[upload-tempfile-sweep] swept ${e.deleted} orphan tempfile(s)`)}catch(e){Y.error({err:e},`[server] upload-tempfile sweep failed`),Fr.push(`upload-tempfile-sweep`)}try{vt=await Ce.openDirectConnection(SYSTEM_DOC_NAME),Te?.emitServerInfo(oe,getActiveBranch())}catch(e){Y.error({err:e},`[server] failed to open __system__ direct connection — CC1 push disabled`),Fr.push(`cc1-push`)}let g=J?[]:CONFIG_DOC_NAMES;for(let e of g)try{let t=await Ce.openDirectConnection(e);Tt.set(e,t)}catch(t){Y.error({err:t,docName:e},`[server] failed to open ${e} direct connection — config bind degraded`),Fr.push(`config-doc:${e}`)}let S=new Map([[CONFIG_DOC_NAME_PROJECT,resolveConfigPath(`project`,s)],[CONFIG_DOC_NAME_PROJECT_LOCAL,resolveConfigPath(`project-local`,s)],[CONFIG_DOC_NAME_USER,resolveConfigPath(`user`,s,k)]]);for(let e of g){let t=S.get(e);if(t)try{Y.info({docName:e,path:t},`[config-file-watcher] starting`);let s=await startConfigFileWatcher(t,t=>{let s=Ce.documents.get(e);Y.info({docName:e,hasDocument:s!==void 0,contentLength:t.length},`[config-file-watcher] file changed`);let g=applyExternalConfigChange(s??null,e,t,ye.configPersistenceCtx);if(Y.info({docName:e,outcome:g},`[config-file-watcher] applyExternalConfigChange outcome`),e===`__config__/project`||e===`__local__/project`){let e=te();$t?.setEnabled(e).catch(t=>{Y.warn({err:t,enabled:e},`[sync] failed to apply autoSync.enabled from config`)})}let S=ne();Ie.applyConfig({enabled:S.enabled,providerFingerprint:ae(S)})});Et.push({docName:e,cleanup:s}),Y.info({docName:e,path:t},`[config-file-watcher] started`)}catch(s){Y.warn({err:s,docName:e,path:t},`[config-file-watcher] failed to start for ${e}`),Fr.push(`config-file-watcher:${e}`)}}if(!J){let e=(e,t)=>{let s=managedArtifactDocNameForPath(e,ye.managedArtifactCtx);if(!s)return;let g=applyExternalManagedArtifactChange(Ce.documents.get(s)??null,s,t,ye.managedArtifactCtx);Y.info({docName:s,outcome:g},`[managed-artifact-watcher] external change`),parseGlobalSkillBundleDoc(s)&&me.ingestGlobalSkillBundles(managedArtifactSkillsRoots(ye.managedArtifactCtx),getActiveBranch()).then(()=>{Ke(`backlinks`),Ke(`graph`)}).catch(e=>{Y.warn({err:e,docName:s},`[backlinks] global skill bundle re-ingest failed`)})};try{let t=managedArtifactSkillsRoots(ye.managedArtifactCtx),s=await startManagedArtifactWatcher(t,e);Et.push({docName:`__skill-files__`,cleanup:s}),Y.info({roots:t},`[managed-artifact-watcher] skills started`)}catch(e){Y.warn({err:e},`[managed-artifact-watcher] skills failed to start`),Fr.push(`managed-artifact-watcher:skills`)}try{let t=new Set([``]);try{for(let e of resolveProjectTemplates(s).templates)t.add(e.source_folder)}catch(e){Y.warn({err:e},`[managed-artifact-watcher] template enumeration failed; root only`)}let g=[...t].map(e=>e?resolve(s,e,`.ok`,`templates`):resolve(s,`.ok`,`templates`)),S=await startManagedArtifactWatcher(g,e,TEMPLATE_WATCH_OPTIONS);Et.push({docName:`__template-files__`,cleanup:S}),Y.info({rootCount:g.length},`[managed-artifact-watcher] templates started`)}catch(e){Y.warn({err:e},`[managed-artifact-watcher] templates failed to start`),Fr.push(`managed-artifact-watcher:templates`)}}try{let e=resolve(t,`.okignore`),g=resolve(s,`.gitignore`),S=null;try{let e=spawnSync(`git`,[`rev-parse`,`--git-common-dir`],{cwd:s,encoding:`utf-8`,timeout:5e3});if(e.status===0&&e.stdout){let t=join(resolve(s,e.stdout.trim()),`info`,`exclude`);existsSync(dirname(t))&&(S=t)}}catch{}let w=S?[e,g,S]:[e,g],E=Y;E.info({okignorePath:e,gitignorePath:g,gitInfoExcludePath:S,ephemeral:J},`[ignore-watcher] starting multi-path watcher for .okignore + .gitignore (+ .git/info/exclude when present)`);let D=J?null:await startMultiPathConfigFileWatcher(w,(t,g)=>{(async()=>{if(t===e)try{let e=applyExternalConfigChange(Ce.documents.get(`__config__/okignore`)??null,CONFIG_DOC_NAME_OKIGNORE,g,ye.configPersistenceCtx);E.info({docName:CONFIG_DOC_NAME_OKIGNORE,outcome:e},`[ignore-watcher] applyExternalConfigChange outcome`)}catch(e){E.error({err:e,changedPath:relative(s,t)},`[ignore-watcher] applyExternalConfigChange failed; rebuild proceeds independently`)}let S=await fe.rebuildIgnorePatterns();if(S.ok)E.info({changedPath:relative(s,t),patternCount:S.patternCount,nestedFileCount:S.nestedFileCount,durationMs:S.durationMs},`[ignore-watcher] rebuild succeeded — broadcasting files channel`),Te?.signal(`files`);else{let e=relative(s,t)||`.`;E.warn({changedPath:e,error:S.error.message},`[ignore-watcher] rebuild failed — emitting config-ignore-nested-error`),Te?.emitConfigIgnoreNestedError(e,S.error.message)}})().catch(e=>{E.error({err:e,changedPath:relative(s,t)||`.`},`[ignore-watcher] handler threw`)})});D&&(Et.push({docName:`__ignore-files__`,cleanup:D}),E.info({okignorePath:e,gitignorePath:g},`[ignore-watcher] multi-path watcher started`))}catch(e){Y.warn({err:e,projectDir:s,contentDir:t},`[ignore-watcher] failed to start multi-path watcher`),Fr.push(`ignore-files-watcher`)}let w=resolveGitDir(s),E=w?readBranchFromHead(w)??`main`:`main`;switchReconciledBaseScope(E),me.switchBranch(E);try{{let e=getActiveBranch();try{if(await me.loadFromDisk(e)){let t=await me.reconcileWithDisk(e);(t.added>0||t.updated>0||t.deleted>0)&&Y.info(t,`[backlinks] startup reconcile: offline changes applied`)}else await me.rebuildFromDisk(e);try{await me.ingestGlobalSkillBundles(managedArtifactSkillsRoots(ye.managedArtifactCtx),e)}catch(t){Y.warn({err:t,branch:e},`[backlinks] global skill bundle ingest failed`)}me.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist startup cache for ${e}:`,t)})}catch(t){Y.error({err:t,branch:e},`[backlinks] startup init failed; index will populate incrementally via watcher`)}}Wt=await startWatcher(t,Ht,fe);try{await ge.init()}catch(e){Y.error({err:e},`[tag-index] startup re-init failed; tag index updates incrementally via watcher events`),Fr.push(`tag-index`)}let e=0;try{ee===void 0?await seedBasenameIndex({contentDir:t,contentFilter:fe,basenameIndex:ce,onSkip:(t,s,g)=>{e++,Y.warn({reason:t,code:s,path:g},`[basename-index] skipped entry during seed (${t}${s?` ${s}`:``})`)}}):seedSingleDirBasenameIndex({contentDir:t,basenameIndex:ce,onSkip:(t,s,g)=>{e++,Y.warn({reason:t,code:s,path:g},`[basename-index] skipped entry during single-file seed (${t}${s?` ${s}`:``})`)}}),e>0&&(Y.warn({count:e},`[basename-index] startup seed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve`),Fr.push(`basename-index-partial`))}catch(e){Y.error({err:e},`[basename-index] startup seed failed`),Fr.push(`basename-index`)}}catch(e){Y.error({err:e},`[server] disk bridge watcher failed to start`),Fr.push(`file-watcher`)}try{Kt=await startHeadWatcher(s,async({trigger:e})=>{if(Y.info({trigger:e},`[batch] begin trigger=${e}`),incrementBatch(),Ce.flushPendingStores(),await ye.flushPendingGitCommit(),setBatchInProgress(!0),_e.current){let e=getActiveBranch(),t=resolveGitDir(s),g=t?readBranchFromHead(t)??e:e,S=[];for(let[e,t]of Ce.documents){if(isReservedForUserTree(e))continue;let s=null;if(t.transact(()=>{s=jt(e)},PARK_SNAPSHOT_ORIGIN),s===null)continue;let g=getReconciledBase(e)??s;S.push({docName:e,markdown:s,diskSnapshot:g})}if(S.length>0)try{let t=await parkBranch(_e.current,e,SERVICE_WRITER.id,S,g);t&&(incrementPark(),Y.info({count:S.length,branch:e,sha:t.slice(0,8)},`[history] parked ${S.length} docs on ${e} → ${t.slice(0,8)}`))}catch(e){Y.error({err:e},`[shadow] park failed`)}}},async e=>{let s=Vt.length,g=e.newBranch??`main`;if(Y.info({kind:e.batchKind,headMoved:e.headMoved,docs:s,timeout:!!e.timeout},`[batch] end kind=${e.batchKind} headMoved=${e.headMoved} docs=${s}${e.timeout?` timeout`:``}`),e.batchKind===`within-branch`){if(setBatchInProgress(!1),await Ut(),await ye.flushDeferredStores(`within-branch`),$t!==null)try{await $t.reconcileConflictsFromGit()}catch(e){Y.warn({err:e},`[head-watcher] sync engine conflict reconcile failed`)}}else{incrementBranchSwitch(),Vt.splice(0,Vt.length),switchReconciledBaseScope(g),$e!==null&&(clearTimeout($e),$e=null),me.switchBranch(g),fe.rebuildDirCount();try{let e=0;ce.clear(),await seedBasenameIndex({contentDir:t,contentFilter:fe,basenameIndex:ce,onSkip:(t,s,S)=>{e++,Y.warn({reason:t,code:s,path:S,branch:g},`[basename-index] skipped entry during branch-switch reseed (${t}${s?` ${s}`:``})`)}}),e>0&&(Y.warn({count:e,branch:g},`[basename-index] branch-switch reseed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve on this branch`),Fr.includes(`basename-index-partial`)||Fr.push(`basename-index-partial`))}catch(e){Y.error({err:e,branch:g},`[basename-index] branch-switch reseed failed`)}for(let[e,s]of Ce.documents)if(!isReservedForUserTree(e))try{let S=safeContentPath(e,t);if(!existsSync(S)){let t=getReconciledBase(e)??``,S=jt(e)??``;if(S!==t&&_e.current){let t=_e.current;queueMicrotask(()=>{saveInMemoryCheckpoint(t,L??``,{kind:`external-change-rescue`,docName:e,contents:S,label:`External change recovered @ ${new Date().toISOString()}`,branch:g,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),Y.info({docName:e},`[reconcile] rescue checkpoint saved on branch switch: ${e}`)}).catch(t=>{Y.error({docName:e,err:t},`[reconcile] rescue checkpoint write failed: ${e}`)})})}s.getMap(`lifecycle`).set(`status`,`deleted-upstream`),Y.info({docName:e,branch:g},`[branch-switch] tombstone: ${e} (not on ${g})`);continue}let w=readFileSync(S,`utf-8`);Mt(e,w),setReconciledBase(e,w),Y.info({docName:e},`[branch-switch] reset: ${e}`)}catch(t){Y.error({err:t,docName:e},`[branch-switch] failed to reset ${e}`)}Y.info({branch:g,docCount:Ce.documents.size},`[branch-switch] loaded branch ${g} (${Ce.documents.size} docs)`);try{if(await me.loadFromDisk(g)){let e=await me.reconcileWithDisk(g);(e.added>0||e.updated>0||e.deleted>0)&&Y.info(e,`[backlinks] branch-switch reconcile for ${g}`)}else await me.rebuildFromDisk(g);try{await me.ingestGlobalSkillBundles(managedArtifactSkillsRoots(ye.managedArtifactCtx),g)}catch(e){Y.warn({err:e,branch:g},`[backlinks] branch-switch global skill bundle ingest failed`)}me.saveToDisk(g).catch(e=>{console.warn(`[backlinks] Failed to persist branch cache for ${g}:`,e)})}catch(e){Y.error({err:e,branch:g},`[backlinks] branch-switch rebuild failed; backlinks may be stale`)}if(await ge.init(),_e.current&&e.batchKind===`cross-branch`){let e=0;for(let[t]of Ce.documents)if(!isReservedForUserTree(t))try{let s=await readParkedState(_e.current,g,SERVICE_WRITER.id,t);if(!s||s.markdown===s.diskSnapshot)continue;let S=getReconciledBase(t);if(!S)continue;let w=reconcile({docName:t,base:s.diskSnapshot,ours:s.markdown,theirs:S});switch(w.kind){case`merged`:case`clean`:Mt(t,w.newContent),setReconciledBase(t,w.newContent),e++;break;case`conflicts`:Mt(t,w.newContent),setReconciledBase(t,w.newContent),incrementConflict(),e++;{let e=Ce.documents.get(t);if(e){let t=e.getMap(`lifecycle`);t.set(`status`,`conflict`),t.set(`reason`,`merged-with-markers`)}}break;case`noop`:case`refused`:break}}catch(e){Y.error({err:e,docName:t},`[branch-switch] restore WIP failed for ${t}`)}e>0&&Y.info({count:e,branch:g},`[branch-switch] restored ${e} parked docs on ${g}`)}if(e.oldBranch?.startsWith(`detached-`)&&_e.current)try{let t=shadowGit(_e.current),s=(await t.raw(`for-each-ref`,`refs/wip/${e.oldBranch}/`,`--format=%(refname)`)).trim();if(s){for(let e of s.split(`
3242
- `))e&&await t.raw(`update-ref`,`-d`,e);Y.info({context:e.oldBranch},`[branch-switch] cleaned up detached context ${e.oldBranch}`)}}catch(e){Y.error({err:e},`[branch-switch] detached cleanup failed`)}setBatchInProgress(!1),await ye.flushDeferredStores(`discard-stale`),Te?.emitBranchSwitched(g)}if(e.headMoved&&e.newHead&&_e.current&&s>0){let t=L??`.`;try{let s=await commitUpstreamImport(_e.current,t,e.oldHead,e.newHead,g);incrementUpstreamImport(),Y.info({oldHead:e.oldHead?.slice(0,8)??`null`,newHead:e.newHead.slice(0,8),sha:s.slice(0,8)},`[history] upstream-import from ${e.oldHead?.slice(0,8)??`null`}..${e.newHead.slice(0,8)} → ${s.slice(0,8)}`)}catch(e){Y.error({err:e},`[shadow] upstream-import failed`)}}})}catch(e){Y.error({err:e},`[server] HEAD watcher failed to start`),Fr.push(`head-watcher`)}function D(e){for(let g of e)try{let e=toPosix(relative(t,join(s,g)));if(e.startsWith(`..`))continue;let S=stripDocExtension(e),w=Ce.documents.get(S);if(!w)continue;let E=jt(S);E===null?Y.warn({docName:S,file:g},`[sync] content conflict: serializeDoc returned null; reconciledBase snapshot skipped`):setReconciledBase(S,E);let D=w.getMap(`lifecycle`);D.set(`status`,`conflict`),D.set(`reason`,`sync-merge-conflict`),Y.info({docName:S,file:g},`[sync] marked loaded content conflict`)}catch(e){Y.warn({err:e,file:g},`[sync] failed to mark loaded content conflict`)}}let O=buildSyncCredentialArgs(H);try{$t=new SyncEngine({projectDir:s,contentDir:t,contentFilter:fe,contentRoot:L,syncEnabled:te(),credentialArgs:O,cc1Broadcaster:Te,detectGh:e.detectGh,tokenStore:e.tokenStore,checkPushPermissionFn:e.checkPushPermissionFn,setBatchInProgress:e=>{setBatchInProgress(e),e||ye.flushDeferredStores(`within-branch`).catch(e=>{Y.error({err:e},`[persistence] deferred store drain failed after sync batch`)})},onStateChange:e=>{Y.info({state:e},`[sync] state → ${e}`)},onContentConflictsDetected:D,onAutoDisable:async e=>{Y.warn({reason:e},`[sync] auto-disabled — persisting to project-local config`);let t=await writeConfigPatch({cwd:s,scope:`project-local`,patch:{autoSync:{enabled:!1}}});t.ok||Y.error({result:t,reason:e,humanError:humanFormat(t.error),configPath:resolveConfigPath(`project-local`,s)},`[sync] failed to persist auto-disable — next restart WILL re-enable sync and re-trigger the same failure. Check permissions on the config path.`)}}),await $t.start()}catch(e){Y.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),$t=null}Ke(`files`),Ke(`backlinks`),Ke(`graph`),Ke(`tags`)}return Ir().then(Ue,We),{hocuspocus:Ce,sessionManager:we,cc1Broadcaster:Te,agentFocusBroadcaster:De,agentPresenceBroadcaster:je,maintenanceCoordinator:ve,contentFilter:fe,basenameIndex:ce,serverInstanceId:oe,destroy:Mr,ready:Ge,degraded:Fr,lockDir:se,get syncEngine(){return $t}}}const SERVER_MEMORY_SCHEMA_VERSION=1,BYTES_PER_MB=1024*1024;function toMb(e){return e/BYTES_PER_MB}function captureServerMemorySnapshot(){let e=process.memoryUsage();return{schemaVersion:SERVER_MEMORY_SCHEMA_VERSION,capturedAt:new Date().toISOString(),snapshot:{rssMb:toMb(e.rss),heapTotalMb:toMb(e.heapTotal),heapUsedMb:toMb(e.heapUsed),externalMb:toMb(e.external),arrayBuffersMb:toMb(e.arrayBuffers)}}}let cachedGauge=null;onTelemetryShutdown(()=>{cachedGauge=null});function installServerMemoryGauge(){if(cachedGauge)return;let e=getMeter().createObservableGauge(`ok.server.memory.usage_megabytes`,{description:`Server process memory by section. Bounded labels: section ∈ {heap_used, heap_total, rss}.`,unit:`MB`});e.addCallback(e=>{let{snapshot:t}=captureServerMemorySnapshot();e.observe(t.heapUsedMb,{section:`heap_used`}),e.observe(t.heapTotalMb,{section:`heap_total`}),e.observe(t.rssMb,{section:`rss`})}),cachedGauge=e}const TELEMETRY_FILENAME=`tolerance-telemetry.jsonl`,TELEMETRY_PREV_FILENAME=`tolerance-telemetry.prev.jsonl`,TELEMETRY_MAX_BYTES=8*1024*1024;let appender=null,appendFailureWarned=!1;function isToleranceTelemetryEnabled(e=process.env){return e.OK_BRIDGE_TOLERANCE_TELEMETRY===`1`}function initToleranceTelemetryWriter(e){if(!isToleranceTelemetryEnabled())return;let t=getLocalDir(e);appender=new RotatingAppender({currentPath:resolve(t,TELEMETRY_FILENAME),previousPath:resolve(t,TELEMETRY_PREV_FILENAME),maxBytes:TELEMETRY_MAX_BYTES}),setToleranceTelemetryHook(e=>{let t={event:`bridge-tolerance-fire`,timestamp:e.timestamp,class:e.className,document:e.documentName??null,codeUnitPosition:e.codeUnitPosition,severity:e.severity};appender?.append(`${JSON.stringify(t)}\n`).catch(e=>{appendFailureWarned||(appendFailureWarned=!0,console.warn(`[tolerance-telemetry] append failed; further failures are silent:`,e instanceof Error?e.message:String(e)))})})}async function teardownToleranceTelemetryWriter(){setToleranceTelemetryHook(null),await appender?.drain(),appender=null,appendFailureWarned=!1}const LEGACY_RUNTIME_FILENAMES=[`server.lock`,`ui.lock`,`state.json`,`principal.json`,`sync-state.json`,`conflicts.json`,`last-spawn-error.log`],LEGACY_RUNTIME_DIRNAMES=[`cache`,`tmp`];function findLegacyRuntimeFiles(e){let t=resolve(e,LOCAL_DIR);if(!(()=>{if(!existsSync(t))return!0;try{return readdirSync(t).length===0}catch{return!0}})())return[];let s=[];for(let t of LEGACY_RUNTIME_FILENAMES)existsSync(resolve(e,t))&&s.push(t);for(let t of LEGACY_RUNTIME_DIRNAMES){let g=resolve(e,t);try{existsSync(g)&&statSync(g).isDirectory()&&s.push(`${t}/`)}catch{}}return s}function computeWorktreeAttributes(e){let t=resolveGitDirDetailed(e);switch(t.kind){case`directory`:return{kind:`main`,gitdir:t.path};case`linked`:return{kind:`linked`,gitdir:t.path};case`malformed-pointer`:return{kind:`linked`,gitdir:null};case`inaccessible`:case`absent`:return{kind:`main`,gitdir:null}}}const DEFAULT_IDLE_THRESHOLD_MS=1800*1e3,DESTROY_STEP_TIMEOUT_MS=5e3,PINO_REDACT_MAX_DEPTH=5;async function bootServer(e){let t=e.projectDir??e.contentDir,s=resolveLocalSinkConfig({projectDir:t});if(s){let e=s.telemetry.attributeDenylist,t=[];for(let s of e){t.push(s);for(let e=1;e<=PINO_REDACT_MAX_DEPTH;e++)t.push(`${`*.`.repeat(e)}${s}`)}loggerFactory.configure({pinoConfig:{fileSink:s.logs,redactPaths:t}})}initTelemetry({localSink:s?.telemetry}),initToleranceTelemetryWriter(t),installServerMemoryGauge();let{kind:g,gitdir:S}=computeWorktreeAttributes(e.projectDir??e.contentDir),w={"ok.worktree.kind":g};return S!==null&&(w[`ok.worktree.gitdir`]=normalizeFsPath(S)),withSpan(`ok.boot`,{attributes:w},async()=>bootServerInner(e))}async function bootServerInner(e){let t=e.skipAutoInit??!1,s=e.attachUiSibling??!0,g=e.idleShutdownMs,S=e.log??getLogger(`boot`),w=process.env.OK_LOCK_KIND===`mcp-spawned`||process.env.OK_LOCK_KIND===`interactive`?process.env.OK_LOCK_KIND:void 0,E=e.lockKind??w??`interactive`,{createServer:D}=await import(`node:http`),{updateServerLockPort:O}=await import(`./server-lock-8Lv6A-Xa-C_9VS9L6.mjs`),k=!1;if(!t&&e.autoInitFn)try{k=!!await e.autoInitFn()}catch(e){S.warn({err:e},`autoInitFn failed`)}let j=e.projectDir??e.contentDir,F=resolve(j,`.ok`);if(!existsSync(resolve(F,`config.yml`)))throw new MissingOkConfigError(existsSync(F)?`config`:`okdir`,j);existsSync(resolve(F,`.gitignore`))||console.warn("[boot] Note: .ok/.gitignore is missing — per-machine state files in .ok/ may show up as untracked changes. Run `ok init` to add the recommended ignore entries.");let L=e.gitPreflight??assertGitAvailable;try{e.gitEnabled!==!1&&L()}catch(e){if(e instanceof GitNotAvailableError||e instanceof GitTooOldError){let t=e instanceof GitTooOldError?e.detected:``,s=e instanceof GitTooOldError?`too_old`:`not_available`;emitPreflightFailureSpan(e),S.warn({event:`git_preflight_fail`,platform:e.platform,reason:s,detectedVersion:t},s===`not_available`?`git binary not found`:`git binary too old`),process.stderr.write(`${e.message}\n`)}throw await shutdownTelemetry(),await Promise.race([teardownToleranceTelemetryWriter(),new Promise(e=>setTimeout(e,DESTROY_STEP_TIMEOUT_MS))]),e}let B=findLegacyRuntimeFiles(F);B.length>0&&console.warn(`[boot] Found legacy runtime files at .ok/${B.join(`, `)}. Delete .ok/ and re-init — these files moved to .ok/${LOCAL_DIR}/.`);let H=createServer$1({contentDir:e.contentDir,projectDir:e.projectDir,contentRoot:e.contentRoot,port:e.port,host:e.host,quiet:e.quiet??!1,debounce:e.debounce,maxDebounce:e.maxDebounce,gitEnabled:e.gitEnabled,commitDebounceMs:e.commitDebounceMs,wipRef:e.wipRef,enableTestRoutes:e.enableTestRoutes,shadowRepo:e.shadowRepo,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:E,skipStateManifestCheck:e.skipStateManifestCheck,detectGh:e.detectGh,tokenStore:e.tokenStore,embeddingsKeyStore:e.embeddingsKeyStore,singleDocRelPath:e.singleDocRelPath,ephemeral:e.ephemeral}),{hocuspocus:q,destroy:ee,ready:J,degraded:Y,lockDir:te,sessionManager:ne,agentFocusBroadcaster:ae,agentPresenceBroadcaster:oe,maintenanceCoordinator:se}=H,ce=(()=>{let t=e.host??`localhost`;return t===`0.0.0.0`||t===`::`?`localhost`:t.includes(`:`)&&!t.startsWith(`[`)?`[${t}]`:t})(),ue=e.port??0,de=e.ephemeral?void 0:createMcpHttpHandler({contentDir:e.contentDir,projectDir:e.projectDir??e.contentDir,config:e.config,getServerUrl:()=>`http://${ce}:${ue}`,log:S}),fe=D();fe.headersTimeout=3e4,fe.requestTimeout=6e4;let me=e.serveContentAssets?createAssetServeMiddleware({contentFilter:H.contentFilter,contentSirv:build_default(e.contentDir,{dev:!0,dotfiles:!1}),inlineExtensions:INLINE_RENDERABLE_EXTENSIONS,assetExtensions:ASSET_EXTENSIONS,blocklistExtensions:EXECUTABLE_BLOCKLIST_EXTENSIONS}):void 0,ge=!1;if(e.reactShellDistDir)try{acquireUiLock(te,{port:0,worktreeRoot:e.projectDir??e.contentDir}),ge=!0}catch(e){if(e instanceof UiLockCollisionError)S.info({event:`ui-lock-yielded-to-live-holder`,pid:process.pid,existingPid:e.existing.pid,existingPort:e.existing.port,lockDir:te},`ui.lock already held by a live process — yielding (advertisement is fulfilled)`);else throw await ee().catch(()=>{}),e}let _e=e.reactShellDistDir?build_default(e.reactShellDistDir,{single:!0,gzip:!0,immutable:!0}):void 0,ve=mountMcpAndApi({httpServer:fe,hocuspocus:q,mcpHttpHandler:de,log:S,sessionManager:ne,agentFocusBroadcaster:ae,agentPresenceBroadcaster:oe,maintenanceCoordinator:se,keepaliveGraceMs:e.keepaliveGraceMs,contentAssetMiddleware:me,reactShellMiddleware:_e,ephemeral:e.ephemeral}),ye=async()=>{throw Error(`bootServer: destroy() invoked before initialization — boot did not complete`)},Ce=null;g!==null&&(Ce=attachIdleShutdown({httpServer:fe,thresholdMs:g??DEFAULT_IDLE_THRESHOLD_MS,log:S,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await ye()})})),await restoreLifecycleFromConflictsJson({hocuspocus:q,projectDir:e.projectDir??e.contentDir,log:S});try{await new Promise((t,s)=>{let g=e=>s(e);fe.once(`error`,g),fe.listen(e.port,e.host,()=>{fe.removeListener(`error`,g),t()})})}catch(e){if(ge)try{releaseUiLock(te)}catch(e){S.warn({err:e},`releaseUiLock failed during listen-error cleanup`)}throw await ee().catch(()=>{}),e}let we=fe.address(),Te=typeof we==`object`&&we?we.port:e.port??0;if(ue=Te,O(te,Te),ge&&updateUiLockPort(te,Te),s&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:te,log:S})}catch(e){S.warn({err:e},`spawnUiSiblingFn failed`)}let De=!1,je=async(e,t)=>{let s;try{await Promise.race([t(),new Promise((t,g)=>{s=setTimeout(()=>{g(Error(`${e} timed out after ${DESTROY_STEP_TIMEOUT_MS}ms`))},DESTROY_STEP_TIMEOUT_MS),s.unref?.()})])}finally{s!==void 0&&clearTimeout(s)}};ye=async()=>{if(De)return;De=!0;let e=[],t=async(t,s)=>{try{await je(t,s)}catch(s){e.push(s),S.warn({err:s,step:t},`bootServer destroy step failed`)}};try{Ce?.detach()}catch(t){e.push(t),S.warn({err:t,step:`idleHandle.detach`},`bootServer destroy step failed`)}if(await t(`mount.shutdown`,()=>ve.shutdown()),de!==void 0&&await t(`mcpHttpHandler.close`,()=>de.close()),await t(`mount.wss.close`,()=>new Promise((e,t)=>{ve.wss.close(s=>s?t(s):e())})),await t(`httpServer.closeAllConnections`,async()=>{fe.closeAllConnections?.()}),await t(`httpServer.close`,()=>new Promise((e,t)=>{fe.close(s=>s&&s.code!==`ERR_SERVER_NOT_RUNNING`?t(s):e())})),await t(`destroyHocuspocus`,()=>ee()),ge&&await t(`releaseUiLock`,async()=>releaseUiLock(te)),await t(`shutdownTelemetry`,()=>shutdownTelemetry()),await t(`teardownToleranceTelemetry`,()=>teardownToleranceTelemetryWriter()),await t(`flushLogFileSinks`,()=>loggerFactory.flushAllFileSinks()),e.length>0)throw AggregateError(e,`bootServer destroy completed with errors`)};try{let t=await reconcileSkillInstalls({projectDir:j,skillsRoot:resolve(e.contentDir,`.ok`,`skills`)}),s=t.healed.length+t.adopted.length+t.replaced.length+t.collided.length+t.orphansRemoved.length;s>0&&S.info?.({event:`installed-skills-reconciled`,healed:t.healed.length,adopted:t.adopted.length,replaced:t.replaced.length,collided:t.collided.length,orphansRemoved:t.orphansRemoved.length},`Reconciled ${s} editor skill entr${s===1?`y`:`ies`} to the symlink model.`)}catch(e){S.warn?.({event:`installed-skills-reconcile-failed`,error:String(e)},`Installed-skills reconcile failed (non-fatal).`)}return{httpServer:fe,destroy:ye,lockDir:te,contentDir:e.contentDir,port:Te,ready:J,degraded:Y,didAutoInit:k,serverInstance:H}}async function restoreLifecycleFromConflictsJson(e){let{hocuspocus:t,projectDir:s,log:g}=e,S,w;try{S=new ConflictStore(s),w=S.list()}catch(e){g.warn({err:e,projectDir:s},`[boot] lifecycle restore: failed to read conflicts.json — skipping`);return}if(w.length===0)return;let E=null;try{let e=resolveGitDir(s),t=e?join(e,`MERGE_HEAD`):null;if(!t||!existsSync(t)){S.clear(),console.warn(JSON.stringify({event:`lifecycle-restore-cleared-stale-conflicts`,reason:`no-merge-head`,count:w.length}));return}let g=(await simpleGit({baseDir:s,timeout:{block:5e3}}).raw([`diff`,`--name-only`,`--diff-filter=U`])).trim();E=new Set(g?g.split(`
3246
+ `))e&&await t.raw(`update-ref`,`-d`,e);Y.info({context:e.oldBranch},`[branch-switch] cleaned up detached context ${e.oldBranch}`)}}catch(e){Y.error({err:e},`[branch-switch] detached cleanup failed`)}setBatchInProgress(!1),await ye.flushDeferredStores(`discard-stale`),Te?.emitBranchSwitched(g)}if(e.headMoved&&e.newHead&&_e.current&&s>0){let t=L??`.`;try{let s=await commitUpstreamImport(_e.current,t,e.oldHead,e.newHead,g);incrementUpstreamImport(),Y.info({oldHead:e.oldHead?.slice(0,8)??`null`,newHead:e.newHead.slice(0,8),sha:s.slice(0,8)},`[history] upstream-import from ${e.oldHead?.slice(0,8)??`null`}..${e.newHead.slice(0,8)} → ${s.slice(0,8)}`)}catch(e){Y.error({err:e},`[shadow] upstream-import failed`)}}})}catch(e){Y.error({err:e},`[server] HEAD watcher failed to start`),Fr.push(`head-watcher`)}function D(e){for(let g of e)try{let e=toPosix(relative(t,join(s,g)));if(e.startsWith(`..`))continue;let S=stripDocExtension(e),w=Ce.documents.get(S);if(!w)continue;let E=jt(S);E===null?Y.warn({docName:S,file:g},`[sync] content conflict: serializeDoc returned null; reconciledBase snapshot skipped`):setReconciledBase(S,E);let D=w.getMap(`lifecycle`);D.set(`status`,`conflict`),D.set(`reason`,`sync-merge-conflict`),Y.info({docName:S,file:g},`[sync] marked loaded content conflict`)}catch(e){Y.warn({err:e,file:g},`[sync] failed to mark loaded content conflict`)}}let O=buildSyncCredentialArgs(H);try{$t=new SyncEngine({projectDir:s,contentDir:t,contentFilter:fe,contentRoot:L,syncEnabled:te(),credentialArgs:O,cc1Broadcaster:Te,detectGh:e.detectGh,tokenStore:e.tokenStore,checkPushPermissionFn:e.checkPushPermissionFn,setBatchInProgress:e=>{setBatchInProgress(e),e||ye.flushDeferredStores(`within-branch`).catch(e=>{Y.error({err:e},`[persistence] deferred store drain failed after sync batch`)})},onStateChange:e=>{Y.info({state:e},`[sync] state → ${e}`)},onContentConflictsDetected:D,onAutoDisable:async e=>{Y.warn({reason:e},`[sync] auto-disabled — persisting to project-local config`);let t=await writeConfigPatch({cwd:s,scope:`project-local`,patch:{autoSync:{enabled:!1}}});t.ok||Y.error({result:t,reason:e,humanError:humanFormat(t.error),configPath:resolveConfigPath(`project-local`,s)},`[sync] failed to persist auto-disable — next restart WILL re-enable sync and re-trigger the same failure. Check permissions on the config path.`)}}),await $t.start()}catch(e){Y.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),$t=null}Ke(`files`),Ke(`backlinks`),Ke(`graph`),Ke(`tags`)}return Ir().then(Ue,We),{hocuspocus:Ce,sessionManager:we,cc1Broadcaster:Te,agentFocusBroadcaster:De,agentPresenceBroadcaster:je,maintenanceCoordinator:ve,contentFilter:fe,basenameIndex:ce,serverInstanceId:oe,destroy:Mr,ready:Ge,degraded:Fr,lockDir:se,get syncEngine(){return $t}}}const SERVER_MEMORY_SCHEMA_VERSION=1,BYTES_PER_MB=1024*1024;function toMb(e){return e/BYTES_PER_MB}function captureServerMemorySnapshot(){let e=process.memoryUsage();return{schemaVersion:SERVER_MEMORY_SCHEMA_VERSION,capturedAt:new Date().toISOString(),snapshot:{rssMb:toMb(e.rss),heapTotalMb:toMb(e.heapTotal),heapUsedMb:toMb(e.heapUsed),externalMb:toMb(e.external),arrayBuffersMb:toMb(e.arrayBuffers)}}}let cachedGauge=null;onTelemetryShutdown(()=>{cachedGauge=null});function installServerMemoryGauge(){if(cachedGauge)return;let e=getMeter().createObservableGauge(`ok.server.memory.usage_megabytes`,{description:`Server process memory by section. Bounded labels: section ∈ {heap_used, heap_total, rss}.`,unit:`MB`});e.addCallback(e=>{let{snapshot:t}=captureServerMemorySnapshot();e.observe(t.heapUsedMb,{section:`heap_used`}),e.observe(t.heapTotalMb,{section:`heap_total`}),e.observe(t.rssMb,{section:`rss`})}),cachedGauge=e}const TELEMETRY_FILENAME=`tolerance-telemetry.jsonl`,TELEMETRY_PREV_FILENAME=`tolerance-telemetry.prev.jsonl`,TELEMETRY_MAX_BYTES=8*1024*1024;let appender=null,appendFailureWarned=!1;function isToleranceTelemetryEnabled(e=process.env){return e.OK_BRIDGE_TOLERANCE_TELEMETRY===`1`}function initToleranceTelemetryWriter(e){if(!isToleranceTelemetryEnabled())return;let t=getLocalDir(e);appender=new RotatingAppender({currentPath:resolve(t,TELEMETRY_FILENAME),previousPath:resolve(t,TELEMETRY_PREV_FILENAME),maxBytes:TELEMETRY_MAX_BYTES}),setToleranceTelemetryHook(e=>{let t={event:`bridge-tolerance-fire`,timestamp:e.timestamp,class:e.className,document:e.documentName??null,codeUnitPosition:e.codeUnitPosition,severity:e.severity};appender?.append(`${JSON.stringify(t)}\n`).catch(e=>{appendFailureWarned||(appendFailureWarned=!0,console.warn(`[tolerance-telemetry] append failed; further failures are silent:`,e instanceof Error?e.message:String(e)))})})}async function teardownToleranceTelemetryWriter(){setToleranceTelemetryHook(null),await appender?.drain(),appender=null,appendFailureWarned=!1}const LEGACY_RUNTIME_FILENAMES=[`server.lock`,`ui.lock`,`state.json`,`principal.json`,`sync-state.json`,`conflicts.json`,`last-spawn-error.log`],LEGACY_RUNTIME_DIRNAMES=[`cache`,`tmp`];function findLegacyRuntimeFiles(e){let t=resolve(e,LOCAL_DIR);if(!(()=>{if(!existsSync(t))return!0;try{return readdirSync(t).length===0}catch{return!0}})())return[];let s=[];for(let t of LEGACY_RUNTIME_FILENAMES)existsSync(resolve(e,t))&&s.push(t);for(let t of LEGACY_RUNTIME_DIRNAMES){let g=resolve(e,t);try{existsSync(g)&&statSync(g).isDirectory()&&s.push(`${t}/`)}catch{}}return s}function computeWorktreeAttributes(e){let t=resolveGitDirDetailed(e);switch(t.kind){case`directory`:return{kind:`main`,gitdir:t.path};case`linked`:return{kind:`linked`,gitdir:t.path};case`malformed-pointer`:return{kind:`linked`,gitdir:null};case`inaccessible`:case`absent`:return{kind:`main`,gitdir:null}}}const DEFAULT_IDLE_THRESHOLD_MS=1800*1e3,DESTROY_STEP_TIMEOUT_MS=5e3,PINO_REDACT_MAX_DEPTH=5;async function bootServer(e){let t=e.projectDir??e.contentDir,s=resolveLocalSinkConfig({projectDir:t});if(s){let e=s.telemetry.attributeDenylist,t=[];for(let s of e){t.push(s);for(let e=1;e<=PINO_REDACT_MAX_DEPTH;e++)t.push(`${`*.`.repeat(e)}${s}`)}loggerFactory.configure({pinoConfig:{fileSink:s.logs,redactPaths:t}})}initTelemetry({localSink:s?.telemetry}),initToleranceTelemetryWriter(t),installServerMemoryGauge();let{kind:g,gitdir:S}=computeWorktreeAttributes(e.projectDir??e.contentDir),w={"ok.worktree.kind":g};return S!==null&&(w[`ok.worktree.gitdir`]=normalizeFsPath(S)),withSpan(`ok.boot`,{attributes:w},async()=>bootServerInner(e))}async function bootServerInner(e){let t=e.skipAutoInit??!1,s=e.attachUiSibling??!0,g=e.idleShutdownMs,S=e.log??getLogger(`boot`),w=process.env.OK_LOCK_KIND===`mcp-spawned`||process.env.OK_LOCK_KIND===`interactive`?process.env.OK_LOCK_KIND:void 0,E=e.lockKind??w??`interactive`,{createServer:D}=await import(`node:http`),{updateServerLockPort:O}=await import(`./server-lock-8Lv6A-Xa-iDqi_bbE.mjs`),k=!1;if(!t&&e.autoInitFn)try{k=!!await e.autoInitFn()}catch(e){S.warn({err:e},`autoInitFn failed`)}let j=e.projectDir??e.contentDir,F=resolve(j,`.ok`);if(!existsSync(resolve(F,`config.yml`)))throw new MissingOkConfigError(existsSync(F)?`config`:`okdir`,j);existsSync(resolve(F,`.gitignore`))||console.warn("[boot] Note: .ok/.gitignore is missing — per-machine state files in .ok/ may show up as untracked changes. Run `ok init` to add the recommended ignore entries.");let L=e.gitPreflight??assertGitAvailable;try{e.gitEnabled!==!1&&L()}catch(e){if(e instanceof GitNotAvailableError||e instanceof GitTooOldError){let t=e instanceof GitTooOldError?e.detected:``,s=e instanceof GitTooOldError?`too_old`:`not_available`;emitPreflightFailureSpan(e),S.warn({event:`git_preflight_fail`,platform:e.platform,reason:s,detectedVersion:t},s===`not_available`?`git binary not found`:`git binary too old`),process.stderr.write(`${e.message}\n`)}throw await shutdownTelemetry(),await Promise.race([teardownToleranceTelemetryWriter(),new Promise(e=>setTimeout(e,DESTROY_STEP_TIMEOUT_MS))]),e}let B=findLegacyRuntimeFiles(F);B.length>0&&console.warn(`[boot] Found legacy runtime files at .ok/${B.join(`, `)}. Delete .ok/ and re-init — these files moved to .ok/${LOCAL_DIR}/.`);let H=createServer$1({contentDir:e.contentDir,projectDir:e.projectDir,contentRoot:e.contentRoot,port:e.port,host:e.host,quiet:e.quiet??!1,debounce:e.debounce,maxDebounce:e.maxDebounce,gitEnabled:e.gitEnabled,commitDebounceMs:e.commitDebounceMs,wipRef:e.wipRef,enableTestRoutes:e.enableTestRoutes,shadowRepo:e.shadowRepo,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:E,skipStateManifestCheck:e.skipStateManifestCheck,detectGh:e.detectGh,tokenStore:e.tokenStore,embeddingsKeyStore:e.embeddingsKeyStore,singleDocRelPath:e.singleDocRelPath,ephemeral:e.ephemeral}),{hocuspocus:q,destroy:ee,ready:J,degraded:Y,lockDir:te,sessionManager:ne,agentFocusBroadcaster:ae,agentPresenceBroadcaster:oe,maintenanceCoordinator:se}=H,ce=(()=>{let t=e.host??`localhost`;return t===`0.0.0.0`||t===`::`?`localhost`:t.includes(`:`)&&!t.startsWith(`[`)?`[${t}]`:t})(),ue=e.port??0,de=e.ephemeral?void 0:createMcpHttpHandler({contentDir:e.contentDir,projectDir:e.projectDir??e.contentDir,config:e.config,getServerUrl:()=>`http://${ce}:${ue}`,log:S}),fe=D();fe.headersTimeout=3e4,fe.requestTimeout=6e4;let me=e.serveContentAssets?createAssetServeMiddleware({contentFilter:H.contentFilter,contentSirv:build_default(e.contentDir,{dev:!0,dotfiles:!1}),inlineExtensions:INLINE_RENDERABLE_EXTENSIONS,assetExtensions:ASSET_EXTENSIONS,blocklistExtensions:EXECUTABLE_BLOCKLIST_EXTENSIONS}):void 0,ge=!1;if(e.reactShellDistDir)try{acquireUiLock(te,{port:0,worktreeRoot:e.projectDir??e.contentDir}),ge=!0}catch(e){if(e instanceof UiLockCollisionError)S.info({event:`ui-lock-yielded-to-live-holder`,pid:process.pid,existingPid:e.existing.pid,existingPort:e.existing.port,lockDir:te},`ui.lock already held by a live process — yielding (advertisement is fulfilled)`);else throw await ee().catch(()=>{}),e}let _e=e.reactShellDistDir?build_default(e.reactShellDistDir,{single:!0,gzip:!0,immutable:!0}):void 0,ve=mountMcpAndApi({httpServer:fe,hocuspocus:q,mcpHttpHandler:de,log:S,sessionManager:ne,agentFocusBroadcaster:ae,agentPresenceBroadcaster:oe,maintenanceCoordinator:se,keepaliveGraceMs:e.keepaliveGraceMs,contentAssetMiddleware:me,reactShellMiddleware:_e,ephemeral:e.ephemeral}),ye=async()=>{throw Error(`bootServer: destroy() invoked before initialization — boot did not complete`)},Ce=null;g!==null&&(Ce=attachIdleShutdown({httpServer:fe,thresholdMs:g??DEFAULT_IDLE_THRESHOLD_MS,log:S,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await ye()})})),await restoreLifecycleFromConflictsJson({hocuspocus:q,projectDir:e.projectDir??e.contentDir,log:S});try{await new Promise((t,s)=>{let g=e=>s(e);fe.once(`error`,g),fe.listen(e.port,e.host,()=>{fe.removeListener(`error`,g),t()})})}catch(e){if(ge)try{releaseUiLock(te)}catch(e){S.warn({err:e},`releaseUiLock failed during listen-error cleanup`)}throw await ee().catch(()=>{}),e}let we=fe.address(),Te=typeof we==`object`&&we?we.port:e.port??0;if(ue=Te,O(te,Te),ge&&updateUiLockPort(te,Te),s&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:te,log:S})}catch(e){S.warn({err:e},`spawnUiSiblingFn failed`)}let De=!1,je=async(e,t)=>{let s;try{await Promise.race([t(),new Promise((t,g)=>{s=setTimeout(()=>{g(Error(`${e} timed out after ${DESTROY_STEP_TIMEOUT_MS}ms`))},DESTROY_STEP_TIMEOUT_MS),s.unref?.()})])}finally{s!==void 0&&clearTimeout(s)}};ye=async()=>{if(De)return;De=!0;let e=[],t=async(t,s)=>{try{await je(t,s)}catch(s){e.push(s),S.warn({err:s,step:t},`bootServer destroy step failed`)}};try{Ce?.detach()}catch(t){e.push(t),S.warn({err:t,step:`idleHandle.detach`},`bootServer destroy step failed`)}if(await t(`mount.shutdown`,()=>ve.shutdown()),de!==void 0&&await t(`mcpHttpHandler.close`,()=>de.close()),await t(`mount.wss.close`,()=>new Promise((e,t)=>{ve.wss.close(s=>s?t(s):e())})),await t(`httpServer.closeAllConnections`,async()=>{fe.closeAllConnections?.()}),await t(`httpServer.close`,()=>new Promise((e,t)=>{fe.close(s=>s&&s.code!==`ERR_SERVER_NOT_RUNNING`?t(s):e())})),await t(`destroyHocuspocus`,()=>ee()),ge&&await t(`releaseUiLock`,async()=>releaseUiLock(te)),await t(`shutdownTelemetry`,()=>shutdownTelemetry()),await t(`teardownToleranceTelemetry`,()=>teardownToleranceTelemetryWriter()),await t(`flushLogFileSinks`,()=>loggerFactory.flushAllFileSinks()),e.length>0)throw AggregateError(e,`bootServer destroy completed with errors`)};try{let t=await reconcileSkillInstalls({projectDir:j,skillsRoot:resolve(e.contentDir,`.ok`,`skills`)}),s=t.healed.length+t.adopted.length+t.replaced.length+t.collided.length+t.orphansRemoved.length;s>0&&S.info?.({event:`installed-skills-reconciled`,healed:t.healed.length,adopted:t.adopted.length,replaced:t.replaced.length,collided:t.collided.length,orphansRemoved:t.orphansRemoved.length},`Reconciled ${s} editor skill entr${s===1?`y`:`ies`} to the symlink model.`)}catch(e){S.warn?.({event:`installed-skills-reconcile-failed`,error:String(e)},`Installed-skills reconcile failed (non-fatal).`)}return{httpServer:fe,destroy:ye,lockDir:te,contentDir:e.contentDir,port:Te,ready:J,degraded:Y,didAutoInit:k,serverInstance:H}}async function restoreLifecycleFromConflictsJson(e){let{hocuspocus:t,projectDir:s,log:g}=e,S,w;try{S=new ConflictStore(s),w=S.list()}catch(e){g.warn({err:e,projectDir:s},`[boot] lifecycle restore: failed to read conflicts.json — skipping`);return}if(w.length===0)return;let E=null;try{let e=resolveGitDir(s),t=e?join(e,`MERGE_HEAD`):null;if(!t||!existsSync(t)){S.clear(),console.warn(JSON.stringify({event:`lifecycle-restore-cleared-stale-conflicts`,reason:`no-merge-head`,count:w.length}));return}let g=(await simpleGit({baseDir:s,timeout:{block:5e3}}).raw([`diff`,`--name-only`,`--diff-filter=U`])).trim();E=new Set(g?g.split(`
3243
3247
  `).map(e=>e.trim()).filter(Boolean):[])}catch(e){g.warn({err:e,projectDir:s},`[boot] lifecycle restore: git unmerged probe failed — restoring all entries`)}if(E!==null){let e=0;for(let t of w)E.has(t.file)||(S.removeConflict(t.file),e++);if(e>0&&console.warn(JSON.stringify({event:`lifecycle-restore-pruned-resolved-entries`,pruned:e,remaining:w.length-e})),w=w.filter(e=>E?.has(e.file)),w.length===0)return}for(let e of w){let s=stripDocExtension(e.file),S=null,w=!1;try{S=await t.openDirectConnection(s);let e=S.document;if(!e)continue;let g=e.getMap(`lifecycle`);g.set(`status`,`conflict`),g.set(`reason`,`conflict-markers`),w=!0,console.warn(JSON.stringify({event:`lifecycle-restored-from-conflicts-json`,"doc.name":s}))}catch(e){g.warn({err:e,docName:s},`[boot] lifecycle restore: failed to set lifecycle for doc — skipping`)}finally{if(S)try{await S.disconnect()}catch(e){g.warn({err:e,docName:s,restored:w},`[boot] lifecycle restore: disconnect failed after lifecycle write`)}}}}const ConfigSchema=ConfigSchema$1;function detectClaudeDesktopPresence(e={}){let t=e.home??homedir(),s=e.platformName??process.platform,g=e.env??process.env;return s===`darwin`?existsSync(join(t,`Library`,`Application Support`,`Claude`)):s===`win32`?existsSync(join(g.APPDATA??join(t,`AppData`,`Roaming`),`Claude`)):!1}const OK_LOGS_DIR=join(homedir(),`.ok`,`logs`),MAX_ROTATED_FILES=2,MAX_AGE_DAYS=7,MAX_DIR_SIZE_BYTES=45*1024*1024,REDACT_PATHS=[`authorization`,`password`,`token`,`apiKey`,`secret`,`*.authorization`,`*.password`,`*.token`,`*.apiKey`,`*.secret`];function resolveLogLevel(){let e=process.env.OK_LOG_LEVEL??process.env.LOG_LEVEL;if(e){let t=[`fatal`,`error`,`warn`,`info`,`debug`],s=e.toLowerCase();if(t.includes(s))return s}return process.env.NODE_ENV===`test`?`silent`:`info`}function ensureDir(e){mkdirSync(e,{recursive:!0})}function todayDateString(){return new Date().toISOString().slice(0,10)}function rotateIfNeeded(e){try{if(statSync(e).size<5242880)return}catch{return}for(let t=MAX_ROTATED_FILES;t>=1;t--){let s=t===1?e:`${e}.${t-1}`,g=`${e}.${t}`;try{renameSync(s,g)}catch{}}try{unlinkSync(`${e}.${MAX_ROTATED_FILES+1}`)}catch{}}function pruneLogsDir(e){try{let t=Date.now(),s=MAX_AGE_DAYS*24*60*60*1e3,g=readdirSync(e).filter(e=>e.endsWith(`.log`)||/\.log\.\d+$/.test(e)).map(t=>{try{let s=statSync(join(e,t));return{name:t,mtime:s.mtimeMs,size:s.size}}catch{return null}}).filter(Boolean);for(let S of g)if(t-S.mtime>s)try{unlinkSync(join(e,S.name))}catch{}let S=g.filter(e=>t-e.mtime<=s).sort((e,t)=>e.mtime-t.mtime),w=S.reduce((e,t)=>e+t.size,0);for(let t of S){if(w<=MAX_DIR_SIZE_BYTES)break;try{unlinkSync(join(e,t.name)),w-=t.size}catch{}}}catch{}}function createFileLogger(e){ensureDir(OK_LOGS_DIR);let t=todayDateString(),s=e.filePath??join(OK_LOGS_DIR,`${e.name}.${t}.log`);rotateIfNeeded(s),(e._setTimeout??setTimeout)(()=>pruneLogsDir(OK_LOGS_DIR),5e3).unref();let g=import_pino.default.destination({dest:s,append:!0,sync:!0});return(0,import_pino.default)({level:resolveLogLevel(),name:e.name,redact:{paths:REDACT_PATHS,censor:`[REDACTED]`},base:{pid:process.pid,hostname:void 0,runtime:`cli`,project:e.project??`<no-project>`},timestamp:import_pino.default.stdTimeFunctions.isoTime,...e.additionalOptions},g)}function flushFileLogger(e,t=250){return new Promise(s=>{if(!e){s();return}let g=e[import_pino.default.symbols.streamSym],S=!1,w=()=>{S||(S=!0,s())};if(!g||typeof g.flushSync!=`function`){w();return}let E=()=>{try{g.flushSync?.()}catch{}w()},D=setTimeout(w,t);typeof D.unref==`function`&&D.unref(),typeof g.fd==`number`&&g.fd>=0?(clearTimeout(D),E()):typeof g.once==`function`?g.once(`ready`,()=>{clearTimeout(D),E()}):(clearTimeout(D),E())})}function getLogFilePath(e){return join(OK_LOGS_DIR,`${e}.${todayDateString()}.log`)}function getLogsDir(){return OK_LOGS_DIR}const ANCESTOR_WALK_DEPTH_LIMIT=30,GIT_MARKER=`.git`;function findEnclosingGitRoot(e){let t=resolve(e),s=0;for(;s<ANCESTOR_WALK_DEPTH_LIMIT;){let e=!1;try{e=existsSync(resolve(t,GIT_MARKER))}catch{e=!1}if(e)return{gitRoot:t,distance:s};let g=dirname(t);if(g===t)return null;t=g,s+=1}return null}const execFileAsync=promisify(execFile),log=getLogger(`project-git`);var ProjectGitInitError=class extends Error{stderr;constructor(e,t=``,s){super(e,s),this.name=`ProjectGitInitError`,this.stderr=t}};async function isInsideExistingWorkTree(e){try{let{stdout:t}=await execFileAsync(`git`,[`rev-parse`,`--is-inside-work-tree`],{cwd:e});return t.trim()===`true`}catch{return!1}}async function ensureProjectGit(e){let t=resolve(e),s=resolve(t,`.git`),g=resolve(s,`HEAD`),S=!1;if(existsSync(s)){if(!statSync(s).isDirectory()||existsSync(g))return{didInit:!1};log.info({},`detected partial .git/ — running git init to repair`),S=!0}else if(await isInsideExistingWorkTree(t))return{didInit:!1};let w=``;try{w=(await execFileAsync(`git`,[`init`,`--initial-branch=main`,t])).stderr??``}catch(e){let s=typeof e==`object`&&e&&`stderr`in e?String(e.stderr??``):``;throw new ProjectGitInitError(`git init failed at ${t}: ${e instanceof Error?e.message:String(e)}`,s,{cause:e})}if(!existsSync(g))throw new ProjectGitInitError(`git init reported success but ${s}/HEAD is missing (partial init detected)`,w);return S?(log.info({path:t},`backfilled missing .git/HEAD`),{didInit:!0,repaired:!0}):(log.info({path:t,branch:`main`},`initialized .git/`),{didInit:!0})}async function resolvePackageVersion(e,t){let s;try{s=createRequire(t).resolve(e)}catch(e){if(e?.code===`MODULE_NOT_FOUND`)return;throw e}for(let t=dirname(s),g=0;g<32;g+=1){let s=join(t,`package.json`);if(existsSync(s))try{let t=JSON.parse(await readFile$1(s,`utf-8`));if(t.name===e&&typeof t.version==`string`)return t.version}catch{}let g=dirname(t);if(g===t)return;t=g}}const MAX_CAUSE_DEPTH=5,HOME_PATH_PATTERNS=[{regex:/\/Users\/[^/]+\//g,replacement:`~/`},{regex:/\/home\/[^/]+\//g,replacement:`~/`},{regex:/C:\\\\Users\\\\[^\\\\]+\\\\/g,replacement:`~\\`},{regex:/C:\\Users\\[^\\]+\\/g,replacement:`~\\`}];function scrubPaths(e){if(e===void 0)return;let t=e;for(let{regex:e,replacement:s}of HOME_PATH_PATTERNS)t=t.replace(e,s);return t}function serializeError(e,t=0,s=new WeakSet){if(t>=MAX_CAUSE_DEPTH)return{name:`SerializedError.CauseDepthExceeded`,message:`cause chain depth > ${MAX_CAUSE_DEPTH}; truncated`};if(typeof e==`object`&&e){if(s.has(e))return{name:`SerializedError.CauseCycle`,message:`cyclic cause; truncated`};s.add(e)}if(e instanceof Error)return{name:e.name,message:scrubPaths(e.message)??``,stack:scrubPaths(e.stack),code:e.code,cause:e.cause===void 0?void 0:serializeError(e.cause,t+1,s)};if(e==null)return{name:`UnknownError`,message:String(e)};if(typeof e==`string`)return{name:`StringError`,message:scrubPaths(e)??e};if(typeof e==`object`){let g=e;return{name:String(g.name??`ObjectError`),message:scrubPaths(String(g.message??``))??``,stack:scrubPaths(g.stack),code:g.code,cause:g.cause===void 0?void 0:serializeError(g.cause,t+1,s)}}return{name:`UnknownError`,message:String(e)}}var SingleFileNotFoundError=class extends Error{constructor(e){super(`File not found: ${e}`),this.filePath=e,this.name=`SingleFileNotFoundError`}},SingleFileNotAFileError=class extends Error{constructor(e){super(`Not a file: ${e}. \`ok <file>\` opens a single markdown file.`),this.filePath=e,this.name=`SingleFileNotAFileError`}},SingleFileNotMarkdownError=class extends Error{constructor(e){super(`OpenKnowledge edits markdown files (.md / .mdx): ${e}`),this.filePath=e,this.name=`SingleFileNotMarkdownError`}};function prepareSingleFileOpen(e){if(!isSupportedDocFile(e))throw new SingleFileNotMarkdownError(e);let t;try{t=realpathSync(resolve(e))}catch(t){throw t.code===`ENOENT`?new SingleFileNotFoundError(e):t}if(!statSync(t).isFile())throw new SingleFileNotAFileError(e);let s=dirname(t),g=findEnclosingProjectRoot(s);if(g){let e=g.rootPath;return{mode:`project`,projectRoot:e,docName:stripDocExtension(relative(resolveProjectContentDir(e),t).split(sep).join(`/`)),canonicalFilePath:t}}let S=basename(t);return{mode:`ephemeral`,canonicalFilePath:t,contentDir:s,singleDocRelPath:S,docName:stripDocExtension(S)}}function resolveProjectContentDir(e){return resolve(e,readConfigSafely({absPath:resolveConfigPath(`project`,e),sideline:!1,warn:()=>{}}).value.content?.dir??`.`)}function createEphemeralProjectDir(e){let t=mkdtempSync(resolve(tmpdir(),`ok-ephemeral-`)),s=resolve(t,`.ok`);return mkdirSync(s,{recursive:!0}),writeFileSync(resolve(s,`config.yml`),`# Ephemeral single-file session (\`ok <file>\`). Throwaway — safe to delete.\ncontent:\n dir: ${JSON.stringify(e)}\n`,`utf-8`),writeFileSync(resolve(s,`.gitignore`),`local/
3244
3248
  `,`utf-8`),t}export{STARTER_PACKS as $,writeTargetVersion as $i,isKnownPackId as $n,resolvePack as $r,createExternalChangeHandler as $t,HocuspocusAuthRejection as A,teardownToleranceTelemetryWriter as Ai,getLocalDir as An,readArmedPaneTarget as Ar,bundleSkillMdPath as At,McpLogger as B,tracedUnlinkSync as Bi,incrementCollabSocketFilteredError as Bn,reconcile as Br,compareSemver as Bt,FILE_WATCHER_ORIGIN as C,spansCurrentPath as Ci,flushFileLogger as Cn,parseGitVersion as Cr,bootServer as Ct,GitNotAvailableError as D,startWatcher as Di,formatPackRationale as Dn,planSeed as Dr,buildSkillZip as Dt,GIT_UPSTREAM_WRITER as E,splitMarkdownBlocks as Ei,formatContributorsFrom as En,pathToDocName as Er,buildExecResult as Et,MANAGED_RENAME_ORIGIN as F,tracedMkdirSync as Fi,getMetrics as Fn,readSkillManagement as Fr,clearEmbeddingsKeyFromAllBackends as Ft,PinoLogger as G,validateAgentId as Gi,initToleranceTelemetryWriter as Gn,releaseUiLock as Gr,countStaleAgentWipRefs as Gt,OBSERVER_SYNC_ORIGIN as H,tracedWriteFileSync as Hi,initContent as Hn,recordSkillInstallEvent as Hr,contentHash as Ht,MAX_AGENT_SESSIONS as I,tracedRename as Ii,getTracer as In,readStateManifest as Ir,coercePackId as It,ROOT_GITIGNORE_TEMPLATE as J,withSpan as Ji,installUserSkill as Jn,resolveBundledSkillDir as Jr,createAssetServeMiddleware as Jt,ProjectGitInitError as K,validateCloneInputs as Ki,installPrettyZodErrors as Kn,removeLastKnownHash as Kr,countWipRefs as Kt,MCP_CONNECTION_ID_HEADER as L,tracedRenameSync as Li,handleCollabSocketError as Ln,readTargetRecordedAt as Lr,commitUpstreamImport as Lt,INSTALLED_AGENTS_SCHEMES as M,tracedAppendFileSync as Mi,getLogger as Mn,readProjectLocalSemanticConfig as Mr,classifyFsPath as Mt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as N,tracedLinkSync as Ni,getLogsDir as Nn,readServerPackageVersion as Nr,clearArmedPaneTarget as Nt,GitTooOldError as O,streamingProblemEvent as Oi,gcCheckpointRefs as On,prepareSingleFileOpen as Or,buildStarterFolderFrontmatterYaml as Ot,LOG_MD_TEMPLATE as P,tracedMkdir as Pi,getMeter as Pn,readSkillInstallStateSnapshot as Pr,clearContributors as Pt,STARTER_FOLDER_FRONTMATTER_FILENAME as Q,writeStateManifest as Qi,isHocuspocusAuthRejectionReason as Qn,resolveLockDir as Qr,createEphemeralProjectDir as Qt,MIN_GIT_VERSION as R,tracedRmSync as Ri,handleSpawnCursor as Rn,readTargetVersion as Rr,commitWip as Rt,FILE_SYSTEM_WRITER as S,skillManagementPath as Si,findEnclosingProjectRoot as Sn,parseAuthRejectionWire as Sr,attachIdleShutdown as St,GIT_PREFLIGHT_FAIL_SPAN_NAME as T,spawnDetached as Ti,formatContributors as Tn,parseKeepaliveConnectionId as Tr,buildConfigYmlContent as Tt,OK_OKIGNORE_TEMPLATE as U,updateLastKnownHash as Ui,initShadowRepo as Un,registerAllTools as Ur,contributorCount as Ut,MissingOkConfigError as V,tracedWriteFile as Vi,incrementServerObserverFire as Vn,recordContributor as Vr,containsConflictMarkers as Vt,PANE_TARGET_TTL_MS as W,updateUiLockPort as Wi,initTelemetry as Wn,registerWrite as Wr,countShadowObjects as Wt,SKILL_INSTALL_EVENTS_FILE_REL as X,writeRootGitignoreForNewRepo as Xi,isAllowedWorkspaceHostHeader as Xn,resolveCursorBinaryDefault as Xr,createContentFilterAsync as Xt,SERVICE_WRITER as Y,withSpanSync as Yi,isAllowedApiOrigin as Yn,resolveContentDir as Yr,createContentFilter as Yt,STARTER_FOLDERS as Z,writeSkillManagement as Zi,isConfigDoc as Zn,resolveCursorSpawnInvocation as Zr,createEmbeddingsSecretStore as Zt,ConfigSchema as _,seedBasenameIndex as _i,errorResponse as _n,logsPreviousPath as _r,applySeed as _t,AgentPresenceBroadcaster as a,isJSONRPCRequest as aa,rewriteWikiLinksForDocumentRename as ai,createServer$1 as an,isProjectRoot as ar,SingleFileNotAFileError as at,DEFAULT_PACK_ID as b,shadowGit as bi,fallbackPaths as bn,normalizeFsPath as br,assertGitAvailable as bt,AutoStartDisabledError as c,readConfigSafely as ca,runCloneSubprocess as ci,createTestLogger as cn,isSelfWrite as cr,StateManifestError as ct,BUNDLE_SKILL_NAME as d,writeConfigPatch as da,safeContentPath as di,detectGit as dn,lastKnownHash as dr,UiLockCollisionError as dt,writeTracker as ea,resolvePackageVersion as ei,createFileLogger as en,isLinkIndexExcludedDoc as er,STARTER_PACK_IDS as et,BacklinkIndex as f,GitDirAccessError as fa,safeSubdir as fi,detectProjectShape as fn,listRescueCheckpoints as fr,__getShowAllWalkStatsForTesting as ft,CURSOR_BUNDLE_PATHS_BY_PLATFORM as g,resolveShadowDir as ga,saveVersion as gi,ensureProjectGit as gn,logsCurrentPath as gr,applyExternalChange as gt,CONFLICT_MARKER_RE as h,resolveGitDirDetailed as ha,saveInMemoryCheckpoint as hi,encodeFolderRoute as hn,loggerFactory as hr,applyAgentMarkdownWrite as ht,AgentFocusBroadcaster as i,isInitializedNotification as ia,rewriteMarkdownLinksForDocumentRename as ii,createPersistenceExtension as in,isPathWithinDir as ir,SeedRootDirError as it,HocuspocusAuthTokenSchema as j,toBroadcasterKey as ji,getLogFilePath as jn,readBranchFromHead as jr,classifyEvents as jt,HOCUSPOCUS_AUTH_REJECTION_REASONS as k,swapContributors as ki,getCurrentMcpLogger as kn,readAllTargets as kr,buildWipTree as kt,BUNDLE_IDS as l,resolveConfigPath as la,runDeviceFlowSubprocess as li,describeStoredEmbeddingsKey as ln,isSystemDoc as lr,TagIndex as lt,CONFIG_FILENAME as m,parseCheckpoint as ma,sanitizeClientName as mi,encodeDocName as mn,loadPrincipal as mr,acquireUiLock as mt,AGENT_ID_RE as n,JSONRPCMessageSchema as na,restoreContributors as ni,createMcpHttpHandler as nn,isManagedArtifactDoc as nr,STATE_MANIFEST_FILENAME as nt,AgentSessionCapacityError as o,isJSONRPCResultResponse as oa,runAuthReposSubprocess as oi,createServerObserverExtension as on,isProjectSkillManaged as or,SingleFileNotFoundError as ot,CC1Broadcaster as p,MalformedGitPointerError as pa,safetyCheckpoint as pi,emitPreflightFailureSpan as pn,listStarterPacks as pr,__resetShowAllWalkStatsForTesting as pt,ROLLBACK_ORIGIN as q,validateSkillZip as qi,installTestLoggers as qn,resetMetrics as qr,createApiExtension as qt,AGENT_WRITE_ORIGIN as r,LATEST_PROTOCOL_VERSION as ra,restoreLifecycleFromConflictsJson as ri,createOsProbe as rn,isPairedWriteOrigin as rr,SeedPrerequisiteError as rt,AgentSessionManager as s,atomicWriteFileSync as sa,runAuthStatusSubprocess as si,createStreamingErrorWriter as sn,isReservedForUserTree as sr,SingleFileNotMarkdownError as st,AGENT_ID_MAX_LEN as t,McpServer as ta,resolveUiInfo as ti,createLiveDerivedIndexExtension as tn,isLoopbackAddress as tr,STARTER_TEMPLATES as tt,BUNDLE_SCOPE as u,withFileLockSync as ua,runWithMcpLogger as ui,detectClaudeDesktopPresence as un,isToleranceTelemetryEnabled as ur,USER_GLOBAL_BUNDLE_IDS as ut,DEFAULT_CHECKPOINT_RETENTION as v,serializeError as vi,evictStaleTrackerEntries as vn,makeLazyEmbeddingsKeyStore as vr,armPaneTarget as vt,FileEmbeddingsBackend as w,spansPreviousPath as wi,formatAuthRejectionWire as wn,parseHocuspocusAuthToken as wr,buildAndOpenSkill as wt,EMBEDDINGS_API_KEY_ENV as x,shutdownTelemetry as xi,findEnclosingGitRoot as xn,packageVersionMajorMinor as xr,assertNeverDiskEvent as xt,DEFAULT_EMBEDDINGS_DIMENSIONS as y,setActiveSpanAttributes as yi,extractWikiLinksFromMarkdown as yn,mountMcpAndApi as yr,assertCompatibleStateManifest as yt,MISSING_OK_CONFIG_MESSAGE as z,tracedRmdirSync as zi,hasGcLogLatch as zn,readUiLock as zr,commitWipFromTree as zt};
3245
- //# sourceMappingURL=dist-CcBhqiSK.mjs.map
3249
+ //# sourceMappingURL=dist-CQqrcHvR.mjs.map