The milestone progress bars and the cards beneath them came from different places. The bar is counted SERVER-SIDE over every task; the kanban rendered whatever a single `limit=100` returned. Project 2 has 166 tasks, so 66 never arrived — and because the route sorts `updated_at desc`, the ones dropped were the least recently touched, which is mostly done tasks in completed milestones. So "v1.0 — 12/12" expanded to two cards, and the auto-collapse rule (100% done starts collapsed) read as arbitrary because the number driving it disagreed with what you saw when you opened it. No benefit was being chased. The limit shipped the day the view was written (012eb1d, March 2), when the project had a couple of dozen tasks. It became wrong as the corpus grew, and nothing was watching: the route returns `total` and the view discarded it. Correct when written, wrong later, silent in between — the same shape as half the coherence survey. Four changes: - **Page until complete.** The board groups by milestone and shows per-milestone progress, so it cannot be right on a partial set. Guards against a page that returns nothing while `total` still claims more, rather than looping forever. - **Stop swallowing the error.** `catch {}` left an empty board, which is indistinguishable from a project with no tasks — the same hidden-with-no- indicator failure one layer up. Styled apart from the empty state deliberately; "no tasks" and "the tasks did not load" must not look alike. - **Clamp long plan bodies** to ~6.5rem with a Show more. A milestone IS the plan, so its body carries the whole design — several hundred words now — and rendered in full one plan pushes every other milestone off screen. max-height rather than line-clamp: the content is rendered markdown with block children, which line-clamp handles unpredictably. Length judged on the source string; a per-milestone scrollHeight measurement is a lot of machinery to decide whether to show one button, and the proxy is only wrong near the threshold. - **Auto-collapse decides ONCE per milestone.** It re-ran on every reload, and `loadMilestones` runs after a task's status changes — so expanding a finished milestone and ticking anything snapped it shut again with no visible cause. That is the other half of why the collapse state looked mixed: it wasn't only deciding at start, it was overriding the reader continuously. Reported by the operator after thefd7097cdeploy. Not caused by it — but restoring `.milestone-header` in #2444 is what made the progress track render again, so the mismatch had been invisible rather than absent.
Fabled Scribe
A self-hosted work system-of-record for software projects, built to be driven by Claude Code. Notes, tasks, issues, projects, milestones, rules, and stored processes — reachable from Claude via a built-in MCP endpoint and a bundled Claude Code plugin, with a clean web UI for humans. No in-app LLM; Claude is the sole assistant.
Features
Notes and tasks with a Markdown editor, sub-tasks, milestones, issues, and kanban project workspaces. Stored processes, an engineering rulebook system, and semantic search with proactive knowledge-injection into Claude's context. A knowledge graph, per-user/group sharing, and a built-in MCP server (/mcp) plus a bundled Claude Code plugin so Claude can record and recall your work directly.
Quick Start
Prerequisites: Docker and Docker Compose. No GPU or local model needed — Claude is the sole assistant, reached over MCP.
Download docker-compose.quickstart.yml from this repo, then:
# Optional but recommended — set a secret key
export SECRET_KEY=your-random-secret-here
docker compose -f docker-compose.quickstart.yml up -d
Open http://localhost:5000. The first user to register becomes admin. To connect Claude, create an API key under Settings → API Keys and install the Claude Code plugin — see API Keys & MCP.
Development: To build from source, see Development.
Documentation
| Doc | Contents |
|---|---|
| Architecture | Stack, design decisions, data models, key services |
| Configuration | Environment variables, Docker Compose, production setup, security |
| Features | Detailed feature breakdown and keyboard shortcuts |
| Development | Dev workflow, CI/CD, migrations, release process |
| API Keys & MCP | API key management and Fable MCP install guide |
| SSO / OAuth | OIDC setup for Authentik, Keycloak, and other providers |
| API Reference | All REST API endpoints |
License
This project is privately maintained.