Fixed

  • Milestones: GET /milestones no longer writes new milestone files on every request — this was causing duplicates via race conditions when multiple browser tabs or SSE connections triggered concurrent reads; task-referenced milestone names are now surfaced as virtual in-memory entries instead
  • Sidenav: all sidnavs that extend BaseSidenavModule now close automatically after a successful save; a new closeAfterSave getter (default true) allows subclasses to opt out (TaskSidenavModule is unaffected as it does not extend the base class)
  • Search: selecting a task result now switches to the list view (not board) and opens the task sidenav directly; fallback default for unknown types also changed from “board” to “list”
  • Task sidenav: milestone field replaced with a <select> dropdown populated from existing milestones — free-text entry is no longer possible; auto-create on save removed (create milestones explicitly in the Milestones view)
  • Portfolio: clearing all URL rows no longer silently preserves old URLs — urls: [] is now sent explicitly so the JSON key is present; backend serialize also treats empty arrays the same as undefined (omitted from YAML)
  • Portfolio: githubRepo field was missing from the POST /portfolio body mapping — it is now passed through on project creation