Publish a local file with hackmd_create_note
hackmd_create_note takes an absolute local_path to a .md file in place of content. The server reads the file, so a large note no longer passes through the conversation, creates the note, polls until it reads back with exactly that body, and then tracks the file the way hackmd_pull_note does. The reply carries tracking.status (tracked or not_tracked with a reason); a tracking failure is never an error once the POST has landed, because an error would invite a duplicate create.
Publishing puts local file content on HackMD, so it is stricter than a plain create. It needs a workspace root set in the server's own environment, like an image upload, and an explicit read_permission, since HackMD's default for an omitted one is unmeasured. The path is canonicalized and access-checked before the POST and compared again before the record is written, so a symlink swapped in during the network calls leaves the file untracked. A file that already has a sync record, a non-.md path, and local_path together with content are refused before any request. A file over the large-file warning size needs confirm_large_file: true.
The logic lives in src/sync/adopt.rs; src/note/crud.rs only gains the two input fields and a guard that create_note itself never sees a local_path. docs/tools.md and docs/configuration.md describe the new section and the root requirement.
Verified locally: cargo fmt --check, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-targets --all-features (423 passed, 0 failed, 4 ignored), including six new tests in src/sync/adopt.rs for tracking, a differing read-back, a late read-back, the refusals, the root requirement, and create_note refusing a local_path. Not run against the live HackMD API.
Left out: the capture-and-persist pair is still written out in pull and adopt, and the sync lock is held across the POST and read-back on purpose, so two publishes of one file cannot both win.
Summary by cubic
hackmd_create_note now accepts an absolute local_path to a .md file in place of content. The server reads the file, creates the note, polls until it reads back with exactly that body, and then tracks the file the way hackmd_pull_note does.
- The reply carries
tracking.status(tracked, ornot_trackedwith a reason) and the summary says which; a tracking failure is never an error after the POST, since an error would invite a duplicate create. - Publishing requires a workspace root set in the server's own environment and an explicit
read_permission; a file over the large-file warning size needsconfirm_large_file: true. - Already-tracked files, non-
.mdpaths, andlocal_pathtogether withcontentare refused before any request. - The path is canonicalized and re-checked after the network calls, so a symlink swap leaves the file untracked; the sync lock is held across the POST and read-back so two publishes of one file cannot both win.
- Tests cover every error kind, a missing file, and an unresolvable path; an already-tracked file maps to a conflict, and
create_noteitself refuses alocal_pathas an internal error.