Lific gets a planning layer. Plans turn a goal into an ordered, arbitrarily-nestable tree of steps that persists across sessions and context compaction — the thing that separates an issue tracker from a project planner. Steps can mirror issues, so closing an issue checks its step and completing a step closes its issue, all recorded in the audit log.
Plans
- Persisted, nestable step trees. A plan is a first-class, project-scoped tree of steps (steps containing steps, any depth) that survives across agent sessions and compaction. Issues stay flat and lateral; the hierarchy lives on the plan.
- Steps mirror issues, both ways. Link a step to an issue and the two stay in sync: closing the issue checks the step (anywhere it appears), and marking a step done closes its issue. Reopening an issue reopens its steps in active plans, stamped with the reason. Closing a plan's anchor issue auto-archives the plan. Done flows down from issues, never silently up from plans.
- Authored in one call. Four MCP tools:
create_planbuilds a full nested tree at once,get_planrehydrates it for the next session, andedit_plan_step/update_plan_stephandle surgical edits, done toggles, issue links, and structure changes — with every side effect reported back in the result. - First-class in the web UI. A Plans tab alongside Issues, Board, Modules, and Pages: a list grouped by status and a detail view with a real nested tree — done toggles, per-step markdown descriptions, issue chips with provenance, an anchor issue, a progress bar, and an activity timeline. Built on the same shell as the issue and page views.
- Fully audited. Every plan and step mutation lands in the audit log with actor attribution, including the issue-driven cascades (recorded as system-driven via the triggering issue). A new
/api/plans/{id}/activitysurface and plan support acrosslist_resourcesanddelete. - REST + CLI. Full
/api/plansCRUD plus step operations, identifiers asPROJ-PLAN-n.
Issue list
- Accurate per-status tallies in the topbar. The count was previously
filteredIssues.lengthover a fetch capped at 200, so it silently undercounted once a project grew past that. A newcount_issues_by_statusquery (a single indexedGROUP BY) andGET /api/projects/{id}/issue-countsendpoint return true per-status counts and a real total. - Click a status count to toggle that filter, with narrowed views rendering "shown of total" so the number is always honest.
- List fetch limit raised 200 → 1000 so rows don't truncate as early.