Research behind this decision: [[backlog-system-options-research]] (including the same-day second-pass Planka deep-dive and alternatives sweep).
**Supersedes the v1 vault-native plan (same day).** v1 chose vault task notes + Obsidian Bases kanban. It was overturned within hours by a requirement clarification, recorded here so the reasoning survives:
## The requirement change that flipped the decision
The perspectives panel and v1 optimized for "push beats pull." The user corrected this: **the pull surface — a visual board viewable and interactable from anywhere, any device, any time — is the primary requirement**, not a nice-to-have. The founding pain point is "when I want to jump into a project I have no visual interface to see what's on the docket," and with ADHD a desktop-only interface means forgotten/missed tasks. Conversational access ("what's on my plate?" via chat) does not satisfy this; it must be *visual*.
- Vault-native's known weakness (dashboard maturity, mobile — Bases custom views are desktop-weak) became **disqualifying**.
- Planka's known weakness (task data outside markdown) became **"a development problem"** — solvable via REST API, per the user.
- **Planka v2 Community Edition** (AGPL, plankanban/planka) deployed on the **OVH production server** (`systems-prod-01`, see `~/servers/ovh-prod/`), as a standard `~/services/planka/` docker-compose service behind Traefik with automatic SSL. Auto-discovered by the existing backup script.
- **Why OVH, not the home Proxmox box / hermes01:** always-on independent of home ISP/power; already reachable from anywhere with SSL (phone needs a bookmark, not Tailscale); fits the established deploy + backup pattern. Access control (strong auth at minimum; optional Traefik middleware/IP allowlist — client names will appear on cards) is a deploy-time decision.
- **No filesystem co-location with the vault is needed.** Planka state is Postgres; all integration (CLI, tick, digest, future Hermes) goes through Planka's REST API + git. Cards reference SecondBrain notes by name/URL; any host that ever needs note *content* clones the vault from Forgejo (one command). The vault does NOT currently sync to OVH and doesn't need to.
- **Vault role demoted to knowledge layer:** how-tos, contractor/client notes, conventions, decisions stay in SecondBrain; task *state* lives in Planka. The proven Notion rental pattern (item-with-references) survives split across the two: card = state + links, vault note = knowledge.
- **Forgejo issues remain the code-execution tracker** (rule unchanged: Forgejo = code/arch/deployment work inside a repo; Planka = everything else; cards may link issues).
- **CLI over MCP.** No official Planka CLI exists; we build a thin Ruby one (Sandi Metz style, `lib/` + `bin/`, mirroring the os-adr pattern) over the REST API. `plankapy` (Python SDK) is the endpoint-reference crib. Community MCP servers (bradrisse/kanban-mcp etc.) are shelf reference only.
- **Three repos, three concerns:** deploy artifacts (compose, cron wiring, config, deploy PRD/runbook) live in `~/servers/ovh-prod/`; the Ruby gem (API client + `backlog` CLI + tick/digest logic) lives in `~/dev/ruby-gems/`; cc-os carries only the SessionStart-brief plugin + its eval harness. The plugin depends on the gem's installed binary — no cross-repo source coupling. ovh-prod stays behavior-free (compose + cron + config only) so all logic remains model-free-testable inside the gem.
- **Gem is two-layer:** (1) a thin faithful **client layer** wrapping the Planka REST API broadly — core resources (projects/boards/lists/cards/tasks/due-dates/labels/comments/memberships/auth) **plus webhooks** (decided: wanted, so Planka can trigger strategic outbound actions via n8n/other APIs) and **admin + attachments** (less certain but likely useful — included in the first pass on the grounds that shipping probably-working endpoints now beats reopening the client later; Planka API churn judged low-risk); (2) a small opinionated **domain layer** (`add --quick`, `list --all`, `tick`) used by the CLI, digest, and future Hermes. Client layer generated with the `api-wrapper` skill, `plankapy` as endpoint crib. Per-credential instantiation (no global auth singleton) to support Hermes' scoped tokens.
**Phone gate PASSED 2026-07-09** (Planka v2.1.1 live at planka.hyperthrive.io since 2026-07-08). The per-hat board seeding from Phase 0 is superseded before it ran; this section replaces it.
**Structure — two Planka projects, boards per unit of work:**
- **Dev** project → one board per dev effort. Initial boards: **cc-os** and **planka gem** (`~/dev/ruby-gems/planka` — gem v1 is functionally complete but never went through an organized check-off; its existing "Build" board cards get walked through Review as the first exercise of the process).
- **Clients** project → one board per client. Initial board: **philly-search-engine-marketing** (`~/clients/philly-search-engine-marketing/`). Client cards are PM-altitude: each either links a Dev board that executes it (URL in description — no first-class card links in Planka) or carries its own task checklist when too small for a dev board.
- **Property management and business-dev boards deferred** — hypothetical/nuanced; revisit after living with the system.
- Uniform **lists** on every board: `Backlog → Next → Doing → Waiting → Review → Done` (Waiting = blocked on outside input, doesn't count against WIP).
- **Labels are board-scoped in Planka**, so the CLI/seeding scripts enforce an identical label set on every board: `P0/P1/P2/P3` (priority; P3 added 2026-07-10 for the Apprise expansion cards — currently only on the cc-os board, `backlog board ensure` should adopt it) + `hitl` / `afk-ready` (AI-workability convention, adopted from the gem issue cards).
**Process — kanban with WIP limits, not agile sprints.** Capture into Backlog is cheap; pulling into Next is the only planning ritual (when Next runs dry, not on a calendar); Doing is hard-capped at 2–3 for the human; cards flow one direction.
**Human/AI column ownership:** the human pulls into Next and is the only mover of Review → Done. AI agents pull Next → Doing when pointed at work, comment progress on the card, and land finished work in Review — never Done. AI-created cards (tick recurrence, captured tasks) enter at Backlog only. `hitl`-labeled cards are never picked up by AI autonomously.
**Notification policy v2 — digest and SessionStart brief DROPPED** (mental-clutter / notification-blindness risk; pull beats push applies to notifications too). Replaced by a single **pull-based unified dashboard**: a lightweight web view next to Planka on OVH reading via the API — due/P0/Doing/Review cards across all boards, rows linking into Planka. One starting-point view, opened when the user chooses. NOT Rails — lightweight JS (à la `~/dev/thinkfast/`) or similar; details deferred to its own Planka card. The `tick` recurrence job survives unchanged (writes cards, never notifies).
**Pre-seeding audits:** before creating cards, audit each of the three initial projects to collect all outstanding items + where they're referenced in the repo (docs, TODOs, issues, PRDs), so dispatched card-writing subagents populate cards with full context and pointers.
**Tracker routing (amends the Forgejo rule):** Planka is the default target for `/to-issues` and any future `/triage` — the plugin skill resolves repo → board deterministically (board named after the repo/client dir; Dev vs. Clients project inferred from `~/dev/*` vs `~/clients/*`) and a `backlog board ensure` script creates missing boards with the standard lists + labels. Forgejo remains only where issue-linked commits/PRs in a repo justify it.
**Board lifecycle (archive/activate) — VERIFIED 2026-07-09:** live-instance API tests confirmed Planka v2.1.1 CE **cannot move a board between projects** (`projectId` is not a patchable field), cannot move cards across projects (`E_NOT_FOUND` on foreign listId), and board DELETE is permanent (cascades, no restore — never use for archiving). The Archive-project design is therefore dead; lifecycle is the rename convention: archiving = rename board `archived--<name>` + move to bottom position (ONLY on explicit human go-ahead); activating = rename back (no approval needed). Discovery via the API board listing: active board found → use; `archived--` board found → activate silently; not found for an existing repo → stop and discuss. Label CRUD verified working per board (POST `/api/boards/:id/labels`, PATCH/DELETE `/api/labels/:id`; 41-name color whitelist, no hex). Also verified 2026-07-09 during seeding: creates require an undocumented `type` field — projects `"private"`, lists `"active"`, cards `"project"`; card-label attach is POST `/api/cards/:cardId/card-labels``{labelId}`. **Project visibility gotcha:** a bot-created project gets `ownerProjectManagerId` set (single-owner "private" mode) and is invisible to every other account — even instance admins can't add managers (`E_FORBIDDEN`). Fix/required pattern for `backlog board ensure`: after create, PATCH the project with `{"ownerProjectManagerId": null}` (as the owner; `{"type":"shared"}` is silently ignored), then POST the human's userId to `/api/projects/:id/project-managers`.
**Plugin scope widened:** the cc-os plugin (**decided 2026-07-10: new `os-backlog` plugin, ADR-023** — separation of concerns; os-vault stays memory/knowledge-only) is the AI's process-management surface and should be designed across all four plugin primitives: skills (capture/list/tick/board ops), scripts (deterministic API calls via the gem), named agents (e.g. card-triage, board-audit), and hooks (where session lifecycle genuinely helps — no push-style briefs per the notification policy).
**Execution breakdown (2026-07-09) — grouped by subagent + model tier; Fable orchestrates and reviews only. Status 2026-07-09: steps 1–3 DONE** (API verified, 3 audits run, boards seeded: Dev {cc-os, planka} + Clients {philly-search-engine-marketing}, 50 cards incl. 12 gem slices in Review and a dashboard-design card; old "planka-api gem" project left in place pending human deletion go-ahead):
1.**API verification** (haiku, 1 agent, first — everything downstream depends on it): against the live instance, test board-move-between-projects, cross-project card moves, label CRUD per board. Mechanical curl/gem calls; report findings only.
2.**Project audits** (sonnet, 3 parallel agents — judgment: what counts as an outstanding item): one each for cc-os, `~/dev/ruby-gems/planka`, `~/clients/philly-search-engine-marketing`. Sweep docs/TODOs/issues/PRDs; return itemized outstanding work with file references, suggested priority (P0–P2), and hitl/afk-ready call.
3.**Structure + seeding** (1 agent, after 1+2): create Dev + Clients projects (no Archive project — boards can't move between projects, see lifecycle above), boards per convention, uniform lists + labels; write cards from the audit outputs (no human pre-approval — 2026-07-09: human wants to see the AI's card decisions and adjust after). Since the existing "planka-api gem" project's Build board can't be moved into Dev, recreate the gem board fresh in Dev: the 12 verified-done build slices become cards in **Review** (the check-off exercise), audit findings in Backlog/Waiting; the old project is left untouched pending a human deletion go-ahead.
4.**Dashboard** (sonnet — design first as its own Planka card, then build): lightweight JS app on OVH reading the Planka API.
5.**Plugin** (sonnet build after a Fable/human design pass — the os-backlog vs. extend-os-vault decision, skill/agent/hook inventory, and tracker-routing skill are design-tier): then card-triage/board-audit named agents, `backlog board ensure` script wiring, `/to-issues` routing.
6.**tick cron on OVH** (haiku): unchanged from Phase 1.
### Plugin home + notification transport (2026-07-10 amendment)
- **Plugin decision resolved (human gate passed):** new **`os-backlog`** plugin in cc-os, NOT an os-vault extension — separation of concerns (memory/knowledge vs. workflow/process, different stores and failure modes). Recorded as **cc-os ADR-023**, which also makes the ecosystem framing explicit: cc-os = the always-on personal operating layer (`os-*` plugins, mutually aware over time, on every machine); `~/dev/cc-plugins` = optional as-needed plugins.
- **Apprise supersedes Pushover as the notification transport (cc-os ADR-024).** Planka natively speaks Apprise; the user's services (Discord, Telegram, Bark, Home Assistant, Gnome, Zoom, Pushover) are all Apprise targets. This iteration stays minimal: Apprise API server as a docker-compose service on OVH + swap the gem's Pushover P0 for a minimal Apprise `notify` client. Expansion seeded as P2/P3 cards on the cc-os board: Apprise client gem + CLI, an `os-notify` cc-os plugin (AI-routable notifications from any session/machine), multi-service routing, Planka's native Apprise integration pointed at the same server. Notification *policy* (pull beats push, silent days silent) is unchanged — transport only.
1.**TaskView** (taskview.tech) — on-paper ideal (native mobile apps, scoped API tokens, first-party MCP) but source-available, ~6 months old, thin sourcing. *Verify claims hands-on first, then trial.* Modern-and-unproven; only reached if Planka fails the gate.
2.**Vikunja** — mature API, kanban view, but mobile app explicitly alpha; revisit 2027.
3. Vault-native v1 plan (archived below via git history) / Backlog.md — the markdown lane, if hosted boards fail entirely.
**Donetick** (recurring-chore tracker, native mobile) noted as a lane-specific fallback if tick-driven recurrence proves annoying for property maintenance — resisted for now (fifth-backlog trap).
Planka went commercial (2025); CE keeps the full board UI. Three Pro-only features matter here, all covered by composing around the API — **we never modify or fork Planka**:
| Pro-only | Our layer instead |
|---|---|
| Recurring cards | `tick` script creates cards via REST on schedule — idempotent, elapsed-time catch-up (instantiates all missed occurrences), rules ours and portable |
| Cross-board global view | CLI `backlog list --all`, daily digest, and SessionStart brief aggregate across boards via API; in-app stays per-board (acceptable start) |
| Notification providers | The digest is ours (script-sent), Planka's notifiers irrelevant |
Known costs: "Pro discovery" banner in the free UI (cosmetic); API-token scoping story unverified (historically username/password; verify at deploy — matters for per-profile Hermes credentials; worst case a tiny API proxy enforces scope, which fits the approval-broker pattern anyway). Project health: v2 GA early 2025, tagged releases slowed since but commits continue — mature/stabilizing with a commercial turn, not dead. 12K+ stars, strong ecosystem.
1.**Ambient (default, zero interruptions):** the board itself + the Claude Code SessionStart brief. Information waits where the user already looks.
2.**Digest (the only routine notification):** at most ONE morning message, on ONE channel, sent **only when something is due or P0** — silent days stay silent.
3.**Interrupt:** essentially never in v1; reserved for genuinely urgent items.
Target trajectory: reminders are the degenerate case where AI can't act yet. Eventually the agent drafts the action (e.g., tenant spigot email) and the notification becomes "draft ready — approve?" — a decision, not a chore.
- sonnet subagent: deploy Planka CE per the ovh-prod service pattern (`~/services/planka/`, compose + postgres, Traefik labels, temp domain first, verify backup discovery). Decide auth posture at deploy.
- haiku subagent: seed boards per hat (property, clients, cc-os/dev, business dev) + 8–10 real fixture cards via REST (spigot winterization due 2026-10-15; Woodfin HVAC/electrical/plumbing checkups; cc-os someday items incl. "adopt Storybloq handover-doc pattern"; 1–2 client items). Also proves API CRUD end-to-end.
- **Human gate — the phone test:** from the phone (responsive web; official app and Planka Pal as alternates), view boards, drag a card between lists, add a card, complete one. Pass → continue. Fail → fallback ladder.
**Phase 2 — Hermes (independent design exercise, guardrails-first — NOT in the pilot's critical path)**
Considered separately from the task system; the task system's only obligation is integrate-ability, which REST + (verified) scoped tokens provide by construction. Design principles locked now:
- **Capability-based access:** each Hermes profile/hat (property manager, accountant, client manager, business partner) gets its own narrow, revocable credential (e.g., read-only or single-board token). Hermes never holds credentials for catastrophic actions (money movement, deletion, infra).
- **Approval broker:** catastrophic-class actions are *requests* Hermes submits to an interface (n8n workflow / API) that holds the real credentials and routes to the user for approve/reject. Guardrails are the interface, not a policy.
- Sequence: read-only digest/query first, then narrow acting (comms drafting for `property` items), one hat at a time, property manager first. Gets its own design note when started.
3. Due/P0 items visible in ONE pull-based starting-point view with zero navigation (unified dashboard; digest + SessionStart brief dropped 2026-07-09).