Skip to content

feat(desktop): link Markdown files and folders alongside Vault copies - #262

Open
Kechos23 wants to merge 31 commits into
ThisIs-Developer:mainfrom
Kechos23:codex/linked-markdown-workspace
Open

Kechos23 wants to merge 31 commits into
ThisIs-Developer:mainfrom
Kechos23:codex/linked-markdown-workspace

Conversation

@Kechos23

@Kechos23 Kechos23 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Desktop Linked Workspace: original files, folder workflows and draft protection

This updates the reviewed Linked Workspace proposal with the requested hierarchy, actions and safety behavior. It depends on the separately proposed shared persistence/reliability changes; those are not presented as defects introduced by Linked Workspace.

User-facing behavior

  • Group Vault, Linked Workspace and Secret Workspace under WORKSPACES. Use file-symlink / folder-symlink for real linked sources, keeping normal Vault icons unchanged.
  • Provide Link file, Link folder and Create new linked file actions in the desktop toolbar and Linked Workspace menu. Keep creation separated from linking existing sources.
  • Show source paths on hover instead of crowding file names. Use compact, distinct conflict/missing-source indicators with explanatory tooltips.
  • Keep local recovery drafts separate from Vault storage, preserving linked-folder hierarchy. Saving the original is explicit; automatic persistence does not write the source.
  • Support layout-independent Ctrl+S. Save As appends .md when needed and proposes the document name. A Vault export keeps its Vault document and focuses the new linked document; a linked Save As keeps both linked documents.
  • Support linked file/folder conversion to independent Vault copies, including existing sidebar HTML dragging. Preserve folder hierarchy and original external files. Vault folder Save As creates a separate linked folder without merging into an existing destination.
  • Keep conversions independent: reopening/rescanning the original can create a linked entry without consuming a Vault copy. Explicit rescan can restore entries previously excluded by removal/conversion.
  • Use consistent status toasts and centered confirmations for consequential choices. Original-save confirmation has a preference to skip subsequent ordinary confirmations; conflict protection remains active.
  • Keep the default Vault Welcome content unchanged. Identify unmodified built-in guides using metadata and use book-open-text for both guides. Update only the Linked Workspace guide.
  • Allow middle-button tab closing in the shared web/desktop interface.

Safety and failure handling

  • Capture live primary/split editor input before refresh, save, conversion and workspace maintenance, rather than relying on the debounce having finished.
  • Preserve a local draft when a source changes, disappears or returns. Recheck relevant draft/source state after confirmation; cancelling does not discard the draft.
  • Establish watchers for newly saved linked files. Persist bulk-removal exclusions before discarding records, and fail without a success message when persistence fails.
  • Treat imported backup paths as data, not authorization to write external files or create watchers. Restored drafts need explicit relinking.
  • Bound native file reads and folder scans; serialize relevant operations and report partial export/conversion results accurately.

Platform and limits

Linked-source actions require desktop native APIs and are hidden/disabled in the web app, including Docker-served deployments. Browser recovery content remains usable without reconnecting local paths. Native development/manual evidence is Windows-based; macOS/Linux native behavior is not claimed verified.

This branch uses the official Neutralino 6.5.0 runtime/client pins. Standard external HTML file drops remain Vault-copy imports. Native path drops, single-instance integration and the experimental pointer fallback are proposed separately in draft #269.

Scan limits: 10,000 Markdown files, 40,000 entries, 2,000 directories, depth 32, 20 MiB per Markdown source, 200 MiB staged content and a 60-second scan budget. Recovery is not a backup. Native APIs do not provide an atomic compare-and-write/no-overwrite guarantee, so a race with another process cannot be completely eliminated by application-side checks.

Validation

  • 117 unit tests passed.
  • Full Chromium run: 495/495 passed after the Media/Table focus-race fixes, before final locale completion. After completing the catalogs, 16 focused Chromium tests passed for localization/typography, desktop Save, action icons and web isolation; static validation also passed.
  • Locale audit passed: 15 catalogs × 1,580 keys, with aligned placeholders and reviewed finite exceptions for legitimate unchanged terms. Actual English fallback labels were translated and internal toast IDs/search tokens/selectors were removed from extraction. Native-language quality still benefits from native-speaker review.
  • The user accepted Windows smoke tests on the final official-runtime review executable: language switching/document preservation, Save/Save As, external conflict handling and folder conversion. Native macOS/Linux, Firefox/WebKit and comprehensive native failure/race testing remain unverified.

Existing Linked Workspace demonstration

Review dependency

Depends on shared safety/reliability PR #279. Because this cross-fork PR still targets upstream main, its full diff currently includes that baseline. For the Linked Workspace-only changes, use the incremental comparison. After #279 merges, I will rebase onto the resulting upstream baseline.

@vercel

This comment was marked as outdated.

@vercel

This comment was marked as outdated.

This comment was marked as outdated.

@ThisIs-Developer

This comment was marked as outdated.

@ThisIs-Developer
ThisIs-Developer self-requested a review September 29, 2026 19:47
ThisIs-Developer

This comment was marked as outdated.

@ThisIs-Developer ThisIs-Developer added the enhancement New feature, improvement, or usability enhancement. label Oct 2, 2026 — with ChatGPT Codex Connector
@Kechos23

This comment was marked as outdated.

ThisIs-Developer

This comment was marked as outdated.

@Kechos23
Kechos23 force-pushed the codex/linked-markdown-workspace branch from c09fdc7 to 9e8b706 Compare October 11, 2026 11:56

This comment was marked as outdated.

This comment was marked as outdated.

@ThisIs-Developer

This comment was marked as outdated.

Copy link
Copy Markdown
Owner

Hi @Kechos23,

Thank you for the quick updates you made based on the Copilot review. I don’t fully rely on Copilot reviews, but since I’ve been busy, I used it as an extra check. I really appreciate you resolving those points.

I finally have some time today to properly review and work on this PR. I have a few UI/UX changes from my side, and Codex also found some code-level issues that I want to address.

Would you be okay with enabling Allow edits from maintainers for this PR? I already have the fixes prepared and tested locally. If you enable it, I can push the changes directly to your branch, run another review afterward to verify everything, and then we can move toward merging.

If you prefer to make the changes yourself, that is completely fine too. I can share all the review points with you instead.

I’m being extra careful because we previously had a data-loss issue in the project, and this feature deals directly with users’ local files. I want to make sure there is no chance of document loss or unsafe behavior before merging.

If you enable maintainer edits, I’ll make the changes, and you are absolutely welcome to review my changes afterward with Codex or any other tool you prefer.

Thank you again for all the work you’ve put into this feature.

@Kechos23

Copy link
Copy Markdown
Contributor Author

Hello, @ThisIs-Developer , of course you are welcome to do the changes.
It would be helpful just to list and name the UI/UX changes for my information

@ThisIs-Developer

Copy link
Copy Markdown
Owner

Hi @Kechos23,

Thank you for enabling maintainer edits and for being open to me making the changes directly. I really appreciate it.

As requested, I’m sharing the changes I’m planning to make. First, these are my UI/UX points, and after that I’ve included the Codex review findings I’m currently working through.

UI/UX changes

  1. Remove “Confirm saving to original” from Settings
    I don’t think we need this extra setting. When a user saves a linked file using Ctrl+S or Save, the existing confirmation dialog already clearly informs them that the original file will be updated. I think that is sufficient.

    Screenshot 2026-10-14 230429

    Also, the setting itself didn’t seem to work correctly in my testing, so I’m planning to remove it completely while keeping the actual save confirmation flow.

  2. Remove “Create new linked file”
    From my perspective, Linked Workspace should mainly be about linking existing Markdown files and folders. Creating a completely new linked file feels outside that concept.

    I’m planning to remove Create new linked file from the Linked Workspace menu and its right-click menu.

  3. Use the normal Markdown file icon for guide files
    I noticed the built-in guide files use a separate book-open-text icon. Since they are still Markdown documents, I think using the normal Markdown/file icon will look simpler and more consistent with the rest of the application.

  4. Allow linking directly inside a linked folder
    When a user right-clicks a folder inside Linked Workspace, I want the context menu to show:

    • Link file
    • Link folder
    Screenshot 2026-10-15 142005

    Similar to New file / New folder in the normal Workspace.

    The linked file or folder should then be added directly inside the selected linked folder instead of always being added at the Linked Workspace root.

That’s everything from my UI/UX side for now.

@ThisIs-Developer

Copy link
Copy Markdown
Owner

Codex review

I also gave the latest commit to Codex several times for deeper review. I can’t personally guarantee yet that every finding is a real-world issue, but Codex repeatedly reproduced and flagged the same four areas, so I’ve asked it to help me prepare fixes and regression tests for them.

The four findings are:

1. P1: Secret Workspace
Multiple-document drag-and-drop can prevent Secret Workspace from reopening.
Location: [script.js:6860–6862](https://github.com/ThisIs-Developer/Markdown-Viewer/blob/50a5668102ba2bbc093b7ed4579087e1869cf4fe/script.js#L6860-L6862)

Reproduction: Start with an unconfigured Secret Workspace. Select two ordinary documents, drag them into Secret Workspace, and confirm creation of the access key once.

Actual behavior: Each document independently invokes the unlock/setup flow, registering multiple confirmation handlers. One confirmation therefore starts multiple encryption initializations. Under a reproduced asynchronous completion order, the __folders__ record is encrypted with a different key from the final manifest. Subsequent unlocking fails because the application decrypts every record.

Expected behavior: One password setup and one consistent encryption key for the entire batch.

Suggested fix: Unlock or initialize Secret Workspace once before processing the selected documents, or retain the previous batch-move unlock gate.

Validation: Reproduced using production functions and Node WebCrypto. Latest commit: two handlers, two initializations, folder-record decryption failure. Baseline: one handler, one initialization, all records decrypt.

Required regression test: Move multiple documents into a new Secret Workspace, then lock and unlock it successfully.


2. P2: Stale Read
A pending linked-file open can replace newly saved editor content with older text.
Location: [script.js:11959–11962](https://github.com/ThisIs-Developer/Markdown-Viewer/blob/50a5668102ba2bbc093b7ed4579087e1869cf4fe/script.js#L11959-L11962)

Reproduction: Open a linked file containing old text. Start another open operation and delay its asynchronous managed-Vault path check. Edit the document, successfully save new text, then allow the pending open to finish.

Actual behavior: linkedReadEpoch is captured after the asynchronous check, so the stale operation adopts the newer Save epoch. It replaces the editor and persisted recovery copy with the old text without marking a conflict. The original file on disk retains the newly saved text.

Expected behavior: The stale open must be discarded; editor and recovery content must retain the successful Save state.

Suggested fix: Capture the read epoch before the first await, or propagate and validate the caller’s original epoch throughout the operation.

Validation: Reproduced in the real Chromium application using its mocked desktop filesystem and actual Ctrl+S workflow.

Required regression test: Pause the managed-Vault check, complete Save, resume the pending open, and assert that editor and recovery content remain unchanged.


3. P2: Bulk Move
Bulk Move bypasses linked-document restrictions and creates a broken Secret Workspace state.
Location: [script.js:6251–6253](https://github.com/ThisIs-Developer/Markdown-Viewer/blob/50a5668102ba2bbc093b7ed4579087e1869cf4fe/script.js#L6251-L6253)

Reproduction: Select two linked documents, choose Move to → Secret Workspace, complete the move, edit one document, and press Ctrl+S.

Actual behavior: The bulk menu excludes only the built-in guide. Linked documents enter the ordinary move flow and retain sourcePath inside encrypted Secret Workspace records. Saving then fails recovery verification. Locking and unlocking restores the invalid linked state. The external original remains unchanged.

Expected behavior: Bulk Move must enforce the same linked-document restrictions or conversion rules as the other movement workflows.

Suggested fix: Reject unsupported destinations for linked selections, or perform an explicit supported conversion before moving them.

Validation: Reproduced in Chromium; persisted encrypted metadata and lock/unlock behavior were checked. Full application relaunch was not tested.

Required regression test: Bulk-move linked and mixed selections, verifying destination restrictions, resulting metadata, persistence, and subsequent Save behavior.


4. P3: Backup Hierarchy
Repeated backup restoration through the browser loses linked recovery folders.
Location: [workspace-storage.js:2781](

metadata.recoveryFolderSegments = recoveryFoldersFromStoredPath(importedMetadata.vaultRelativePath || importedMetadata._vaultRelativePath);
)

Reproduction: Restore a desktop backup containing nested linked documents in the browser. Export another backup from the browser, then restore that backup again.

Actual behavior: The first restore removes physical Vault paths and retains recoveryFolderSegments. Export preserves that hierarchy, but the next restore reads only the removed physical-path fields. Nested documents become flattened under the Linked Workspace root. Document content survives.

Expected behavior: Folder organization must survive repeated backup/export/restore cycles without restoring external-file access.

Suggested fix: Fall back to validated recoveryFolderSegments or the validated archive path when physical Vault paths are absent.

Validation: Reproduced using production backup normalization/export methods.

Required regression test: Round-trip a nested linked recovery backup through browser import, export, and another import.


Verification Limits
At the reviewed commit, 136 unit tests passed, and build/localization checks passed. Focused Chromium tests passed 38/39; repeated Save As checks passed 11/12, exposing intermittent menu and background-persistence timing failures that also need stabilization.

I’ve already given these findings to Codex to work on the fixes locally. After I apply the changes, I’m going to run another review against my own modifications to make sure I haven’t introduced anything else.

Because this feature touches users’ files, recovery data, backups, and Secret Workspace encryption, I’d rather do a few extra rounds of checking before merging.

Once I push the changes, please feel free to review my code as well. I’d absolutely welcome your review before we merge.

Thank you again for trusting me with the branch and for all the work you’ve put into this feature.

Simplify linked workspace controls, use standard guide icons, and persist sidebar-only grouping without moving original sources.

Guard linked read races and bulk moves, preserve backup recovery hierarchy, and make Secret moves retain durable content before plaintext cleanup. Update documentation, translations, desktop resources, and regression tests.

This branch was successfully deployed

1 active deployment
Preview — d6a2c501 Deployed Oct 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature, improvement, or usability enhancement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants