Commit Graph
2 Commits
Author SHA1 Message Date
Bryan Van DeusenandClaude Sonnet 4.6 eed6aedc9e Add duplicate entry prevention to LLM tool pipeline
Three-layer guard on create_note and create_task:
1. Exact title match (get_note_by_title, case-insensitive) → hard block,
   redirects model to use update_note instead
2. Fuzzy title match (SequenceMatcher ≥82%, punct-stripped word search for
   candidates) → hard block; catches "Game Premise" vs "Game Premise Notes"
3. Semantic content similarity (semantic_search_notes threshold=0.87) → soft
   block with requires_confirmation:true; model asks user then retries with
   confirmed:true; graceful no-op if embedding model is unavailable

create_project and create_milestone now always require confirmed:true before
creation (structural entities — must be intentional). Both are also guarded
by exact + fuzzy title checks post-confirmation.

create_note and create_task gain an optional confirmed parameter (not
required by default; only used to bypass a content-similarity soft-block
after the user has been asked).

Helpers added to tools.py:
- _fuzzy_title_match(title, candidates, threshold=0.82)
- _PUNCT_RE for stripping punctuation before word-search candidate fetch
- difflib.SequenceMatcher and re imported at module level

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 14:19:58 -05:00
Bryan Van DeusenandClaude Sonnet 4.6 87d3f3ea16 Fix project/milestone association and redesign AppHeader navigation
Backend:
- routes/tasks.py: POST + PUT were silently dropping project_id,
  milestone_id, parent_id from request body — root cause of association
  not saving from the task editor
- routes/tasks.py: GET /api/tasks/:id now includes parent_title in
  response (secondary lookup when parent_id is set)
- routes/notes.py: add PATCH /api/notes/:id for partial updates (used
  by sub-task status toggle; PUT already existed but PATCH was missing)
- routes/projects.py: GET /api/projects/:id/notes now fetches milestone
  IDs and passes them via milestone_ids so tasks assigned to a milestone
  (but lacking project_id) are included in the project view
- services/notes.py: create_note() auto-sets project_id from milestone
  when milestone_id is provided and project_id is omitted; list_notes()
  gains milestone_ids param — when combined with project_id uses OR
  condition (project_id=X OR milestone_id IN (...))

Frontend:
- NoteEditorView: add MilestoneSelector; milestone resets when project
  changes; all save paths (save/create/auto-save) include milestone_id
- stores/notes.ts: add milestone_id to createNote + updateNote types
- TaskEditorView: sub-tasks now inherit milestone_id from parent task
- AppHeader: three-zone layout — brand left, Notes/Projects/Tasks/Chat
  centered (absolute positioning), right rail with status/theme/? and
  gear dropdown containing Settings/Users/Logs; mobile dropdown unchanged

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 13:34:01 -05:00