fix(tools): cut repeated text from 27 tool definitions and lower the size cap - #636
aliasunder wants to merge 21 commits into
Conversation
vault_insert_at_anchor, vault_search_by_tag, vault_write_note, vault_list_memory_files and vault_search_by_folder each said some facts twice, in the description and again in the input schema or in a second section. Each fact now has one home. vault_write_note also states that overwriting without properties keeps the existing property values, and lists the refusal for a path a folder occupies, with an error-contract test. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
vault_list_tasks, vault_create_task and vault_update_task described most parameters twice, once in the description and once in the input schema. The description now keeps only what the schema does not say: parameter interactions, consequences, and the status behaviour on Kanban boards, recurring tasks and delete-on-completion tasks. The position parameter's interaction rules live in the description only. Example sets are cut to one per pattern. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…o one side A review of the first five edits found the shortened path-error bullet no longer said that hidden means dot-prefixed. The bullet says it again. vault_insert_at_anchor keeps its verbatim and trailing-newline rule in the description and vault_write_note its merge rule, with the schema text cut to the plain meaning. vault_search_by_tag's When to use names the main use. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…itions Each tool loses the text its input schema or another section already carried: restated parameter bullets, duplicate examples, and the long cause clause of the path-error bullet. Facts that only one side stated stay where they were. Three Errors sections gain a failure the tool can return, each with an error-contract test: vault_delete_memory on a missing memory file, vault_read_file on an image that cannot be decoded, and (already added) vault_write_note on a path a folder occupies. vault_list_tags states its empty result under Errors like the other listing tools. vault_delete_note's unreadable-config bullet names the real risk: a guessed setting could let the retention sweep remove a note set to be kept forever. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…us 2% The default configuration's tool list fell from 133,810 to 124,145 chars (3,762 per tool), so the allowance drops from 4055 to 3838 to hold the saving. AGENTS.md gains the rule to edit only the tools a change is meant for. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
vault_read_note's description no longer repeats the outline shape that the outline parameter's schema text already gives, so the drift guard reads the schema text and asserts it whole. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The nested-folder example moves to the folder parameter's schema text, and Returns says again that only supported types are readable. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The default configuration's average is 3,764 chars per tool after the vault_list_files fix, so the 2% allowance is 3840. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds three failures to the Errors sections of the tools that return them: a memory file name with a path separator (vault_get_memory, vault_update_memory, vault_delete_memory), heading_level without heading (vault_read_note), and a move onto the same path (vault_move_note). Removes four listed messages the client never sees because the input schema rejects the input first: "oldText cannot be empty" (vault_replace_in_note), "dependsOn cannot be empty" (vault_create_task, vault_update_task) and "addSubtasks cannot be empty" (vault_update_task). Each added entry, and the entries that stay in the edited bullets, has an error-contract test over real HTTP. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
umm-actually re-reviewed at No new findings (16 tracked finding(s) across all runs). Context notes
umm-actually · z-ai/glm-5.3-flash |
vault_update_memory quoted "entry/section contains a control character", a string the client never receives; it now quotes the two real messages. Its shrink-guard entry and vault_delete_memory's say what triggers the refusal and what to do, since re-reading alone does not clear it. Entries that share a remedy share a bullet (the memory file-name errors, vault_get_memory's two "requires a file" errors). vault_get_outgoing_links quotes its extension error. vault_get_daily_note lists the remaining unsupported format tokens. Three repeated facts are cut from one side. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…al allowance vault_create_task and vault_update_task list the three path-guard errors their path parameter can raise. vault_read_file lists "invalid .canvas JSON". vault_read_note and vault_patch_note list "heading cannot be empty" for a whitespace-only heading. The NON_TASK entry on both task tools quotes the message as the server sends it. Each has an error-contract test. The size allowance is 3875: the final default average (3,798 chars per tool) plus 2%. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Add the newly listed unsupported daily-note tokens to the README note
This PR expands vault_get_daily_note's unsupported-token list in the tool description to include w, Q, and Z/ZZ, but README's Daily-notes note still enumerates only ordinals, dd, d, e, k/kk and the L-family — the user-facing doc now under-reports which formats error out. Failure scenario: A user with a daily-note filename format using w or Z reads the README, sees those tokens not listed as unsupported, keeps the format, and vault_get_daily_note rejects every call while the docs said nothing about it. Suggested fixExtend the README note's token list with the weekday/quarter/zone tokens (w, Q, Z/ZZ) the tool description now names.umm-actually · z-ai/glm-5.3-flash |
Fix 16 readability pauses from the fresh-eyes stranger read: resolve ambiguous antecedents (pause 3), replace jargon (pause 2 "rendition", pause 7 "tokens"), fix broken grammar (pause 10 NON_TASK sentence), separate packed sub-cases (pauses 5, 14, 15), define opaque terms (pause 13 "trailing section content"), break dense clauses (pauses 6, 9, 12), clarify compact notation (pauses 1, 4, 8), add missing cascade order (pause 11), and make the AGENTS.md "one home per kind" heading concrete (pause 16). Tighten both Obsidian syntax paragraphs (create and update) for the same pattern. Net size change is a small shrink; six frozen tools untouched. Ship-Check: code-quality · claude-opus-4-6 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reviews of the edited definitions listed about thirty places where the description and a parameter's schema text still said the same thing, or where a small fact was missing or misleading. Each repeat is cut from one side: plain meaning stays in the schema, interactions and consequences in the description. Restores three facts and one spelled-out abbreviation that the previous readability commit dropped: the Dataview form and the adjacent-field effect in the task tools' Obsidian syntax note, and what a daily-note forward reference points to. Also: vault_memory_recall's second example no longer uses the query form its own text calls poorly ranking, vault_list_files says what an extensionless file reports, and the sort cascade names its real order. The size allowance is 3821: the default average (3,745 chars per tool) plus 2%. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The sort_by .describe() text said "done and cancelled do not cascade" but "cancelled" is not in the sort_by enum — an agent reading this would think it is a valid sort key. Only "done" lacks a cascade. Ship-Check: bug-check · claude-opus-4-6 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…README The daily-notes note named ordinals, dd, d, e, k/kk and the localized formats. The server also rejects w, Q and Z/ZZ, which the tool description now lists, so the README names them too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Reply to issue comment 5972944109 ("Add the newly listed unsupported daily-note tokens to the README note"): valid, fixed in 17f3208. The README daily-notes note now lists Sweep for the token list: README.md is the one doc that carries it. DOCKERHUB.md is regenerated from the README and does not include that note. The 🔍 ship-check · pr-monitor · claude-fable-5-1 |
|
Mark additional_properties conditional in recent_notes and search_by_property
Pre-existing: vault_recent_notes and vault_search_by_property list additional_properties as an unconditional Returns field, but this PR's own edits mark it conditional (additional_properties?) in vault_search_by_tag and vault_find_orphans and reword vault_search_by_folder to 'when present'. All five tools map results through the same formatNoteMetadata helper, so presence semantics are identical and the two unconditional listings misstate the response shape. Failure scenario: A script consuming vault_recent_notes builds on the documented shape and reads additional_properties from every entry; a note whose frontmatter holds only promoted keys (title, tags, type, created, related) comes back without the field, and the consumer throws on the missing key or reports a malformed response. Suggested fixChange both Returns lists to "additional_properties?" (or add a "when present" clause, as vault_search_by_folder now does) so all five metadata listings agree with formatNoteMetadata's actual behavior. If the new "Edit only the tools a change is meant for" rule is read as blocking these two, land the two-word fix in a follow-up rather than leaving the definitions contradicting each other.umm-actually · z-ai/glm-5.3-flash |
…at resolves The bullet ended with "inspect the file before retrying", but the guard refuses the same append again until the content a rewrite cannot keep is gone. It now says a retry returns the same refusal until a manual edit removes that content, and that reading the note finds it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Reply to issue comment 5973542886 ("Mark additional_properties conditional in recent_notes and search_by_property"): valid, and the maintainer approved fixing it in a follow-up change.
🔍 ship-check · pr-monitor · claude-fable-5-1 |
…st_files The tool description says an empty extensions array returns an empty listing, and no test made that call. The fixture vault holds files, so the empty result can only come from the filter. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… that tool is disabled The parent_block_id / parent_line bullet named vault_update_task without the availability check its two sibling references use. The clause now goes through whenToolEnabledText, so the text is unchanged while vault_update_task is served and absent when it is not. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
||
| Errors: | ||
| - A visible folder containing no files — or one that doesn't exist — returns an empty listing, not an error. | ||
| - A visible folder containing no files — or one that doesn't exist — returns an empty listing, not an error. So does an empty extensions array. |
There was a problem hiding this comment.
Reject an empty extensions array instead of documenting an empty listing
Low severity · conventions · medium confidence
vault_list_files' new Errors bullet promises that an empty extensions array returns an empty listing, turning an accidental artifact ([] is truthy, so the filter is applied with an empty allow-list) into a documented contract. An empty filter list can never select anything, so per the conventions' input-boundary rule it is invalid input and should be rejected by the schema's .min(1) floor — as the sibling array params (depends_on, subtasks, heading) already do — rather than silently producing a result the caller likely reads as "this folder has no files".
Failure scenario: An agent computes the extensions list from its own intent (e.g. "images" for a folder that turns out to hold none) and sends vault_list_files({ extensions: [] }) expecting an unfiltered listing; the server returns { files: [], extension_counts: {}, total: 0, truncated: false }, and the agent reports the vault/folder as containing no files.
Suggested fix
In `asset-tools.ts`, change the filter schema to reject the empty list (and drop the Errors clause): `extensions: z.array(z.string().min(1)).min(1).optional().describe(...)`. If the empty list is intentionally kept as a valid input, say so in the schema `.describe()` too, since that is where a caller reads the parameter's plain meaning.umm-actually · deepseek/deepseek-v4.1-flash
…fore limit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…un in the body vault_delete_span's bullet said only runs left by the deletion collapse, but deleteSpan collapses every run in the note's body, as vault_replace_span's bullet already says. Pin both tools' claims: runs elsewhere in the body collapse on delete and replace, and a run inside replacement content collapses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…adings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What does this PR do?
Tightens the MCP definitions of the 27 tools that score below 5.0 on Glama's Tool Definition Quality Score, and lowers the size cap to hold the saving. The default tool list drops from 133,810 to 123,723 chars (−10,087, about 8%), which every claude.ai and Claude Desktop conversation loads. The
Errors:sections were also checked against what a client can actually receive.Each edit answers the grader's written reason for that tool. The most common reason was that the description repeats what the input schema already says, so each repeated fact now has one home:
The six tools at 5.0 are not touched:
vault_get_backlinks,vault_list_notes,vault_list_property_keys,vault_list_property_values,vault_recent_notes,vault_search_by_property. No runtime behaviour changes.Changes per tool
vault_insert_at_anchorpositionandfirst_matchbullets cut (the schema states both); the verbatim and trailing-newline rule stays in the description and leaves the schemavault_search_by_tagvault_write_notepropertieskeeps the existing property values; lists the refusal for a path a folder occupies; merge rule leaves the schemavault_list_memory_filesleading_calloutare each defined once, in Returnsvault_search_by_foldervault_update_taskpositioninteraction rules leave the schemavault_create_taskpositioninteraction rules leave the schemavault_list_tasksvault_searchtags,typeandrelatedfilter bullets cut; the two date-filter bullets become onevault_read_fileraw: trueexamples cut; the per-typerawsentences become one bullet; lists the failure for an image that cannot be decodedvault_read_noteoutlineparameter; the description keeps thebytesand empty-heading factsvault_move_notevault_patch_notevault_replace_in_notevault_update_propertiesvault_delete_memoryvault_delete_notevault_get_daily_notevault_get_outgoing_linksbytesclause tightenedvault_update_memoryvault_delete_spanvault_replace_span's doesvault_find_orphansvault_get_memoryon_or_afterparagraph tightenedvault_memory_recallfileis applied beforelimit; truncation rule leaves the schemavault_replace_spancontentvault_list_filesBehavior:linevault_list_tagsErrors:, like the other listing toolsThe path-error bullet in each edited tool becomes
"absolute path blocked" / "path traversal blocked" / "hidden path blocked" — use a vault-relative path with no hidden (dot-prefixed) file or folder in it. The three messages name their own causes.vault_update_memoryandvault_delete_memoryalso fix a grammar slip in their opening sentence ("a About Me/ memory file").Added facts, checked against the code
vault_write_notepropertieskeeps the existing property valuesserializeNote,vault-filesystem.ts:260vault_write_note"cannot write note …: that path is not a file"vault-filesystem.ts:431vault_delete_memory"memory file not found"readMemoryFile,memory-store.ts:588, called bydeleteMemoryvault_read_filefitImageToByteBudget,fit-image-to-byte-budget.ts:99vault_memory_recallfileis applied beforelimitmemoryRecall,search-queries.ts:587–601, thenbuildMemoryRecallResultvault_replace_spancontenttoovault-patcher.ts:514vault_delete_spanvault-patcher.ts:456vault_delete_notetrash-config.ts:57vault_list_filesextensionsarray returns an empty listingbuildAssetListing,asset-operations.ts:388Errors sections match what the client receives
Every message quoted in an
Errors:section of the 33 tools was traced to a throw that a schema-valid call can reach. That found entries in both directions.Listed, but the client could never receive them (the input schema rejects the input first, so the client gets an input validation error). Removed:
vault_replace_in_note"oldText cannot be empty"vault_create_task,vault_update_task"dependsOn cannot be empty"vault_update_task"addSubtasks cannot be empty"Quoted text that was not the text the server sends. Corrected:
vault_update_memory"entry/section contains a control character""entry contains a control character"/"section contains a control character"vault_create_task,vault_update_task"checkbox '[c]' is a NON_TASK status""checkbox "[c]" is a NON_TASK status"Returned by the tool, but not listed. Added:
vault_write_note"cannot write note …: that path is not a file"vault_delete_memory"memory file not found"vault_get_memory,vault_update_memory,vault_delete_memory"memory file must be a bare name without path separators"vault_read_note"heading_level requires a heading","heading cannot be empty"vault_patch_note"heading cannot be empty"vault_move_note"source and destination are the same path"vault_create_task,vault_update_task"absolute path blocked"/"path traversal blocked"/"hidden path blocked"vault_read_file"invalid .canvas JSON", and the decoder's message for an image that cannot be decodedThe memory shrink-guard entry on
vault_update_memoryandvault_delete_memorynow says what triggers the refusal and what resolves it (a manual edit), because re-reading and retrying returns the same refusal.Each added or corrected entry has a test over real HTTP: the error entries in
server-error-contracts.test.ts, and the emptyextensionsresult inserver-integration.test.ts. The other added facts are pinned where the code does them: thefile-before-limitrule inmemory-recall.test.ts, and blank-line collapsing invault-patcher.test.ts(inside the replacement content forvault_replace_span, and elsewhere in the body for both span tools).Size
The three task tools account for most of the saving. A few tools grow slightly because they gained
Errors:entries (vault_update_memory,vault_delete_memory,vault_read_file).CHARS_PER_TOOL_ALLOWANCEdrops from 4055 to 3821: the default average when the allowance was set (3,745 chars per tool) plus 2%. The default average is now 3,749. The cap assertion was checked by adding one char more than the remaining headroom, which fails it.Checks on the text
vault_searchandvault_memory_recallwere checked as well. The pass found three drops, all restored in this PR: what a hidden path is, and twovault_list_filesfacts.The README's daily-notes note now lists the unsupported format tokens
w,QandZ/ZZ, which the server already rejected andvault_get_daily_notenow names.AGENTS.md gains one rule under "MCP tool definitions": edit only the tools a change is meant for, because a grader re-scores every definition whose text changes.
One existing test changed: the guard that pinned the outline shape in
vault_read_note's description now pins it on theoutlineparameter, where the shape lives.Type of change
Checklist
npm testpassesnpm run lintpassesnpm run prettier:checkpassesnpm run buildsucceeds🤖 Generated with Claude Code