fix(work-mcp): harden pillar keyword loading and repair QMD import flag#77
Open
stevegranshaw wants to merge 1 commit into
Open
Conversation
Two root-cause fixes in core/mcp/work_server.py. 1. Coerce pillar keywords to str at load time. An unquoted YAML token like `1:1` parses as a sexagesimal int (61), which crashes guess_pillar's `keyword in text` with "'in <string>' requires string as left operand, not int" -- taking down every pillar-inferring tool (list_tasks, create_task, get_work_summary, get_week_progress). 2. Repair the QMD semantic-search import. The qmd_query import used the wrong module path (utils.qmd_query -> core.utils.qmd_query) and ran before sys.path was set up, so it always failed; a second HAS_QMD assignment in the qmd_indexer block then set HAS_QMD=True, leaving is_qmd_available undefined while the flag claimed QMD was available. create_task and meeting-context lookups then hit "NameError: name 'is_qmd_available' is not defined". Defer the qmd_query import to after sys.path setup with the correct path, and stop the indexer block from touching HAS_QMD. Verified in a clean Python process: pillars load with all-str keywords, guess_pillar handles `1:1`/`121` without raising, QMD symbols resolve, and find_similar_tasks falls back to keyword matching when QMD is not indexed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Linked Issue
What Changed
Two root-cause fixes in
core/mcp/work_server.py:Pillar keyword crash. An unquoted YAML token like
1:1in a user'sSystem/pillars.yamlparses as a base-60 int (61), soguess_pillar()'skeyword in item_lower(work_server.py:313) raises'in <string>' requires string as left operand, not int. That takes down every pillar-inferring tool —list_tasks,create_task,get_work_summary,get_week_progress. Fix: coerce keywords tostrat load (load_pillars_from_yaml), so the loader is robust to any non-string value regardless of how a user's pillars file was written.create_taskNameError. TwoHAS_QMDassignments guard different imports:qmd_queryimport (is_qmd_available,vault_search) used the wrong path (utils.qmd_queryrather thancore.utils.qmd_query) and ran beforesys.path.insert(..., <vault root>), so it always failed →is_qmd_availablenever defined.qmd_indexerimport succeeds (it runs after thesys.pathinsert) and setHAS_QMD = True, clobbering the earlierFalse.Result:
HAS_QMDisTruewhileis_qmd_availableis undefined, sofind_similar_tasks(:2140) and the meeting-context path (:2613) raiseNameError: name 'is_qmd_available' is not defined. (Side note: because theqmd_queryimport never resolved, QMD semantic de-duplication has effectively been dead code.) Fix: move theqmd_queryimport to after thesys.pathinsert with the correct path, and stop theqmd_indexerblock from touchingHAS_QMD(it has a no-op fallback and one unguarded call site, so it never needed the flag).Test Plan
str;guess_pillarreturns the right pillar for1:1,121, and multi-word titles with no crash.is_qmd_available,vault_search,refresh_search_indexall resolve;HAS_QMD == True.is_qmd_available()returnsFalse→find_similar_tasksfalls back to keyword matching (the existingtry/except), so there's no behavior change beyond removing the crash.refresh_search_indexintact).load_pillars_from_yamlreturns all-strkeywords given an unquoted1:1; (b)guess_pillar('1:1 sync')does not raise. Glad to add before merge if you'd like.Risk & Rollback
is_qmd_available()plus atry/exceptkeyword fallback, so it can't crash task creation. The one behavioral change: on machines where QMD is installed, semantic de-dup now actually runs (its intended, previously-dead behavior).Docs Impact
CHANGELOG.mdentry (e.g. v1.20.2): task tools crashed on certain pillar keywords, andcreate_taskhit a hidden semantic-search error — both fixed.Found while using Dex; fix written with Claude Code's help and verified before submitting, per CONTRIBUTING.md.