@inkeep/open-knowledge 0.87.6-beta.1 → 0.88.0-beta.0

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 (145) hide show
  1. package/dist/assets/skills/project/SKILL.md +2 -2
  2. package/dist/assets/skills/project/references/conflict-resolution.md +50 -31
  3. package/dist/assets/skills/project/references/doc-editing.md +1 -1
  4. package/dist/cli.mjs +72 -72
  5. package/dist/constants-BT6Biqag.mjs +1 -0
  6. package/dist/{dist-D8vm6fUQ.mjs → dist-B2Ob9aIQ.mjs} +1 -1
  7. package/dist/{dist-Cgap2iP0.mjs → dist-DHzxlDC1.mjs} +516 -513
  8. package/dist/index.mjs +226 -226
  9. package/dist/{init-ERU7x1Nk.mjs → init-D5hUaj9E.mjs} +28 -28
  10. package/dist/init-ievsEzYa.mjs +1 -0
  11. package/dist/{launch-json-removal-reFSWZqp.mjs → launch-json-removal-DsHjD-e-.mjs} +1 -1
  12. package/dist/loader-DcsfArYj.mjs +1 -0
  13. package/dist/{loader-CVL2wmPn.mjs → loader-sNVcoBaZ.mjs} +1 -1
  14. package/dist/{md-manager-BGnqyqi1-BZc5cHgU.mjs → md-manager-BGnqyqi1-CAY3I0ul.mjs} +159 -159
  15. package/dist/{open-browser-DOwyy7xf.mjs → open-browser-DYDl2MPM.mjs} +1 -1
  16. package/dist/parse-worker.mjs +1 -1
  17. package/dist/preview-C_IMTPrq.mjs +1 -0
  18. package/dist/{preview-C63Zc5kO.mjs → preview-CkUXY2Xe.mjs} +1 -1
  19. package/dist/public/assets/{AccountSection-K2l-YHsi.js → AccountSection-D-u6NZht.js} +1 -1
  20. package/dist/public/assets/{ActivityModeContent-C2LDnizs.js → ActivityModeContent-BpzVdP8Q.js} +1 -1
  21. package/dist/public/assets/{AddPropertiesButton-DFcMH7L-.js → AddPropertiesButton-DSPDpZJ_.js} +2 -2
  22. package/dist/public/assets/{AgentConnectionsSection-BpNIjE3C.js → AgentConnectionsSection-CbKU194h.js} +1 -1
  23. package/dist/public/assets/{AgentDiffPane-DHNmeqU5.js → AgentDiffPane-NEOwIKXE.js} +1 -1
  24. package/dist/public/assets/{AttachmentsSection-BOc57EAR.js → AttachmentsSection-DYG_TP5Q.js} +1 -1
  25. package/dist/public/assets/{AuthModal-Ckf-DBLD.js → AuthModal-DsmG3Tvf.js} +1 -1
  26. package/dist/public/assets/{CodeMirrorPropInput-7xPcMswa.js → CodeMirrorPropInput-CTh2IKX8.js} +1 -1
  27. package/dist/public/assets/{ContentRulesSection-DRzRUX_2.js → ContentRulesSection-zm962mfi.js} +1 -1
  28. package/dist/public/assets/{DiffViewBoundary-CoGZuziQ.js → DiffViewBoundary-C58eMqyu.js} +1 -1
  29. package/dist/public/assets/{DocumentContext-SRNCAE4T.js → DocumentContext-DTlihm6x.js} +1 -1
  30. package/dist/public/assets/{EditorModeToggle-I0_3UnWj.js → EditorModeToggle-C8wXEXv7.js} +1 -1
  31. package/dist/public/assets/{ExcalidrawDocEditor-Wf-kVhDD.js → ExcalidrawDocEditor-CJyb1cJD.js} +1 -1
  32. package/dist/public/assets/FeedbackForm-C9ymt52z.js +1 -0
  33. package/dist/public/assets/{GraphPanel-L9IO53Fe.js → GraphPanel-DOx9UNvO.js} +1 -1
  34. package/dist/public/assets/{ImportSkillDialog-CJBw__mB.js → ImportSkillDialog-BadQGhGu.js} +1 -1
  35. package/dist/public/assets/{LinkPreviewsSection-CTShrAOL.js → LinkPreviewsSection-DDM74MEZ.js} +1 -1
  36. package/dist/public/assets/{LintConfigEditor-Dd6S-93X.js → LintConfigEditor-BYUbMqlQ.js} +1 -1
  37. package/dist/public/assets/{LintingSection-DUY28yWo.js → LintingSection-CpGzROYK.js} +1 -1
  38. package/dist/public/assets/{ManagedArtifactProperties-De2jnxkW.js → ManagedArtifactProperties-CpUtR0kH.js} +1 -1
  39. package/dist/public/assets/ManagedArtifactProperties-D-5Hw3G-.js +1 -0
  40. package/dist/public/assets/{MermaidDocEditor-CExVaBdk.js → MermaidDocEditor-CBsqHq3S.js} +1 -1
  41. package/dist/public/assets/{NetworkAccessSection-BiN8lHCF.js → NetworkAccessSection-CBL6U29P.js} +1 -1
  42. package/dist/public/assets/{ProjectTemplatesSection-Ba0wgJX_.js → ProjectTemplatesSection-BgNT0K8r.js} +1 -1
  43. package/dist/public/assets/{PropertyDisplayRow-BlXXOSxY.js → PropertyDisplayRow-BGxRgVXM.js} +1 -1
  44. package/dist/public/assets/{PublishToGitHubDialog-eu0fsJeF.js → PublishToGitHubDialog-2x8KD1qF.js} +1 -1
  45. package/dist/public/assets/{RegisteredAgentIcon-B51BQwvX.js → RegisteredAgentIcon-BsD-s4ln.js} +1 -1
  46. package/dist/public/assets/{SchemaConfigEditor-BGx6w1CV.js → SchemaConfigEditor-CNB3TByj.js} +1 -1
  47. package/dist/public/assets/{SearchSection-Datg6M8D.js → SearchSection-6uzOvmhu.js} +1 -1
  48. package/dist/public/assets/{SessionsHost-Czk-1Lbr.js → SessionsHost-GDK89Pwj.js} +2 -2
  49. package/dist/public/assets/{SettingsDialogBody-g9TYbV1W.js → SettingsDialogBody-B3zt5ALZ.js} +2 -2
  50. package/dist/public/assets/{ShareReceiveMissDialog-DtUIiW8T.js → ShareReceiveMissDialog-WR_ParP1.js} +1 -1
  51. package/dist/public/assets/{SkillCostValue-BXljSvEn.js → SkillCostValue-CfttVYIg.js} +1 -1
  52. package/dist/public/assets/{SkillForkDialog-DIpR0Mwi.js → SkillForkDialog-Bh1ENNhm.js} +1 -1
  53. package/dist/public/assets/{SkillInstallMenu-DOYhAQR4.js → SkillInstallMenu-BNOJ1gOq.js} +1 -1
  54. package/dist/public/assets/{SkillOriginInline-BT2eZg6J.js → SkillOriginInline-CbftHWN_.js} +1 -1
  55. package/dist/public/assets/{SkillPluginBundleDialog-iRUTWDNb.js → SkillPluginBundleDialog-BZidbHAz.js} +1 -1
  56. package/dist/public/assets/{SkillToolbarControls-Db6vyiXk.js → SkillToolbarControls-a-0Pzr1Y.js} +1 -1
  57. package/dist/public/assets/{SkillsManagerSection-CFMf2-T8.js → SkillsManagerSection-8kamzhJv.js} +1 -1
  58. package/dist/public/assets/{SlidesPluginSection-CFr5hvHb.js → SlidesPluginSection-DGY8OW-e.js} +1 -1
  59. package/dist/public/assets/{SlidesToolbarControls-B-kNt6zW.js → SlidesToolbarControls-iMBibqX8.js} +1 -1
  60. package/dist/public/assets/{SourceEditor-DonfEHGX.js → SourceEditor-DLc-td_r.js} +1 -1
  61. package/dist/public/assets/{SpellingSettings-vOQhoS2i.js → SpellingSettings-ucYYz478.js} +1 -1
  62. package/dist/public/assets/{SyncSection-D2wAdJCr.js → SyncSection-CFsG7qG4.js} +1 -1
  63. package/dist/public/assets/{SyncStatusBadge-BhXU_JDu.js → SyncStatusBadge-Cmulk5eW.js} +1 -1
  64. package/dist/public/assets/{TemplateRow-e7WlliTB.js → TemplateRow-3gYh359C.js} +1 -1
  65. package/dist/public/assets/{TerminalLaunchContext-CG7oBBWt.js → TerminalLaunchContext-8-tVdZR6.js} +1 -1
  66. package/dist/public/assets/{TerminalPanel-FW1X3V6m.js → TerminalPanel-Bl1RiE6k.js} +1 -1
  67. package/dist/public/assets/{TerminalSection-PST5dg6l.js → TerminalSection-8YxE_I08.js} +1 -1
  68. package/dist/public/assets/{TerminalWindowApp-CiSuozT3.js → TerminalWindowApp-CLD65RGA.js} +1 -1
  69. package/dist/public/assets/{TextDocEditor-zblAlLMU.js → TextDocEditor-fnv1nu2C.js} +1 -1
  70. package/dist/public/assets/{ThemePluginSection-CbfAKivf.js → ThemePluginSection-DJWSYu1B.js} +1 -1
  71. package/dist/public/assets/{ThreadView-CoJPE8hj.js → ThreadView-CFr-rPKt.js} +1 -1
  72. package/dist/public/assets/{TimelineDiffPane-DyI9GRK3.js → TimelineDiffPane-CMxAbcJY.js} +1 -1
  73. package/dist/public/assets/{_envelope-ZrGDIqK5-CqysLCFT.js → _envelope-eL1L23Tr-B0_VTKOS.js} +1 -1
  74. package/dist/public/assets/{agent-connections-DDQhNqYY.js → agent-connections-qusR8JdV.js} +1 -1
  75. package/dist/public/assets/{agent-registry-BiUbIDTG.js → agent-registry-E4-YX-C7.js} +1 -1
  76. package/dist/public/assets/{bridge-UUn4EXk7.js → bridge-BC8zoeJp.js} +2 -2
  77. package/dist/public/assets/{catalog-CikhuADr.js → catalog-BLHq__9W.js} +1 -1
  78. package/dist/public/assets/{client-version-D2xlYP9X.js → client-version-Dk0LjYGu.js} +1 -1
  79. package/dist/public/assets/{comment-chips-BRNv4l8B.js → comment-chips-Dte0v4gq.js} +1 -1
  80. package/dist/public/assets/{config-provider-CYRHVjhx.js → config-provider-R1rcnJaF.js} +2 -2
  81. package/dist/public/assets/config-schema-XNMCu6AJ.js +1 -0
  82. package/dist/public/assets/{css-color-to-hex-BoByeFHH.js → css-color-to-hex-BxZMOPR2.js} +1 -1
  83. package/dist/public/assets/{doc-undo-manager-xHhzuPQP.js → doc-undo-manager-CregyD_N.js} +1 -1
  84. package/dist/public/assets/{field-controls-D6pzaJlX.js → field-controls-VYlM-zuI.js} +1 -1
  85. package/dist/public/assets/field-controls-mTFxITM4.js +1 -0
  86. package/dist/public/assets/{handoff-yTc6yTWB.js → handoff-DfyrwqdH.js} +1 -1
  87. package/dist/public/assets/{ime-composition-Cg9HhP4A.js → ime-composition-82-FXhge.js} +1 -1
  88. package/dist/public/assets/{index-3aLqrFWC.js → index-Bpp2ysx6.js} +9 -9
  89. package/dist/public/assets/{lint-config-client-D8erFdO3.js → lint-config-client-44sBu7BY.js} +1 -1
  90. package/dist/public/assets/{lint-plugins-BLvMu3e9.js → lint-plugins-hp3r0gcI.js} +1 -1
  91. package/dist/public/assets/markdown-lint-DuEyV_QZ.js +26 -0
  92. package/dist/public/assets/{markdownlint-rule-browser-BgMQxWzD.js → markdownlint-rule-browser-eM3Qv7kg.js} +1 -1
  93. package/dist/public/assets/{pending-receive-nav-store-C8UxJzBR.js → pending-receive-nav-store-Dh50hE6-.js} +1 -1
  94. package/dist/public/assets/{preferred-session-events-G-Kxe13x.js → preferred-session-events-B4fv6Hrl.js} +1 -1
  95. package/dist/public/assets/{progress-8Yr78Bb-.js → progress-Cz2Vg488.js} +1 -1
  96. package/dist/public/assets/{saved-themes-client-Cv82XlL2.js → saved-themes-client-BKoVNUUS.js} +1 -1
  97. package/dist/public/assets/{schema-section-BRYiNH1_.js → schema-section-QBDszEOo.js} +1 -1
  98. package/dist/public/assets/{schemas-api-00wdDb8Y.js → schemas-api-Bfr5hz6Y.js} +48 -48
  99. package/dist/public/assets/{selection-context-DhJv_5Gy.js → selection-context-B-4OCkYY.js} +1 -1
  100. package/dist/public/assets/{skills-api-DR4dR-aZ.js → skills-api-K7ohwTHC.js} +1 -1
  101. package/dist/public/assets/{src-I5i3plt6.js → src-CUFtJtWY.js} +1 -1
  102. package/dist/public/assets/storage-scope-BMJUnURI.js +1 -0
  103. package/dist/public/assets/{tag-pill-input-gvoOZssC.js → tag-pill-input-CuM3KvPL.js} +1 -1
  104. package/dist/public/assets/{telemetry-impl-BLUx9SzQ.js → telemetry-impl-BfZPg5XO.js} +1 -1
  105. package/dist/public/assets/{telemetry-startup-DiTds2mk.js → telemetry-startup-Dqizy_Gc.js} +1 -1
  106. package/dist/public/assets/terminal-cli-display-CnNZPRHq.js +1 -0
  107. package/dist/public/assets/{terminal-command-events-DEpEcoke.js → terminal-command-events-WwmIH6_2.js} +1 -1
  108. package/dist/public/assets/{terminal-launch-events-1xQIAzyc.js → terminal-launch-events-BZhihNCW.js} +1 -1
  109. package/dist/public/assets/{typing-burst-detector-DafMJnEv.js → typing-burst-detector-DG8Nnc7B.js} +1 -1
  110. package/dist/public/assets/{use-activity-panel-Dw_xmyMd.js → use-activity-panel-M_zwM3HT.js} +1 -1
  111. package/dist/public/assets/{use-apply-config-color-theme-DWk1Xz6p.js → use-apply-config-color-theme-CX_Lat5F.js} +1 -1
  112. package/dist/public/assets/{use-conflicts-CSjvmH8b.js → use-conflicts-8HzsEqZ0.js} +1 -1
  113. package/dist/public/assets/{use-live-xterm-theme-Dq-X9XNA.js → use-live-xterm-theme-TpVKyL9M.js} +1 -1
  114. package/dist/public/assets/{use-open-skill-Da7OuTUm.js → use-open-skill-BzeMe-Va.js} +1 -1
  115. package/dist/public/assets/{use-semantic-search-status-CYV2OYQJ.js → use-semantic-search-status-t6poTntV.js} +1 -1
  116. package/dist/public/assets/{use-skill-origin-DzTAHw-G.js → use-skill-origin-Bn6DLUoJ.js} +1 -1
  117. package/dist/public/assets/{use-skill-targets-R1WlO_4G.js → use-skill-targets-BGy2OH1p.js} +1 -1
  118. package/dist/public/assets/{use-skills-DwxqJ1Ij.js → use-skills-zxVtcQ4J.js} +1 -1
  119. package/dist/public/assets/{use-terminal-enabled-B6yVfE42.js → use-terminal-enabled-B5-GR1VP.js} +1 -1
  120. package/dist/public/assets/{use-timeline-entry-diff-6mM8LyW2.js → use-timeline-entry-diff-D8CqNmdV.js} +1 -1
  121. package/dist/public/assets/{use-workspace-CfiatAjW.js → use-workspace-C24MYxZb.js} +1 -1
  122. package/dist/public/index.html +51 -51
  123. package/dist/{registry-probes-lrX3q5gR.mjs → registry-probes-CrJkrmoY.mjs} +3 -3
  124. package/dist/{removal-file-path-EUNkhbbj.mjs → removal-file-path-BlzOT5Cg.mjs} +1 -1
  125. package/dist/{repair-launch-json-n1pbwYQK.mjs → repair-launch-json-BYBhER0H.mjs} +1 -1
  126. package/dist/{repair-mcp-configs-CtDwhbhA.mjs → repair-mcp-configs-D_w-Ru8V.mjs} +1 -1
  127. package/dist/src-Bc5Lde8y.mjs +1 -0
  128. package/dist/src-CdaPvDT4.mjs +16 -0
  129. package/dist/start-C1LonNJx.mjs +1 -0
  130. package/dist/{start-sVq-UqgO.mjs → start-DW9JRDjq.mjs} +3 -3
  131. package/package.json +4 -4
  132. package/dist/constants-zKMswRJV.mjs +0 -1
  133. package/dist/init-DxuNLNd1.mjs +0 -1
  134. package/dist/loader-C8C9ts0_.mjs +0 -1
  135. package/dist/preview-B7RXwLoM.mjs +0 -1
  136. package/dist/public/assets/FeedbackForm-0FypQyuS.js +0 -1
  137. package/dist/public/assets/ManagedArtifactProperties-BlpGhHHV.js +0 -1
  138. package/dist/public/assets/config-schema-3Au6NwEi.js +0 -1
  139. package/dist/public/assets/field-controls-B7huN6RQ.js +0 -1
  140. package/dist/public/assets/markdown-lint-VH2FeEHI.js +0 -26
  141. package/dist/public/assets/storage-scope-mUSZicU5.js +0 -1
  142. package/dist/public/assets/terminal-cli-display-BnYDv2L8.js +0 -1
  143. package/dist/src-hmh7mbyc.mjs +0 -16
  144. package/dist/src-nFvNpYd8.mjs +0 -1
  145. package/dist/start-AZsEibGN.mjs +0 -1
@@ -103,9 +103,9 @@ Every `.md` / `.mdx` needs YAML frontmatter — `title` + `description` required
103
103
  - **Use a template when one fits (MUST).** Instantiate via `write({ document: { path, template } })`; inherited templates count. Skip only when none match or the user asked for free-form (note why in chat). Create templates proactively when a shape recurs.
104
104
  - **When recurring per-doc properties emerge (MUST).** Writing the same frontmatter on multiple siblings → bake those starting values into a template (`write({ template })`). Folder frontmatter does not cascade values into docs.
105
105
 
106
- ## Conflict-aware writes
106
+ ## Write outcomes
107
107
 
108
- For a conflict refusal, follow the tool's recovery instructions and `references/conflict-resolution.md`; ask the user to resolve tracked conflicts in the app.
108
+ For every write result, read `outcome` and follow `nextStep` (`references/conflict-resolution.md` has each outcome's move): never repeat a write that landed (`merged-first`, `both-kept`, `projection-held`), and when a refusal says `nextStep: none`, nothing you send changes it: tell the user which file and what the result says, and carry on.
109
109
 
110
110
  ## Anti-patterns — the top offenders
111
111
 
@@ -1,50 +1,69 @@
1
- # Conflict-aware writes
1
+ # Write outcomes and conflicts
2
2
 
3
- A doc can land in conflict through a Git merge, a pull that collides with a local overlay, or OK's own reconciliation of the editor against disk. Reconciliation also protects an acknowledged edit when another app restores the exact older file version; that `stale-external-write` path works with GitHub sync disabled. The MCP server refuses a mutating call against a conflicted doc with a structured RFC 9457 response:
3
+ A document, template or skill write through `write` or `edit`, a document `restore_version` and a `lint` fix that changed the doc carry three fields once the server answers, success or not: `outcome` (what happened to the write), `saved` (whether its bytes were in the file when the server answered) and `nextStep` (what to do next). Read them before anything else in the result, and follow `nextStep`.
4
4
 
5
- ```json
6
- {
7
- "type": "urn:ok:error:doc-in-conflict",
8
- "title": "Document is in conflict.",
9
- "status": 409,
10
- "detail": "The document is in a conflict state. Ask the user to resolve it in the OpenKnowledge app, then retry.",
11
- "file": "notes/sso.md",
12
- "conflict": { "kind": "reconcile", "reason": "disk-markers" },
13
- "resolutionOptions": ["mine", "content", "delete"]
14
- }
15
- ```
5
+ | `outcome` | What happened | `saved` | Your move |
6
+ | - | - | - | - |
7
+ | `applied` | The write landed and is saved. | `true` | Carry on (`nextStep: none`); with a `content-divergence` warning `nextStep` is `re-read` (below). |
8
+ | `merged-first` | An outside change to the file was handled before your write was saved: merged in, or saved to the doc's history when it could not be merged. Your write landed. | `true` | Re-read before the next edit (`exec("cat <path>")`). Never repeat the write. |
9
+ | `both-kept` | Your write landed and is saved. A block was changed both here and outside, so both versions are in the doc, this doc's version first and the outside version directly under it. | `true` | Never repeat the write. Re-read, and remove the duplicate with an ordinary `edit` if your task calls for it. |
10
+ | `refused` | Not saved. OpenKnowledge saves it only after someone acts: you, as `nextStep` says, or the user. | `false` | Follow `nextStep`: `retry` means send it again, corrected the way the detail says (a fixed path, quoted YAML, a different name) or after the wait it names; `re-read` means re-read, then re-apply only what is missing; `none` means nothing you send changes it, so tell the user (below). |
11
+ | `projection-held` | Your write is in the doc but not yet in its file; OpenKnowledge saves it on its own. On OpenKnowledge Cloud the same outcome means the doc's file projection is held. | `false` | Never repeat the write. Re-read before the next edit. |
16
12
 
17
- The gate covers `write`, `edit`, `delete`, `move`, `restore_version`, and agent undo (the doc-CRDT write spine; template/folder ops are fs-direct). You cannot route around it by writing content that byte-matches one of the stages. The gate refuses on tracked state, not on body equality.
13
+ A `both-kept` or `projection-held` result comes back as an error result because it is not plain success, but its text starts by saying the write landed: do not repeat it. A batch reports these per entry in `documents[]`, and a skill write per file in `skill.files[]`. If `outcome` holds a value you do not know, treat it as `merged-first` when `saved` is true and `refused` otherwise, and re-read; treat an unknown `nextStep` as `re-read`. If there is no `outcome`, the server predates the fields, or the doc is a Mermaid, Excalidraw, text, settings or global skill file whose save does not report back yet: read the result text. `retryWhen` and a warning's own `nextStep` are older fields; ignore them.
18
14
 
19
- A write that first detects a stale file during its final disk flush returns `urn:ok:error:stale-external-write` (409). The edit reached collaborative state and the recovery snapshot, but the disk write did not happen. Ask the user to resolve it in the app, then re-read. Do not repeat the operation: a retried append can duplicate content already retained in the current version.
15
+ ## What each result asks of you
20
16
 
21
- **You cannot resolve a conflict over MCP.** There is no conflict tool, and `exec` is read-only. On either 409, stop writing to that file, tell the user which file is in conflict, and ask them to resolve it in the OpenKnowledge app. After they confirm, re-read the document. For `doc-in-conflict`, the operation was refused; retry only if it is still needed. For `stale-external-write`, the operation already reached collaborative state; do not repeat it. Compare the resolved document with the intended result and make only any remaining edit.
17
+ The fields come from one table on the server, and this one repeats it: for every result below, the move matches its `nextStep`. With `none`, nothing you send changes the result: stop writing to that file, tell the user which file it is and what the result says, and carry on with other work; do not wait on them. **You cannot resolve a conflict over MCP**: there is no conflict tool, no write tool takes a conflict parameter, and `exec` is read-only. Never work around a refusal by writing the same content somewhere else.
22
18
 
23
- ## The three kinds
19
+ | Result | `outcome` | `saved` | `nextStep` | Your move |
20
+ | - | - | - | - | - |
21
+ | `both-kept` (409) | `both-kept` | `true` | `re-read` | Never repeat the write. Re-read, and remove the duplicate with an ordinary edit if your task calls for it. |
22
+ | `applied` (200) with a `content-divergence` warning | `applied` | `true` | `re-read` | The write landed and is saved, but the stored text differs from what you sent. Re-read before the next edit. |
23
+ | `concurrent-overwrite-refused` (409) | `refused` | `false` | `retry` | Wait the seconds `retryAfterSeconds` names, then send the write again; an `append` or `prepend` is never refused this way. |
24
+ | `too-many-agent-sessions` (503) | `refused` | `false` | `retry` | Wait the seconds it names, then send the write again. |
25
+ | `doc-not-found` (404) | `refused` | `false` | `retry` | Send the edit again at the path the detail or `candidates` names. |
26
+ | `reserved-doc-name` (400) | `refused` | `false` | `retry` | Send the write again under a different name. |
27
+ | `frontmatter-malformed` (400) | `refused` | `false` | `retry` | Fix the YAML the detail points at, then send the write again. |
28
+ | `frontmatter-edit-not-supported` (400) | `refused` | `false` | `retry` | Send the frontmatter change again as a frontmatter patch. |
29
+ | `invalid-frontmatter-patch` (400) | `refused` | `false` | `retry` | Correct the patch the detail describes, then send it again. |
30
+ | `target-not-found` (404) | `refused` | `false` | `re-read` | Re-read the document, then make the edit against text that is there. |
31
+ | `stale-target` (409) | `refused` | `false` | `re-read` | Re-read the document, then make the edit against what is there now. |
32
+ | `doc-in-conflict` (409) | `refused` | `false` | `none` | Tell the user which file it is. Write to it again only after they say the conflict is resolved. |
33
+ | `stale-external-write` (409) | `refused` | `false` | `none` | Tell the user which file it is. Your edit is kept in the document and the recovery snapshot; do not repeat it. |
34
+ | `save-held` (503) with `pending-conflict` | `refused` | `false` | `none` | Tell the user which file it is. The save runs once they deal with the file in the app; do not repeat the write. |
35
+ | `save-held` (503) on a file with no agreed version | `refused` | `false` | `none` | Tell the user its file changed outside OpenKnowledge, and do not write to that document again: any write replaces it with the file on disk and moves your edit to its history. |
36
+ | `save-held` (503) with any other `reason` | `projection-held` | `false` | `re-read` | Do not repeat the write. Re-read before the next edit; with `pending-rename`, re-read at the new name the detail gives. |
37
+ | `doc-moved` (409) | `projection-held` | `false` | `re-read` | Do not repeat the edit. Re-read the document at the new name the detail gives. |
38
+ | `branch-switched` (409) | `projection-held` | `false` | `re-read` | Do not repeat the edit. Re-read the document before the next edit. |
39
+ | `doc-removed` (409) after a rename | `refused` | `false` | `re-read` | Re-read the document at the new path the detail names, and re-apply your change there if it is missing. |
40
+ | `doc-removed` (409) after a delete | `refused` | `false` | `none` | Tell the user the file is gone; the edit is in the document's history (timeline). Do not re-create the document on your own. |
41
+ | `server-stopped` (503) | `refused` | `false` | `none` | Tell the user; after the restart the edit is in the document's history (timeline). |
42
+ | `server-stopped` (503) during a move | `refused` | `false` | `re-read` | After the restart, re-read the document at the new name the detail gives, and re-apply the edit only if it is missing. |
43
+ | `path-escape` (400) | `refused` | `false` | `none` | Tell the user the document's path could not be resolved. |
44
+ | `store-refused` (503) | `refused` | `false` | `re-read` | Do not repeat it now. Once the user has fixed the filesystem fault, re-read and re-apply only what is missing. |
45
+ | `write-replaced` (409) | `refused` | `false` | `re-read` | Re-read: the document now holds the file as it is on disk, and your edit is in its history. Re-apply it if it is still needed. |
46
+ | `storage-full` (507), `storage-readonly` or `storage-error` (500) | `refused` | `false` | `re-read` | Once the user has fixed the storage, re-read and re-apply only what is missing. |
47
+
48
+ If you come back to that file later, re-read it first. For a refusal before anything was written (`doc-in-conflict`), write again only if the write is still needed; otherwise compare the doc with the intended result and make only the edit that is still missing.
49
+
50
+ Stale-save recovery data lives in `.ok/local/stale-external-writes.json`, with owner-only permissions. Do not delete that file or restart with empty state when it is corrupt or unreadable; it may hold the only copy of protected edits. Preserve it, restore a known-good backup, and run `ok bug-report` from the project directory for diagnostics.
51
+
52
+ ## Git conflicts
53
+
54
+ A Git merge or a pull that collides with local edits puts a doc in conflict until the user resolves it in the app. `conflict.kind` says which:
24
55
 
25
56
  | `conflict.kind` | Where it comes from | What a resolve does |
26
57
  | - | - | - |
27
58
  | `merge-native` | a git merge left unmerged stages in the index | stages your choice with git, and commits the merge once no `merge-native` conflict is left (other kinds do not hold the commit back) |
28
59
  | `working-tree` | a pull-only overlay collision, pinned to the origin blob it collided with | writes the chosen bytes to disk; nothing is committed |
29
- | `reconcile` | OK's own three-way merge of the editor against disk, including stale external saves. No git object holds the stages, so OK snapshots them at detection | writes the chosen bytes to disk and into the loaded document; no git command runs |
30
-
31
- A `reconcile` conflict carries a `reason`: `refused-conflict-markers` (the disk bytes already carried markers), `disk-markers` (markers landed on disk under an open doc), `refused-no-base` (there was no acknowledged version to merge against), `refused-too-large` (a merge past the size cap or one that failed OpenKnowledge's fidelity check, raised only when the outside version could not be saved to history), or `stale-external-write` (an older displaced version returned on disk). `merged-with-markers` appears only on entries recorded by earlier versions, or in the rare case where both versions were merged but could not be applied to the open document. An outside edit to the same block as edits made here is not a conflict: both versions are kept, this document's version first, and your write reports `disk-edit-reconciled` with `mergeOutcome: "both-kept"` (see `references/doc-editing.md`). The compatibility `conflictKind` field is `stale-external-write` for that last reason and `git` otherwise.
32
-
33
- ## What the user chooses
34
60
 
35
61
  The controls depend on the conflict's shape:
36
62
 
37
63
  | Shape | What the app shows | Controls |
38
64
  | - | - | - |
39
- | Conflict markers (`resolutionOptions` includes `content`) | The Conflict view, comparing both sides | **Accept current**, **Accept incoming** and, where available, **Accept both** for each conflict; the user then applies the resolution |
40
- | Whole file, such as `refused-too-large` (no `content` option) | A preview of the user's version | **Keep my version**, plus **Use their version** and **Delete the file** when offered |
65
+ | Conflict markers | The Conflict view, comparing both sides | **Accept current**, **Accept incoming** and, where available, **Accept both** for each conflict; the user then applies the resolution |
41
66
  | Deleted locally, modified upstream | A preview of the upstream version | **Keep file deleted**, plus **Restore with remote changes** when offered |
42
67
  | Modified locally, deleted upstream | A preview of the user's version | **Keep my version** or **Accept their deletion** |
43
68
 
44
- For a stale external write, Current is the version OpenKnowledge protected and Incoming is the restored older version. `resolutionOptions` lists the strategies the app offers for that file; no MCP tool accepts them, so never try to apply one yourself. Explain what each choice would keep, but leave the choice and application to the user.
45
-
46
- If applying a resolution fails, ask the user to inspect the remaining conflict in the app. OpenKnowledge retains unresolved conflict and recovery state. Wait for the user to finish, then re-read the document before deciding what work remains.
47
-
48
- A conflict can also close without you. Resolving a merge with raw git outside the app prunes the `merge-native` entry on the next disk change or HEAD move, and a `reconcile` conflict whose file comes back clean on disk dissolves on the next watcher pass.
49
-
50
- Stale-save recovery data lives in `.ok/local/stale-external-writes.json`, with owner-only permissions. Do not delete that file or restart with empty state when it is corrupt or unreadable; it may hold the only copy of protected edits. Preserve it, restore a known-good backup, and run `ok bug-report` from the project directory for diagnostics. An unresolved conflict does not expire with the displaced-hash window.
69
+ Explain what each choice would keep, but leave the choice and its application to the user. If applying a resolution fails, ask the user to inspect the remaining conflict in the app; wait for them to finish, then re-read the doc before deciding what work remains. Resolving a merge with raw git outside the app prunes the `merge-native` entry on the next disk change or HEAD move.
@@ -10,4 +10,4 @@
10
10
 
11
11
  **MDX.** To author an MDX doc (the KB renders MDX/JSX components), set `extension: ".mdx"` on the create: `write({ document: { path: "guides/widget", content, extension: ".mdx", position: "replace" } })` lands `guides/widget.mdx`. A `.mdx` suffix typed into `path` works too (the `extension` field wins if you pass both); omit both and it lands `.md`. An existing doc keeps its on-disk extension regardless — changing it in place isn't available via the MCP today.
12
12
 
13
- **Advisory warnings on writes.** `write` and `edit` responses may include `structuredContent.document.warnings` (batch: per-doc `structuredContent.documents[].warnings`) — advisory entries discriminated by `kind`, each also summarized as a `⚠` line in the response text. The write always landed; the entries tell you what to do next. Write-integrity kinds mean re-read the doc (`exec("cat <path>")`) before continuing: `content-divergence` (`{ kind, intendedBytes, actualBytes, byteDelta, hint }` — the converged Y.Text doesn't match what the payload composed to: concurrent peer residue, or — rare — a primitive regression) and `disk-edit-reconciled` (an out-of-band disk edit was folded in before your write landed on top; `mergeOutcome` says how: `clean`, `merged`, `both-kept` or `kept-live`). With `"both-kept"` the out-of-band edit changed the same blocks as edits made here, and three counts say what landed: `duplicatedBlocks` blocks are in the doc twice, this doc's version first and the out-of-band version directly under it; `restoredDeletedHere` blocks deleted here came back with the out-of-band version because it changed them; `restoredDeletedOutside` blocks the out-of-band edit deleted stayed with this doc's version because they were changed here. With `"kept-live"` it could not be merged, so the version here stayed and the out-of-band version was saved to the doc's history. Both carry `nextStep: "re-read"`, and in both your write landed: do not retry it. Re-read, and after `both-kept` remove a duplicate, or delete a block restored over a deletion here, with an ordinary `edit` if your task calls for it. A `mergeOutcome` or `nextStep` you do not know means the same as `merged`: re-read. The renderability kind `mermaid-parse-error` (`{ kind, fenceIndex, fenceFirstLine, message, line? }`) means that mermaid fence will not render — fix the fence and re-edit. The top-level `warning` field on write tools is unrelated: it is the preview-attach hint (`action: "attach-preview-once" | "start-ui"`), not an advisory — a separate key from `document.warnings`, and the two can coexist on one response.
13
+ **Advisory warnings on writes.** `write` and `edit` responses may include `structuredContent.document.warnings` (batch: per-doc `structuredContent.documents[].warnings`) — advisory entries discriminated by `kind`, each also summarized as a `⚠` line in the response text. What to do next is the result's `outcome` and `nextStep` (`references/conflict-resolution.md`); the entries say why. Write-integrity kinds come with `nextStep: re-read`, so re-read the doc (`exec("cat <path>")`) before continuing: `content-divergence` (`{ kind, intendedBytes, actualBytes, byteDelta, hint }` — the converged Y.Text doesn't match what the payload composed to: concurrent peer residue, or — rare — a primitive regression; the write is `applied`) and `disk-edit-reconciled` (an out-of-band disk edit was folded in before your write landed on top; `mergeOutcome` says how: `clean`, `merged`, `both-kept` or `kept-live`). With `"both-kept"` the out-of-band edit changed the same blocks as edits made here, and three counts say what landed: `duplicatedBlocks` blocks are in the doc twice, this doc's version first and the out-of-band version directly under it; `restoredDeletedHere` blocks deleted here came back with the out-of-band version because it changed them; `restoredDeletedOutside` blocks the out-of-band edit deleted stayed with this doc's version because they were changed here. With `"kept-live"` it could not be merged, so the version here stayed and the out-of-band version was saved to the doc's history. In both your write landed: do not retry it. Re-read, and after `both-kept` remove a duplicate, or delete a block restored over a deletion here, with an ordinary `edit` if your task calls for it. A `mergeOutcome` you do not know means the same as `merged`: re-read. The renderability kind `mermaid-parse-error` (`{ kind, fenceIndex, fenceFirstLine, message, line? }`) means that mermaid fence will not render — fix the fence and re-edit. The top-level `warning` field on write tools is unrelated: it is the preview-attach hint (`action: "attach-preview-once" | "start-ui"`), not an advisory — a separate key from `document.warnings`, and the two can coexist on one response.