Skip to content

Task board — migration, notifications, data, shortcuts, board and SOP findings

Part of task-board. Design sections for the Kanboard task board: migrating the old tasks, notifications, adding tasks, data, home shortcuts, the board views and SOP findings as tasks. Text moved verbatim from task-board; references such as "above" and "below" point into that note or its sibling files.

Migrating what we already have

The 112 tasks in ~/.local/state/assistant/assistant.sqlite move across via JSON-RPC, one project per department, source/source_ref preserved in task metadata. Then:

  • tasks.py in the assistant stops being a store and becomes a thin client.
  • The admin Tasks card points at Kanboard rather than duplicating its CRUD.
  • tasks-export keeps writing ~/Notes/tasks.md, now reading Kanboard — the plain-text mirror in the vault is the copy that survives the server, and it is not negotiable.
  • The old sqlite table is left in place, read-only, until the mirror has matched for a week.

Notifications

Use Kanboard's, do not build one. It has per-user notification settings out of the box: email or web, and a filter for all tasks in my projects / only tasks assigned to me / only tasks I created. Wired to Resend over SMTP, which we already pay nothing for.

What that gives immediately, with no code:

  • assigned a task → email
  • a task you own is commented on, moved, or closed → email
  • Kanboard's daily cronjob command → overdue task notifications, plus recurring tasks

What it does not give, and we add:

  • "Due soon". Kanboard notifies on overdue, which is already too late. A small morning digest (the one planned for Phase 4) reads the API and mails each person what is due today and this week, one message rather than a stream. This is the reminder that actually works.
  • Push to a phone. Kanboard webhooks can drive ntfy for anyone who wants it on their phone rather than in their inbox. Optional, per person, and worth offering to Yara — she lives in a messaging app, not an email client.

Rules so the mail stays worth reading: default every new person to tasks assigned to me, never all activity; the digest is one email a day, not one per task; and nothing sends from a noreply address — mail comes from the shop address so a reply reaches a human.

Adding a task by hand

Four doors, one register behind them. Nobody should have to learn Kanboard to raise a task.

  1. The home board — a + Task button next to the lists. A short form: title, department (defaults to yours), assignee (defaults to nobody), due date, priority. Posts through JSON-RPC. This is the door most people will use, and it is deliberately smaller than Kanboard's own form.
  2. Kanboard itself — the full board, drag-and-drop, columns, comments, attachments, subtasks. For whoever wants the real thing. Linked as a tile.
  3. The assistant — "add a task for Purchasing to re-price the LCSC line by Friday". create_task already exists and already drafts-then-confirms; it gets repointed at Kanboard. Useful on a phone, where a form is a chore.
  4. The SOP audit and friends — automatic, covered below.

Whichever door, the same minimum: a title that says what done looks like, and a department. Assignee and due date may be empty — an unassigned task in the right team's column is honest, and a fake owner is not.

Data

Kanboard's own task fields cover title, description, due date, priority, assignee, column and project. What it has no first-class notion of, we keep in task metadata (its key/value store, reachable over the API):

Column Why
department the project already encodes it; mirrored in metadata so exports do not have to resolve project ids
ai_state queued / proposed / applied. Kanboard has an assignee but no notion of handing work to a machine
dedupe_key UNIQUE, nullable. The whole automatic-task mechanism depends on this
accepted_until a finding we have consciously decided to live with, and when to re-ask

The record Angel asked for — who closed it, how long it took — is Kanboard's own activity stream plus its time tracking, which is one of the better reasons to have adopted it. We read that stream rather than keeping a parallel log. The one thing we log ourselves is the AI proposal trail (proposed / reviewed / applied, per item, with the deciding person), because that is ours and has no home in Kanboard.

Shortcuts: the home page as the one front door

Today's tiles are hardcoded and everybody sees all eight, including the ones they cannot open. Once home is served by the assistant service it renders from each person's tiles: list in departments.yml, and the list grows to cover the outside services we actually use — the things Angel currently reaches by hunting a bookmark.

Two kinds of tile, and they should look different:

  • Ours — behind the Access gate, one Google login already spent: ERP, Assistant, SOPs, Reports, Admin, Vault, NAS, Sandbox.
  • Outside — someone else's login, opened in a new tab. Grouped under a quieter heading so nobody thinks the gate covers them.

Outside services worth a tile, from what is actually configured on this server (~/.config/) and in the project notes:

Tile Who needs it
Business Gmail / Google Workspace admin Administration, Sales
Cloudflare dashboard (DNS, Pages, Zero Trust, R2) Administration
GitHub — EmbeddedEra org Engineering, Administration
DigiKey · Mouser · LCSC · JLCPCB Purchasing, Engineering
eBay Seller Hub · Amazon Seller Sales
Resend (email delivery) Administration
Uptime Kuma Administration
The public site + the quote inbox Sales, Administration

And one new one of ours: a Notebook tile for the plans, decisions and hardware notes published from the vault — see notebook-site.

Rules for the tile list, so it stays honest:

  • It lives in departments.yml next to everything else that decides who sees what. One registry, not a second list in the HTML.
  • Every tile says which host it goes to, as they do now, and outside tiles are marked as outside. No pretending a third-party login is covered by ours.
  • A tile a person cannot open is not shown. Half of what makes the current page feel like a patch is offering people doors that are locked.
  • LAN-only tiles (the NAS) keep the existing shop-network-only treatment.

The board

Per person, three lists (stacked on a phone, columns on a laptop):

  • Yours — assigned to you
  • Your team — your departments, unassigned or on someone else
  • Due and overdue — across your departments, overdue first and in red

Each row: title · department chip · due date · who has it. Row actions: Done (demands a note, same as the admin card already does), Reassign, Due date, Hand to AI. One + Task button. Administration gets a fourth view: everything, plus closed history and the numbers.

Phone-first at 375 px, three-state theme, Home link, brand tokens — the house rules for internal pages, no exceptions for this one.

SOP findings become tasks

sop-audit already emits stable check ids (SOP-002.no-image) with a count and a sample. That is the whole hook.

  • One task per failing check, never per failing item. 43 parts with no image is one task that says 43, not 43 tasks. The sample goes in the detail and the count updates.
  • dedupe_key = "sopaudit:<check_id>". Each nightly run: failing and no open task → create; failing and already open → refresh count and detail, leave the due date and assignee alone; passing and open → close it automatically, actor sop-audit. The board empties itself as the shop gets fixed, which is the only way people keep trusting it.
  • Routing needs no new registry. Each check carries its SOP number; each SOP's front-matter owner is already a department. Finding → SOP → owner → team.
  • Severity sets priority sets the default due date (high 7 days, normal 30, low none), from one dict that lives next to the check table.
  • Accepted risk is mandatory. A finding we have decided to live with gets a note and an expiry, and the audit will not recreate it until then. Without this escape hatch a permanent nag trains everyone to ignore the board — that is what kills audit dashboards.

The same hook takes any source with stable keys: backup canaries, the Access drift alert from onboard access-sync, SMART warnings. Worth naming now, not worth building yet.