docs+fix: reconcile the docs with the shipped tool surface, and stop under-scoping Full Disk Access - #119
Merged
Conversation
…under-scoping Full Disk Access Four classes of drift had accumulated between the docs and the code, all of the same shape: a doc asserts a capability is impossible or a permission is irrelevant, while the shipped tools do the opposite. 1. Capabilities documented as infeasible that shipped anyway. docs/APPLESCRIPT-LIMITATIONS.md still denied any constructable notes:// deep link and called the `show` command "deliberately not wrapped as a tool", and argued that reading NoteStore.sqlite for pin state was out of scope — while get-note-link, four show-* tools and get-note-metadata all ship. Rewrote both sections around what is actually still true (no link property or link enumeration, error -2753; pin state unsettable) and recorded the database paths that replaced the rest. Same claim removed from the README's limitations bullet, its "No pinned notes" row, TODO.md and TECHNICAL_NOTES.md (which both still list prepend as GUI-only under every approach, six weeks after append-to-note shipped it), and the audit doc's status table, whose 17 rows all read "Open" though every issue is closed. 2. Full Disk Access described as a checklist-only concern. The FDA guide is the page every FDA failure message links to, and it said "One feature area" needs it and "All other tools work normally" — but get-note-metadata errors without it, get-note-link's primary path is a database read (its AppleScript fallback is gone on macOS 26+), and get-sync-status silently reports "no pending uploads". Enumerated the real set in the guide, the README, `doctor` and `health-check`, and added the FDA requirement to get-note-link's own tool description, which never mentioned it. 3. get-note-content's lossiness was invisible to structured consumers. Oversized inline images are replaced with text placeholders, but the only signal was prose appended to the text block — so an agent following the documented read-modify-write recipe writes the placeholders back as the note body. Added strippedImages/truncated to the outputSchema, said so in the tool description and the README Returns block, told the warning string not to write the body back, and pointed the update recipes at append-to-note. 4. Errors and docs that steer callers at the wrong problem. create-note blamed Notes.app configuration for a folder it never creates; create-folder was documented as flat-name-only and as erroring on an existing folder it actually skips; the 500-id batch cap, append-to-note, show-note, get-note-link, get-selected-notes and get-default-location were missing from the agent-facing skill and CLAUDE.md; and Automation-permission errors were the one setup-failure class with no docs URL and no `doctor` pointer. Verified against real Notes.app: the missing-folder message now names the folder, get-note-content returns the new structured fields, and tools/list carries the corrected schemas.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Documentation sweep against the live tool inventory (dumped from the built server over MCP, not inferred). Every finding was adversarially verified before landing, and several were deliberately not applied where the verifier showed the claim was overstated or the proposed fix would have introduced a new false statement.
Fixed
docs/FULL-DISK-ACCESS.md— the page every FDA failure message hyperlinks to — opened with "One feature area needs Full Disk Access" and closed with "All other tools work normally", and the README,doctor, andhealth-checkall said the same. Three more tools read the same protectedNoteStore.sqlite:get-note-metadatafails outright without FDA,get-note-link's primary path is a database read (its AppleScriptnote linkfallback exists only on macOS 12–15 and is gone from the SDEF on macOS 26+), andget-sync-statusdegrades silently — it still answers, but reports no pending uploads and no active sync. A user who randoctor, saw the warning scoped to checklists they don't use, and skipped the grant got unexplained failures elsewhere. All five are now enumerated, with each one's no-FDA behaviour, in the guide, the README, thedoctorcheck detail and thehealth-checkline.get-note-link's own tool description, which said only "requires macOS 12+" and never mentioned FDA at all, now states the requirement and the fallback's version window.get-note-content's lossiness was invisible tostructuredContentconsumers. Inline base64 images overAPPLE_NOTES_MCP_MAX_INLINE_IMAGE_BYTES(default 256 KB) are replaced with[inline image omitted: …]text placeholders, but the only signal was prose appended to the text block — the structured payload carried the lossy body with no flag, which is precisely what an agent consumingstructuredContentreads. Following the documented read-modify-write recipe (get-note-content→update-note) therefore replaced a note's real images with placeholder text, permanently. The output schema now carriesstrippedImages(count) andtruncated(boolean); the tool description, the READMEget-note-contentReturns block, the skill, and the warning string itself now say not to write the returned body back, and point atappend-to-noteinstead.create-noteblamed Notes.app for a folder it never creates.createNoteaddresses the target folder directly and does not create it, but the failure returned "Check that Notes.app is configured and accessible" — sending callers on a TCC/permissions hunt in the one case where Notes.app is demonstrably fine. The message now names the missing folder and points atlist-folders/create-folder(or, for a badaccount, atlist-accounts), keeping the automation-permission advice as the fallback. The requirement is also stated in the tool description, thefolderparameter description, and the README, matching the wordingmove-notealready used.doctorpointer, though the Full Disk Access path has carried both since 2.5.11. Both strings (the generic executor error mapping insrc/utils/applescript.ts, which fronts every tool, and thehealth-checkpermission probe) now share oneAUTOMATION_REMEDIATIONconstant insrc/utils/docsUrls.tsthat names the app to grant, says to quit and relaunch it, and ends with the absolute troubleshooting URL plus "run the doctor tool to verify".Documentation
docs/APPLESCRIPT-LIMITATIONS.mdstill asserted there is "no readable or constructableapplenotes:///notes://deep link" and that theshowcommand "is deliberately not wrapped as a tool" — whileget-note-linkreturns exactly that URL andshow-note/show-folder/show-account/show-attachmentall ship; and its pinned section argued that readingNoteStore.sqlitewas "outside what an AppleScript-based server should do" and concluded "pinned read/write is not supported", afterget-note-metadatahad shipped doing it. Both sections are rewritten around what remains true — anotehas noURL/url/linkproperty (error-2753), link relationships still cannot be read or inserted, and pin state still cannot be set — with the database-backed paths that superseded the rest recorded alongside. The same obsolete claims are corrected in the README's limitations bullet and its "No pinned notes" row.get-note-metadata,get-note-content'shashtags,get-note-link, and the requiredintegrationCI job. The two genuine residual limits (pin state unsettable, no note-to-note linking within a body) are already stated in the AppleScript-limitations section and the Known Limitations table, so nothing is lost.docs/STABILITY-PERF-AUDIT-2026-06-19.mdmarked all 17 findings "Open". Every one is closed. The status column now records the release each landed in, with L1 (Expose pinned notes (investigate feasibility) #28) and L3 (Note-to-note links (investigate/document) #30) marked partial — pin state is readable but not settable, andget-note-linksupersedes only half of the note-links finding — and L2 (Surface tags/hashtags #29) marked read-only. The "Target release: 2.0.0" line is replaced with a note that the fixes landed across 2.0.0–2.6.x and the document is a historical record, not a live backlog. The audit body is left as the dated 1.4.4 snapshot it is.TODO.mdandTECHNICAL_NOTES.mdboth still listed prepend as "GUI-only under every approach".append-to-notehas done append and prepend over ordinary AppleScript since 2.6.0, with no Shortcuts bridge. Corrected in both, along with TODO.md's stale "As of v2.1.0" header; the Shortcuts-inventory table keeps "Prepend to a body" in its right-hand column (Notes genuinely ships no such Shortcuts action) but the column is retitled and footnoted so it no longer reads as a global impossibility.append-to-note's candidate bullet is amended rather than deleted, since a true in-place append that cannot disturb attachments is still unbuilt.append-to-note,show-note,get-note-link,get-selected-notes,get-default-location. The skill's canonical "Add milk to my shopping list" example walked an agent through reading the whole body and resending it viaupdate-note— the destructive path — six releases after the purpose-built tool existed. The Updating Notes recipe now splits addition (append-to-note) from replacement (update-note), and the tool tables and CLAUDE.md cover all five. The Attachment-Safe Updates guidance is unchanged:append-to-notealso rewrites the full body, so it is not an attachment-safe alternative.CLAUDE.mdsaidget-checklist-state"Returnsnull" when a note has no checklists or the database is unreadable. It never returns null — all six failure modes come back as MCP error responses (isError: true), including the routine "this note has no checklist items", which an agent would otherwise treat as a tool failure. Replaced with the actual contract and the message text that distinguishes each case.create-folderwas documented as flat-name-only, with an error it cannot raise. The README saidnamewas a "Name for the new folder" and that the call errors "if folder already exists"; it in fact takes a whole nested path, creates every intermediate segment, skips existing ones, and is idempotent — which is what its live schema has always said. Corrected, andcreate-folderandbatch-move-notesadded to CLAUDE.md's nested-path list.batch-delete-notes/batch-move-noteswas undocumented in prose. The schema already emittedmaxItems: 500to machine callers, but no README table, tool description, skill, or CLAUDE.md entry mentioned it. Added to all four.docs/FULL-DISK-ACCESS.md's "See also: Known Limitations" pointed at#known-limitations, which GitHub resolves to the first matching heading — a Features-level subsection about pinned notes and note links that says nothing about checklists or Full Disk Access. That subsection is renamed to "AppleScript limitations", matching its own body, so the anchor reaches the Known Limitations table again. The README's own FDA heading is renamed from "Full Disk Access for Checklist Features" to "Full Disk Access" (its two inbound anchors updated) now that the section covers more than checklists.Verification
lint (0 errors), typecheck, format:check, full test suite, plugin-manifest sync, skills drift check, and bundle-matches-source all pass — re-run independently of the authoring pass.
skills/edited at the canonical root only, thenpnpm run sync:skills.Checklist
## [2.6.13]CHANGELOG heading