SecondBrain/vault-backlog-pilot-plan.md

20 KiB
Raw Blame History

summary tags status last_reviewed
Backlog decision + pilot plan (Planka CE on OVH, live 2026-07-08, phone gate passed 2026-07-09) — Dev + Clients Planka projects with per-repo/per-client boards, kanban WIP flow with human/AI column ownership, thin Ruby gem/CLI + tick, pull-based unified dashboard (digest + SessionStart brief dropped), vault demoted to knowledge layer
scope/global
type/decision
domain/task-management
tool/claude-code
project/cc-os
accepted-pilot-live 2026-07-10

Backlog system: decision and pilot plan v2 (2026-07-06)

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.

Decision

  • 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.

Repo/artifact separation + gem scope (2026-07-07 amendment)

  • 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.
  • PRDs drafted 2026-07-07: deploy PRD → ovh-prod repo docs; gem PRD → ruby-gems repo. cc-os plugin PRD deferred to Phase 1 (plugin-home decision resolved 2026-07-10: new os-backlog, ADR-023).

Organization + workflow v2 (2026-07-09 amendment — gate passed)

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 23 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 13 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 (P0P2), 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.

Human gates: archive go-aheads always, plugin design decision (5), gem-card Review→Done acceptance. (Card-content pre-approval rescinded 2026-07-09.)

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.

Fallback ladder (if the phone gate fails)

  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).

The Planka Pro paywall and how we route around it

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.

Notification policy (ADHD / notification-blindness constraint)

Three tiers, designed so silence stays meaningful:

  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.

Pilot plan — Fable orchestrates, cheap models do grunt work

Phase 0 — deploy + THE GATE (day 1)

  • 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) + 810 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"; 12 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 1 — the agent layer (parallel after the gate)

  • sonnet subagent: Ruby backlog CLI (lib/ + bin/, model-free tests): add --quick "title" (defaults board/list/priority), list --all (cross-board), tick (idempotent elapsed-time recurrence catch-up from a recurrence manifest; simple offsets +1y|+6m|+3m|+1m only — no rule engine).
  • haiku subagent: daily tick scheduling on the OVH box (cron or a small container next to Planka). Digest dropped 2026-07-09.
  • SessionStart brief dropped 2026-07-09 → replaced by the pull-based unified dashboard (own Planka card; lightweight JS, not Rails). Plugin (skills/scripts/agents/hooks) home + naming per cc-os-plugin-skill-naming-convention (decided 2026-07-10: new os-backlog plugin, cc-os ADR-023; run bin/refresh-plugins after).
  • Fable: review all deliverables; verify a fresh session surfaces the fixtures.

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.

Phase 3 — close-out (Fable)

  • cc-os ADR + CLAUDE.md update; retire the v1 vault-task-type idea from vault-conventions planning.
  • One-week live trial. Week-2 review gates (each pre-captured as a card): digest too noisy → tighten; capture friction → extend CLI; Forgejo top-issues added to brief; recurrence annoyance → evaluate Donetick for the property lane.

Explicitly deferred (captured as someday cards, not built): recurrence rule engine, effort/quick-win filter, AI comms drafting, Hermes acting autonomously, vault→OVH sync, per-board polish, TaskView evaluation (unless gate fails).

Success criteria

  1. The board is viewable and interactable from the phone, anywhere (the gate, then daily reality).
  2. Recurring tasks cannot silently miss a week (tick catch-up on an always-on host).
  3. Due/P0 items visible in ONE pull-based starting-point view with zero navigation (unified dashboard; digest + SessionStart brief dropped 2026-07-09).
  4. Capturing a task costs one command or one sentence to Claude.