Auto Kanban logo

Auto Kanban

Community
ojiudezue
auto-kanban

A capture-first kanban board for agent-driven work. Fights chat-to-plan context loss with one rule: every user push AND every agent mid-turn discovery becomes a card the SAME turn, before acting. Source of truth is a structured YAML data file (committed); markdown and HTML views are regenerated by a render script that shows a STALE banner when code or docs move without a board reconcile; the release script refuses to deploy without naming the cards being shipped and marks them shipped as part of the deploy flow; a hosted board's disposition buttons (done/deferred/declined + approve/investigate on intake cards) queue operator dispositions the agent applies at session start. Load this skill at session start, whenever the user pushes a new idea or request, whenever the agent proposes something mid-turn (a test, a config knob, a bug it just found), and before writing a planning doc (to harvest cards into the plan). Includes the adjacency sweep, finish-the-job rule, an Investigating lane with binary exits, verify-before-work against ground truth, a config-first gate step, card linking, and the unattended overnight-pass contract.

Overview

Publisherojiudezue
Repositoryproductmind-skills
Skill nameauto-kanban
Stars
81
Forks
18
Bundled files
2
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 2 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by ojiudezue on GitHub. Read the source before you install it.

Installation

Install the Auto Kanban AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/ojiudezue/productmind-skills/tree/main/skills/auto-kanban
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/ojiudezue/productmind-skills.git /tmp/productmind-skills
mkdir -p .claude/skills
cp -r /tmp/productmind-skills/skills/auto-kanban .claude/skills/auto-kanban
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Auto Kanban in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Auto Kanban on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Auto Kanban is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Auto-Kanban — capture-first board for agent workflows

A single durable board for bursty, multi-thread work between a human and an AI agent. It exists because chat is a terrible database: the agent's context compresses and compacts as a session runs, and anything that lives only in the transcript eventually decays into a summary of itself.

Why This Is a Product Skill

Losing a thread isn't an engineering annoyance — it's how product intent leaks out of a build. The constraint a stakeholder stated in passing, the alternative that was considered and rejected, the half-formed idea that would have become the next feature: these are product decisions, and chat memory silently drops them. A capture-first board makes the backlog a property of the system, not of anyone's memory.

Why this exists

Chat is linear and lossy. The agent compresses as it goes; context compaction preserves decisions but strips texture — exact phrasings, half-formed asides, and above all the origin pointer (which message an item came from). When a plan is later written from working memory, anything that scrolled out of context is reconstructed from the compressed summary, not the source. The result is conceptual entropy: constraints stated in passing vanish, rejected alternatives resurface as fresh proposals, verbally-proposed config values never get named settings, and the agent's own mid-turn discoveries (a bug found inside a tool call) are never promoted because they didn't come from the user.

Two failure modes this system kills:

  • Capture failure — a user request or flag is acknowledged in chat but never acted on, and falls out of context hours later.
  • Reconciliation failure — stale context is carried forward (the agent nags the user about something they already did, or re-plans work that already shipped).

When to load this skill — invocation points

This skill is meant to be loaded at session start automatically and re-entered at specific events, not left to memory. Two mechanisms guarantee the session-start load: a SessionStart hook that injects a load reminder + disposition/stale check, and a project-instructions line that names it. Load it at every point below:

Invocation pointWhy
Session start (auto — hook + project instructions)Read the board, apply queued dispositions, run the renderer's --check, reconcile before reporting status.
Every user push / new requestCapture the card(s) the same turn, before acting.
Any mid-turn discovery (a bug/knob/constraint inside a tool result)Card it before continuing — mid-turn finds are the most fragile.
Before writing a planning docHarvest the relevant cards into the plan (the anti-entropy handoff).
Before dispatching a buildBoard maintenance — move the target card to In-progress, reconcile siblings.
Deploy / commit / release write-backReconcile In-progress → Review → Shipped (release-coupled gate).
Turn end (state changed)Move cards, re-render, redeploy the hosted view.
Grooming / lull / overnightSweep, dedupe, link, AND score (rank: inputs) — ranking is part of grooming.
Picking "what's next"The ranked board is the source of the next task — drive from it, don't ask.

If the skill is already loaded this session, re-entry is cheap — follow it; do not re-ask whether to load it.

The one rule: capture-first

Every user push AND every pre-planning idea the agent generates lands in the data file as a card in the same turn, before acting — Inbox first, unprocessed. Nothing is allowed to live only in the transcript. This includes the agent's own mid-turn finds (bugs, config knobs, risks surfaced inside a tool result) — those are the most fragile, because nothing else will ever re-raise them.

Capture-at-handoff — the sibling failure to capture-at-turn. Session-close handoff notes and decision-journal / vibememo entries routinely record forward decisions ("the real fix is a RAM upgrade", "next we should migrate X") that never become cards, because the handoff-writing path does not route through card creation. The result is a decision that is documented but invisible to every status-first read of the board — the exact loss capture-first exists to prevent, just displaced to the end of the session. Rule: writing a handoff or a decision-trail entry is a capture trigger. Every forward-looking decision in it must be minted as a card in the same commit. If it is worth writing down for the next session, it is worth a card the next session can actually see.

The second rule: adjacency sweep before a new card is accepted

No new card is accepted as its own item before sweeping ALL existing work for adjacency or duplication. This does not weaken capture-first — capture into Inbox immediately, then run the sweep before the card is promoted out of Inbox. Board hygiene fails in the mirror-image direction from capture failure: a board that never merges becomes a list nobody reads, and duplicate cards split the evidence for one problem across two places so neither is decisive.

The board is NOT the whole prior art. Sweep all four surfaces, in order — skipping the last two is the observed failure mode:

  1. The board data file — every card's title + why, not just the thread you assume it belongs to. Adjacency routinely crosses threads.
  2. The project's backlog file(s) — newer diagnoses often land there, not on the board.
  3. Parked / deferred deliverables inside planning docs ("plan completion tracking" sections). A parked deliverable with an evidence trigger is a card living in a planning doc. This is the surface that gets missed, because it looks like shipped work.
  4. Catalogs / audits / probe results — the extend-vs-new adjudicators.

Test the relationship in order:

  • Duplicate — same problem, same fix surface → merge into the existing card; do not create.
  • Adjacent — different problem, but same code surface, same decision, or same discriminator → fold in as a sub-finding, or create with an explicit link (see "Card linking"). Adjacency is the case most often mis-filed as new.
  • New — no shared surface or decision → create it, and record what it was swept against.

Is it a new card or an INSTANCE of an existing one? A newly-measured occurrence of a defect that is already carded is an instance: append it to the existing card as a dated INSTANCE_<date> block. "It was found in a different cycle" is not a reason for a new card.

Record the ruling on the survivor (DEDUPE_<date>: what was folded in and why) — a silent merge is indistinguishable from a dropped card three weeks later. Merging is lossy if careless: the survivor inherits the union of Origin / Constraints / evidence, never the intersection. A parked item whose trigger has since fired is not done — it is READY; promote it, don't re-plan it. And check parked-plan triggers at cycle close, not only at card creation: a shipped cycle often fires a parked plan's revival trigger and nobody notices until the human asks.

The third rule: finish the job — don't leave siblings carded

Decomposing one body of work into pieces (deliverables D1..Dn, tiers, a cluster of cards in one arc) is a commitment to finish the whole set, not a menu to pick one or two from. Shipping part of an arc and leaving the sibling pieces as open cards is the failure mode — the human looks at the feature and doesn't see the work, because the visible half wasn't built.

  • Capture-first still holds — the failure is carding-instead-of-finishing, not carding.
  • Drive the whole decomposed set to done.
  • The one legitimate stop is a real divergence — the remaining pieces are genuinely a different objective / code area / risk owner. Then ask to stop and re-sequence; never leave them silently. A different tier of the SAME problem is not a divergence.

Finish-the-arc mechanics — five rules

Field finding from an arc review: work is rarely lost outright — it piles up (in one month, 69 cards opened vs 31 closed; 40 parked on the human; a card in-progress for two months; built work in review for a month). Goal: finish the key parts of an arc and don't spawn unfinished tasks.

  1. Arc-close at release (make it HARD). The release script's card gate also checks the shipped cards' arc siblings (same batch, same or pointing links.parent, or sibling_of). An open sibling blocks the release unless it ships in the same release, is parked with a trigger, or is cut with an explicit reason that gets written onto the card. Set batch: / links.parent when you decompose an arc, or the gate can't see it.
  2. Recommend, don't menu. A waiting_user card's next states the default the agent will take and why. For low-tier, reversible, non-outward-facing cards, if the human hasn't vetoed by the next session, take the default and record it. Everything else still waits for an explicit answer.
  3. WIP cap on built work. A review card older than ~7 days gets the first slot at the next attended release, ahead of new builds. An unattended pass doesn't start a new build while ≥3 cards sit in review; it drains them instead.
  4. Residuals fold into the parent. A leftover from an investigation or a ship is a dated block on its parent card unless it has its own problem statement, fix and acceptance criteria.
  5. Capture covers everything that changes the system, not only the main repo's code: config changes made through tools/UIs, sibling-repo work, and cross-session hand-offs. These are the changes that most often never get a card, because they never touch the code path.

Architecture — structured data as the source of truth

The board is data, not prose:

  • Source of truth: kanban.data.yaml — structured cards, committed to the repo. Edit HERE. Must stay valid YAML before every commit.
  • Generated views: a render script (render_board.py or equivalent) reads the YAML and emits KANBAN.md (human-readable markdown) and board.html (self-contained static page). Views are a pure function of the data — same input, byte-identical output. Never hand-edit a view; edit the YAML and re-render. Regenerate on every data commit, so a committed YAML change can never leave a view describing the previous board. If the board is hosted somewhere (a static file behind a tiny web server), a cron pull-and-render job on the host is the robust default over git hooks: hooks fire per-clone, and once multiple clones or worktrees edit the repo, some editor will always be missing the hook. A dumb loop that pulls and re-renders every few minutes converges no matter who committed from where.
  • Staleness banner (the freshness contract): the data file carries meta.last_reconciled. The renderer compares that date against the newest signal of shipped work and, if any is newer, renders a loud STALE banner into every view (markdown, HTML, hosted page), warns on build, and exits non-zero in --check mode. Reconciling the board (moving the shipped cards, then bumping meta.last_reconciled) is what clears it. A board that must be interrogated for staleness is not a mechanism; a banner that appears by itself is.
    • Wire the trigger to what THIS repo actually moves — not to a signal it never emits. The original design keyed only on the newest git tag + newest release-notes file. That is silent in any repo that ships without tagging or writing release notes (observed in production: 26 work commits, board 2 weeks stale, banner never fired because the repo has zero tags). The load-bearing trigger is the newest WORK commit — the newest commit touching any file other than the board's own files (exclude kanban/*, the rendered views, and the render script itself, so a pure reconcile commit does not re-trip it). Keep the tag/release-note checks as additive, but the commit check is the one that fires. A banner wired to the wrong signal fails exactly as open as no banner at all.
  • History: done cards age out of the active data file into kanban.history.yaml rather than bloating the board. Git history is the durable record.

Board render design — autonomy visibility + operator agency

The render exists to make autonomous work visible and steerable, not just to list cards. Three elements, all pure functions of the data (so a view can never drift from the board):

  1. Lane order elevates the human decision queue. Render the "waiting on the human" lane(s) immediately after review (ahead of shipped/organic), so cards needing a call are near the top — and groom that lane FIRST each session (a card whose input already arrived is a grooming miss).
  2. "Waiting on human" cards carry a free-form instruction box (not just fixed buttons). It posts {card_id, action:"instruct", text, at} to the same disposition endpoint the buttons use; the agent applies it at session start (writes the instruction onto the card, front of the grooming queue, treats it as authority). This is the human's free-text steering channel — no drop back to chat.
  3. Top-of-board autonomy counter + recent-work feed (a meta.autonomy_feed list):
    • Counter (large type, above all lanes): N / D where N = feed entries concluded in the last 24h (ack-agnostic — a conclusion is a historical fact) and D = open-card count (status != done). D shrinks as work completes, and the ratio is recomputed every render, so it re-bases after each push automatically.
    • Feed: an expandable list of entries that are NOT acknowledged AND younger than 7 days, newest first. Each has an Acknowledge button (posts {card_id:<feed-id>, action:"ack"}); ack retires the entry from the live feed, and any entry older than 7 days auto-archives (hidden) regardless — so the feed never clutters.
    • Append discipline (load-bearing): every time a card is concluded autonomously (built / parked-at-gate / moved to waiting / shipped / done), append one feed entry the same turn. A conclusion with no feed entry is invisible to the human's 24h view — the same capture-failure the board exists to kill, applied to the progress counter. Prune acknowledged / >7-day entries during grooming so the data file stays lean.

Board-stack BLUEPRINT — the contract every board implements itself

When a project runs MULTIPLE hosted boards, do NOT hand-patch each host's server per change — that coupling is what this blueprint removes. The skill IS the contract: any agent maintaining any board reads it and brings ITS OWN render + server into conformance. Maintain one reference implementation.

  1. Disposition API. A tiny static-file server + micro-API: POST /api/disposition {card_id, action, at[, text]} appends one JSONL line — action ∈ done|deferred|declined|approve|investigate|instruct|ack|move:<status>; text is OPTIONAL free-form (operator decision/instruction), capped, and MUST be preserved, not stripped (for ack, card_id is the feed entry id; for instruct, the card id). GET /api/dispositions returns the raw queue; POST /api/dispositions/clear truncates after a successful import. The puller carries text through to the pending file and includes it in the dedup key.
  2. Serving model → why a shim exists. Boards are usually served as a CACHED STATIC file, re-rendered on a cron — so a click's state must survive a reload before the next render via TWO layers: (a) the render reads the pending queue and paints the acked/decided state server-side (durable); (b) a small localStorage echo + CSS class toggle re-applies it instantly on reload. That is the only client state — no framework. Per-request rendering makes (b) optional.
  3. Render contract. Counter N/D (shrinking denominator); feed entries show an Acknowledge button, and "waiting on human" entries ALSO show an inline decision box (posts instruct on the card); acked entries render IN PLACE as "acked — pending apply" (never optimistically removed); queued decisions show a "decision queued: …" chip; the human-decision lanes render elevated.
  4. Groom-time reconciliation. ack → mark the feed entry acknowledged AND, if its card is in a terminal-ready lane and the work is complete, MOVE the card to done (an ack is acceptance, not a dismissal). instruct → write the decision onto the card and move it to the lane the decision implies. Then prune acked/decided entries and re-render. Never leave a half-applied disposition.

Self-conform rule: change this blueprint first, then each board's agent brings its render + server into conformance from the spec — the skill is the single source; per-host files are conformant implementations.

The ship gate — board currency as an output of releasing

Board reconciliation is typically the only step in a release ritual with no forcing function: the deploy script refuses to run without tests and without release notes, but nothing refuses without a board update — so it runs on willpower, and rots. Fix it by making the board update an output of shipping, never a task beside it:

This is rung 1 of the board-currency ladder — the one hard forcing function; the staleness banner and session-start checks below it are soft backups, never substitutes:

  • The release script takes --cards ID[,ID...] naming the board cards being shipped and refuses to deploy without it, printing the current in-progress/review cards as candidates.
  • Card IDs are validated before anything is pushed.
  • After a successful push, the script writes status: shipped + the released version onto each card, updates meta.last_reconciled, and (if you keep a decision journal) emits the "why we shipped this" entry — so the status board and the decision trail cannot lag the release.
  • An explicit --no-cards escape exists for pure-docs releases; it is logged, never silent.
  • Safety rule: a failed board write must never abort a deploy that has already pushed. Write after the push succeeds; warn loudly on failure; never exit non-zero post-push. A stale board is strictly better than a half-released version.

Rung 1 only bites if shipping actually runs through it. In a repo that deploys by many paths that were never built to call the release script — pct push, vercel --prod, ad-hoc host scripts, a session-close handoff commit — the ship gate is simply bypassed and the board rots anyway. Do not assume one release ritual. Instead hook the reconcile onto the real deploy paths: add a post-deploy step (a git post-commit/post-push hook, or a line at the end of each deploy script) that runs render_board.py --check and surfaces its non-zero exit. That converts every real shipping path into a reconcile prompt, so the forcing function follows the work instead of waiting at a door nobody uses.

Overnight / unattended work needs a scheduler, not an intention

"Build it tonight while I'm sleeping" has no forcing function: the session ends and nothing wakes anything up. Work tagged for unattended execution must be bound to a real recurring scheduled job whose first action is a board reconcile. An overnight commitment with no scheduler is a promise — and "documented but never wired" is itself a finding (observed: an investigations lane didn't drain for days because the nightly pass was specified in the skill but never scheduled).

Pick the vehicle by what the work must reach. If the measurements need private-network data (a LAN database, SSH to a home server, local MCP servers), a cloud-hosted scheduled agent cannot run them — it has none of that reach. Run it as a local scheduled job (launchd / cron / systemd timer) on an always-on machine that already has the access, invoking the agent CLI headless. A cloud routine is fine only for code-side work: reconcile, static/prior-art investigation, low-tier builds.

The pass contract, in order, every run:

  1. Reconcile first. Load this skill, apply queued dispositions (including instruct / ack), run --check, move disposed cards to their lanes, prune acked / >7-day feed entries.
  2. Verify-before-work, then drive the ranked eligible queue through the full gate. Groom the waiting_user lane first, then investigating: run each investigation's one-shot read-only measurement, record it on the card, then escalate or build.
  3. Bounded autonomy — MORE conservative than an attended session:
    • Investigations + read-only probes: fully autonomous.
    • Low-tier builds that pass the gate: build + review + validate to review only — never deploy unattended. A deploy at 3 a.m. into a live system nobody is watching is hostile timing. Leave shippable work in review with tests and release notes done.
    • Delicate / ambiguous / destructive / outward-facing: don't act — move to waiting_user with a user-verb next, and send a real notification.
  4. Append a feed entry for everything concluded (measured / built-to-review / parked / escalated), timestamped from the real clock, so the morning counter reflects the run. The board + feed IS the report. Respect a token budget; stop when the eligible queue is dry; never spiral.

An unattended pass shares the checkout with any attended session. If a human-driven session starts while the pass is running, it should detect the pass (process list / lock file) and hold its own repo writes — or the pass should run in its own worktree — so two writers don't edit the board file at once.

Operator dispositions — a one-way human-to-agent queue

If the board is hosted as a web page, the human will read it when the agent isn't running — and will want to act on it. Give every card disposition buttons (done / deferred / declined) that write a disposition queue file (append-only JSONL is plenty: {card_id, action, at} per line) rather than editing the YAML directly. The web page never writes the source of truth; it queues intent.

At session start, before reporting status, the agent applies the queue to the data file with operator authority — apply, don't relitigate:

  • done → mark shipped/done per the card's context.
  • deferred → move to parked, adding a revisit note.
  • declined → close the card, recording the decline the way a rejected alternative is recorded.
  • approve (early-stage cards: inbox / pre-planning) → mark the card explicitly approved with board-button attribution and promote it out of raw intake. Out-of-band approval carries the SAME authority as an in-chat "go" — the agent must not re-ask.
  • investigate (early-stage cards) → flag the card needs_investigation: true; it jumps to the front of the next lull-investigation sweep (below).
  • instruct (waiting-on-human cards) → carries a text field with the human's free-form instruction. Append it onto the card, treat it as authority (act on it, don't re-ask), and put the card at the FRONT of the grooming queue. It usually says how to resolve the card — follow it, moving the card to the right lane; if it asks for something that fails a gate, notify back + record why.
  • ack (recent-work feed entries) → the card_id is a feed entry's id; mark that meta.autonomy_feed entry acknowledged: true so it retires from the live feed. Not a card-status change.

Then delete the queue file, re-render, and commit. Ask only when a disposition is ambiguous against the card's state (e.g. done on a card that never shipped). Dispositions are strictly one-way, human → agent: the queue is how the human drives the board asynchronously, never a channel the agent writes to.

Force the apply, don't trust it. The queue-apply step will silently rot if it relies on the agent remembering it (observed: a declined sat unapplied for a day because the pull-cron ran but nothing forced the apply). Mechanism: the renderer's --check mode returns a distinct non-zero exit code when the queue file is non-empty, enumerating the unapplied entries — so the session-start check cannot pass while a button-tap is pending. Scope the failure to --check only, so the hosted-page render still deploys (with pending chips visible) even when the queue is waiting. A chip is a banner; the exit code is the mechanism.

Two field notes from running this mechanism in production: (1) isolate the renderer's tests from the live queue — a --check exit-code test that doesn't pass an explicit (empty) queue path inherits the repo's real pending file and fails whenever a genuine disposition is waiting; point tests at a tmp queue path and add a dedicated exit-code test that seeds a fake pending entry. (2) verify the whole button→queue→apply loop end-to-end after adding an action — the hosted page's API may validate actions against a whitelist regex; a new button that renders fine can still be silently 400'd server-side. Probe-POST each new action and clean the probe entries from the queue before the next session-start apply.

Inbox hygiene — bounded lull investigation

An uninvestigated intake card is phantom load: it sits on the backlog looking like work while nobody knows if it's a duplicate, already-shipped, config-only, or real. Worked case: one context-wide audit killed a proposed guard card entirely — the existing codebase already had the guard, the proposed discriminator would have caught nothing, and the real fix was a three-entity config swap. Without the audit, a full planning + build cycle would have been spent on the wrong mechanism.

The rule: during lulls (no human turn pending, no build to verify) and on scheduled autonomous passes, sweep intake cards (inbox + pre-planning) through a context-wide investigation — the whole system, not just the subsystem the card names — before they age. Cards flagged needs_investigation (the 🔍 button) jump the queue.

Token bound (hard): ONE search-grade agent per card, single dispatch, no fan-out — set an explicit per-card budget and a per-lull cap (e.g. ≤100k agent tokens per card, at most two cards per lull window). If a card can't resolve inside the budget, that fact IS the finding: record "needs a real planning cycle" and stop digging. Never spawn a review chain or multi-agent workflow for intake triage.

Verdict vocabulary (recorded on the card, same turn): DUPLICATE/ADJACENT (merge) · ALREADY-SHIPPED (close with evidence) · CONFIG-ONLY (stage the fix, close the card) · DEAD (threat model gone; close with the evidence chain) · REAL (promote with the investigation as context) · UNRESOLVED-IN-BUDGET (needs a planning cycle; say what couldn't be determined). An investigated card never returns to plain intake — it moves or it closes.

Watch results write back to cards

When a shipped item's live/organic validation lands — a monitoring pass, a metric read, a user report confirming or violating the ship hypothesis — the result is written back onto the card the same session. This is codified, not best-effort:

  • confirmed → append an evidence line (date + one-line observation) to the card; when all of a card's open hypotheses are confirmed, move it to done.
  • violated → the card returns to review with the violation recorded on it — the regression belongs to the shipping card, not to a fresh card that severs the history.
  • pending → no edit required, but if the proof needs a human action, the card's next must say so explicitly.

A validation result that lives only in a monitoring report or a decision journal is a capture failure: the board is where "is it actually done?" gets answered.

Card schema — the fields ARE the decay vectors

Fill Origin, Why, and Next even when terse. Each field maps to a specific context-loss failure mode it kills:

FieldKills this leak
Status / Threadwhich workstream — prevents cross-thread confusion
Created / Updated (date + time)staleness and churn — a card untouched for weeks, or thrashing daily, is visible at a glance
Refinement status (initial vs refined)whether the plan is as-first-written or has been reworked — a reader knows if it's a raw idea or a hardened one
Problem / Solution (plain language — mandatory)the core — what is wrong and what fixes it, in words anyone can read. See "Problem/Solution framing" below
Origin (date + one-line gist of the originating push)the origin pointer — full intent stays reconstructable after the message scrolls out of context
Whyrationale — a settled decision doesn't get re-litigated in a later session
Constraintsmusts stated in passing ("must never auto-send", "keep the URL stable") that otherwise evaporate
Parked-alts (+ why rejected)rejected options resurfacing as fresh proposals
Knobsverbally-proposed configurables actually becoming named settings instead of magic numbers
Nextthe single next action — a card is never inert; a title with no Next is a transcript line, not a card
Refsplanning doc / review record / commit — the card links to the durable artifacts

Card template (as it appears in the YAML):

yaml
- id: CARD-1
  title: One-line plain-language problem -> solution statement
  thread: area              # workstream
  status: inbox             # CLOSED SET: inbox / investigating / pre_planning / planned /
                            # in_progress / review / shipped / waiting_user / waiting_agent /
                            # parked (+ done in history). Never coin a synonym.
  created: '2026-01-01 14:30'    # date + time the card was born. Set once, never changed.
  updated: '2026-01-02 09:15'    # date + time of the last material edit. Bump on EVERY edit.
                                 # created == updated on a new card.
  refinement_status: initial     # 'initial' (as first written) or 'refined' (reworked since).
  problem_solution:         # MANDATORY, plain language (see "Problem/Solution framing" below).
  - 'Problem: <what is wrong, in plain words a non-expert reads once and gets>.
     Solution: <what we will do about it, same plain words>.'
  approval: unreviewed      # unreviewed / implied / explicit / blocked
  origin:
    date: '2026-01-01'
    gist: one-line gist of the originating push
  why: rationale, so the decision is not re-litigated
  constraints: []
  parked_alts: []           # rejected options (+ why)
  refinement: []            # append-only challenge -> sharpened-form beats; length = how much reworked
  knobs: []                 # named configurables this card introduces
  next: single next action
  refs: []                  # docs / commits / reviews
  rank:                     # all optional — the board ranks on defaults until these are set
    value: 5                # 1-10, user / $ / safety / correctness impact (default 5)
    time_criticality: 3     # 1-10, how fast the cost of delay grows (default 3)
    effort: 5               # fibonacci job-size; omit to derive from a tier tag
    foundational: 0         # 0-10, platform-piece leverage that link fan-out misses (default 0)
  links:                    # cards are a graph, not a list — every link carries a one-line context
    blocks: []              # cards that cannot proceed until this lands
    blocked_by: []          # what this waits on — mirrors the other card's `blocks`
    related: []             # same family, no dependency
    parent:                 # the card whose fix subsumes this one
    sibling_of:             # two faces of one problem
    superseded_by:          # this card's premise was replaced (link, don't delete)
    context: 'ONE SENTENCE PER LINK saying WHY it is linked — a bare id is noise.'

Problem/Solution framing — plain language, mandatory

Every card carries a problem_solution written so a person who was not in the room — the user weeks later, a teammate, a future agent with no context — reads it once and understands both what is wrong and what you intend to do. Two rules:

  1. Problem then Solution, explicitly. State the problem as its own sentence (what is broken or missing, and why it matters), then the solution as its own sentence (what you will do). Not one blurred clause.
  2. Plain, non-jargon language. Write it for a smart reader who does NOT carry the codebase in their head. Acronyms, file:line refs, internal symbol names, and shorthand are a memory burden — they force the reader to reconstruct context the card should have supplied. Put the dense detail where it belongs (a refs: pointer, a forensic key, the reasoning log) and keep the problem/solution readable on its own.

This does not mean dumbing down the engineering — it means the entry cannot be legible only to the person who wrote it that night. If a sentence needs a symbol name to be true, name it once and say in words what it does.

Too much jargon (memory burden): "P8 exterior count STRANDED + naive: count_deduped() live w/ ZERO consumers; _calc_sum sums one bit/sensor (no dedup) -> retire per-sensor sum for the deduped path."

Plain (anyone reads it once): "Problem: two systems count the same thing and disagree — one counts a single item once per sensor that sees it (so one thing can read as three), and the accurate one isn't shown anywhere. Solution: show the accurate count; keep the rough one as a never-misses backup. (Details in refs.)"

The plain version is longer in words but far cheaper to read — no decoding. Optimize for the reader's effort, not the writer's. Retro-fix as you touch: don't mass-rewrite the board; when you next edit any card whose problem/solution is jargon-dense, rewrite that one plainly in the same edit (and bump updated). The board converges through the update hooks, not a big-bang pass.

Timestamps and refinement status — hooks, not memory

  • created is set once and never changed. updated is bumped to the current date+time on every material edit — it rides the same update hooks that govern the rest of the board.
  • refinement_status starts at initial; flip it to refined the first time the card's plan or scope is reworked (not a mere status-column move). The refinement trail's length then shows how much. Together they answer, at a glance: raw first idea, or been through the wringer?
  • The renderer surfaces created / updated / refinement_status on each card in both the Markdown board and the hosted page, so staleness and maturity are visible without opening the YAML.
  • Every timestamp comes from the real clock — read it, never estimate it. Run date (or the equivalent) when stamping created / updated / feed at / any "measured at HH:MM" note. An agent has no reliable sense of wall-clock time, especially a long-running unattended one, and will happily write times that haven't happened yet (observed: an overnight pass stamped feed entries 02:20–03:05 while the clock read 02:10, and a "measured ~07:46" note five hours early). Invented times corrupt the 24-hour progress counter, the staleness ordering, and the anti-starvation tiebreak — and they read as evidence. Use one timezone consistently and say which.

Cards stay true — understanding changes, the card changes the SAME turn

A card is not a task ticket; it is the durable record of what we currently believe. A superseded belief left on a card is a trap set for the next session. Edit the card in the same turn whenever:

  • A root cause is refuted or replaced. Don't just add the new story underneath — mark the old one WRONG and say what killed it. A card carrying two mechanisms and no verdict is worse than one carrying a wrong mechanism, because the reader can't tell which survived.
  • A claim the agent made turns out false — including one made to the human in chat. Retract it ON THE CARD ("I claimed X; that is wrong; here is what refuted it"). Chat scrolls away.
  • Scope changes (something folded in, dropped, handed to another card) — record the decision and its reason, so a reader sees a choice rather than an omission.
  • An estimate becomes a measurement. Replace the guess with the number and how it was obtained.

Test: would a fresh session, reading only this card, act on something we now know is untrue? If yes, edit it now. "The fix is happening in another card" or "the fix will make it moot" are not reasons to defer — a fix in flight can be abandoned, and then only the card remains.

Status must track reality, not just the body. Whenever you write a material update to a card, ask what lane it is now in and move it in the same edit (and bump updated). A card whose body is actively changing while its status still says inbox, or whose implied next step clearly changed (audit finished, build landed, blocker cleared) but nobody moved it, makes the lane view lie — and the lane view is how a returning human reads the board. Common prompt transitions: capture gains a measurement plan → investigating; investigation finds a mechanism → pre_planning/planned; investigation refutes → done; a branch with real work exists → in_progress; needs a human call → waiting_user; the agent owes a check → waiting_agent (never the human's lane).

Card linking — cards are a graph, not a list

A board of unlinked cards loses its most valuable information: which findings are the same finding, which blocks another, which parent will actually fix a symptom. Several of the highest-value findings on a mature board are only visible as relationships — two cards that are one bug carded twice, a cluster of consumers all sitting on one partly-dead producer.

Use the links: block from the card template. Rules:

  1. context is mandatory and is the point. A bare id says two cards touch, not what the relationship buys the reader.
  2. Link at creation, not at cleanup — a link added later has already failed the reader who needed it.
  3. blocks / blocked_by are mirrored on both cards; a one-sided dependency is invisible from the side that needs it most.
  4. Gating is a link, not a note. When several cards wait on one input, put blocked_by on each so ranking can't pick a card whose input isn't ready.
  5. When you refute or supersede, LINK — don't delete. The refuted card is the record of why the current answer is the current answer.
  6. Contradictions get linked too — say so in context, before a builder discovers it mid-cycle.

In prose, reference cards as [[CARD-ID]]; a reference to a card that doesn't exist yet marks work worth carding, not an error.

Columns

Inbox (raw capture) → Investigating (we do not yet know what is true; measuring) → Pre-planning (idea being decomposed) → Planned (has acceptance criteria) → In progress → Review → Shipped — plus three side lanes:

  • Waiting on user — decisions or actions only the human can take.
  • Waiting on agent — things the agent owes (a promised verification, a re-measurement). Track obligations on both sides; filing the agent's own debt under the user's lane hides it.
  • Parked — deliberately deferred, always with a written revisit-trigger. Parked is not done: when a trigger fires, the card is READY, not forgotten.

The next of a waiting_user card must open with the USER's action verb, not the agent's. The card is in this lane because the ball is in the human's court, so its next must name the concrete thing they do — APPROVE (scoped, needs a go/no-go) · PICK (a choice between named options A/B) · ANSWER / VERIFY (a fact only they know) · DO (a physical or external act) · REVIEW (read a delivered doc). Write it as VERB: <the ask> -> <what I do on your answer>, so the human sees their decision first and the downstream work second. A next that opens with the agent's verb ("Add the OFF path…", "Run the reviews…") is the drift this kills: it reads as work parked on the human when it is really the agent's work waiting on one input, and it hides what is actually being asked for. The most common real action is APPROVE or PICK — if a card can't reduce to one of the five verbs, it may be mislaned work the agent can drive under implied approval.

status: is a closed set, and it is the ONLY lane field

Status values are a closed set — inbox, investigating, pre_planning, planned, in_progress, review, shipped, waiting_user, waiting_agent, parked, done. Inventing a near-synonym (intake, todo, blocked) is a silent hygiene failure: the renderer cannot lane it, so the card vanishes from every status-first read while still looking filed (observed: a session coined intake for all seven cards it created that day; every one dropped out of the lane view). If a card fits no lane, discuss the lane — don't coin a status.

One field owns the lane. Do not let a parallel field (column:, state:, lane:) carry the same concept: the renderer buckets on status only, and anything else falls into a bucket nobody reads (observed: a quarter of a board carried its lane in a legacy column: field — perfectly valid values, completely invisible). Two failure shapes look different and read identically on the board: a card in a lane that no longer matches its work (stale value — a judgement error), and a card whose lane the renderer can't see at all (wrong field or invented value — silent, and worse).

Investigating — the step before pre-planning

Pre-planning means we know the problem and are shaping the solution. Investigation is the step before that: we do not yet know what is true, and we are measuring to find out. Different activity, different exit. Without this lane, a card carrying hours of measurement, refutations and corrections sits in Inbox looking identical to a one-line shower thought.

Entry: the card's next action is a MEASUREMENT, not a build or a decomposition.

Exit is mandatory and binary — an investigation that can't say which is not finished:

  • CONFIRMED / mechanism found → promote to pre_planning or planned, carrying the evidence.
  • REFUTED → close the card (done) with the refutation recorded. A refuted investigation is a completed one; closing it is what stops the next session re-deriving the dead mechanism.

Cards must not rot here: an investigation with no measurable next step belongs in parked (with a revisit trigger) or waiting_agent (if the measurement is a debt the agent owes).

When an investigation surfaces real work — retire-and-relink, keyed on the problem statement. Ask one question: does the surfaced build have the SAME problem statement as the card's title?

  • Confirmed — the build IS the card's own premise → promote the same card in place. Don't spawn a new one; the history and evidence stay attached to the work they justify.
  • Refuted-but-fertile — the premise was wrong, but a DIFFERENT real problem surfaced → close the investigation done (refutation recorded) and open a NEW card for the different work, linked superseded_by / related with a one-line context. If a card for that work already exists, point at it instead of minting a duplicate.
  • Refuted-and-barren → close done with the refutation. A complete result, not a failure.

The failure this kills: an investigation that quietly becomes a build under a title describing the disproven hypothesis, so a later reader can't tell what the card is for.

Cadence — bind updates to events, not to a clock

Clock-based cadences ("update the board every 30 minutes") rely on remembering a separate chore, so they drift under load. Bind every board update to a checkpoint that already has to happen:

  1. Session start: read the board; apply any queued operator dispositions (see above); run the renderer's --check; if stale, reconcile against repo/live state before reporting status. Groom waiting_user first — re-verify whether each human input is still needed (the blocker may have cleared) and move cards whose input already arrived.
  2. On every push / mid-turn idea: add or update a card the same turn, before acting.
  3. Pre-planning harvest: before writing any planning doc, harvest the relevant cards — Origin / Why / Constraints / Parked-alts / Knobs flow straight into the plan. This is the anti-entropy handoff from chat to plan.
  4. Before dispatching a build — board maintenance for freshness. BEFORE an agent starts a build / implementation task, move the target card to In-progress then, not at turn-end — a card must never sit in Planned / Pre-planning while its build is actually running; the board should reflect what is happening the moment it starts. While you're there, quick-reconcile the sibling cards the build touches (dependencies, parked-alts, cards it will close). This moves work into In-progress sooner and keeps the board honest during long builds instead of lurching only at turn boundaries.
  5. Turn end: reconcile — move cards between columns, write one-line dispositions, re-run the renderer so committed views match the data.
  6. Release: the ship gate (above) marks cards shipped automatically.

Anti-patterns

  • A card with a title but no Origin/Next — that's a transcript line, not a card.
  • Letting a mid-turn discovery stay in the tool output "because I'll remember it."
  • Hand-editing a rendered view instead of editing the YAML and re-rendering — the data file is the source of truth; every view is a reflection, never the record.
  • Creating a card without first sweeping existing cards, the backlog, and parked planning-doc deliverables for duplicates or adjacent work — a board that never merges becomes a list nobody reads, and duplicates split the evidence for one problem across two places.
  • Silent moves: closing or moving a card without a one-line disposition. A card never just disappears.
  • Treating a parked item as done. Parked means "revisit-trigger set" — check whether the trigger fired.
  • Duplicating the decision journal's reasoning into the board, or the board's status into the journal. The board is WHAT / WHERE / NEXT; the journal is WHY. They compose.

Reference files

Product Lens

Before a card leaves Pre-planning, give it a parsimony verdict: is the problem sharp and real (one falsifiable sentence), and is the fancy version worth its marginal risk over the simplest version that captures most of the benefit? Record BUILD / SIMPLIFY / PARK / DROP on the card. Reaching "good idea, not worth it now — park with a trigger" is a success of the gate, not a failure.

Ranking & sequencing — computed, not eyeballed

Cards are not a flat list, and ranking is computed, not eyeballed — a deterministic score so the drive-loop picks the same "next" every time and the renderer can show it. The model is WSJF (Weighted Shortest Job First): cost-of-delay over job-size.

WSJF = (value + time_criticality + unblock) / effort          # rounded to 1 decimal
FactorRangeSource
value1–10rank.value (default 5) — user / $ / safety / correctness impact
time_criticality1–10rank.time_criticality (default 3); a card tagged live-broken floors at 8 — how fast the cost of delay grows
unblock1–10computed (below) — never hand-stored, so it cannot drift
effortfibrank.effort override, else from a tier tag: T1=2, T2=5, T2-DB=8, T3=13, untiered=5

unblock is leverage, and leverage is more than links. A platform piece that everything quietly stands on is a true unblock even when no card drew the edge, so:

unblock = min(10, max( 2 + 2×(#cards this blocks),  foundational ))
  • link component 2 + 2×fanout — from this card's links.blocks plus the reverse of others' blocked_by.
  • foundational — rank.foundational (0–10) set on genuine platform pieces, or a floor of 6 when tagged a platform-enabler / shared-primitive, else 0. The larger wins. When you build a new primitive many cards will consume (a shared resolver, a core producer, the test harness), set its foundational the same turn — its leverage is otherwise invisible.

The renderer computes WSJF — it is a pure function of the card data. So it works on every card via the defaults and sharpens as rank: inputs are set; you never renumber by hand.

Ordering — per-lane, at all times

Within EVERY lane, cards render first→last by WSJF descending (ranks are per-lane, so each lane shows its own #1, #2, …). Ties break by: (1) batch-affinity with an in-progress card (ship the batch together), (2) unblock desc, (3) oldest updated (anti-starvation — a card never rots at the bottom forever). The one exception is the shipped/done lane, which renders newest-first (WSJF is meaningless once shipped). Each card header shows #<lane-rank> · WSJF X.X · (v… tc… u… / e…), plus a ⚠ default-scored marker when a card is still running on tier + link defaults — so scoring effort lands where it matters.

Selection — display ranks per lane, the loop picks globally

Display is per-lane, but the drive-loop picks the globally highest-WSJF card that passes the eligibility filter — deps (blocked_by) all done, approval not blocked, and (for the highest tier) approval explicit. That card is always some lane's #1, so the per-lane #1s are the candidate pool and the agent takes the best of them. Never start a card whose dependency is unmet, however high its raw score.

Re-evaluate on every move — and score AS you groom

Two things keep ranks honest:

  1. Ranks recompute on every render. WSJF is a pure function of the data, so re-running the renderer after any change re-orders every lane automatically — a card moved between lanes lands at its correct per-lane rank with no manual renumbering. This is why the turn-end render hook is load-bearing: a lane move without a re-render leaves the shown order stale. Render after every status move.
  2. But the score INPUTS are not automatic — revisit them when the card materially changes. A lane move often changes what the card is worth or costs: promotion sharpens effort; a measurement that lands changes value; a dependency clearing raises other cards' unblock. When you move or materially edit a card, re-check its rank: inputs in the same edit, exactly as you re-check its status and links.

Ranking is a core part of grooming, not a separate chore. Every groom pass — the inbox sweep, an overnight reconcile, a disposition — sets or refreshes the card's rank: inputs (at minimum value and effort; foundational for platform pieces) alongside its verdict and links. A groomed board is not just correctly-laned and de-duped — it is scored, so the drive-loop can pick from it. An un-scored card after grooming is an unfinished groom; the ⚠ default-scored marker is the tripwire for cards the sweep skipped.

Drive from the board — motion, not permission-seeking

Each card carries an approval state (unreviewed / implied / explicit / blocked) so the agent can plough independent work without waiting, while never ploughing into things that need a human call. The default posture is motion, not permission-seeking: a groomed, ranked board is a work queue — work it. The change classification (tier) is the throttle.

The autonomy ladder (by tier):

  • Lower-tier work (hotfix + standard feature cycles) → DRIVE autonomously, no pause for a go. Run the card's parsimony + cost/benefit gate FIRST (below). If the verdict is BUILD or SIMPLIFY, take it all the way — build → the tier's reviews → verify → ship — without stopping to ask. Approval is implied by the tier plus a passing gate; do not re-request it.
  • Delicate / invariant-critical / cost-AND-safety work → PAUSE for approval before build and again before deploy. These are the changes where one missed path loses money or safety.
  • Investigations (measure-first cards) → DRIVE autonomously too. Run the measurement (a cheap, read-only probe over data that already exists). Then branch on the OUTCOME: if it does NOT open a build lane (refuted, or the fix needs a human call / external input) → record the finding and drop the card into waiting_user with a crisp user-verb next (or close it if the mechanism was refuted). If it DOES open a build lane → plan and build ONLY if it passes the FULL gate below — not just the tier. Tier is the first gate; value, prior-art, parsimony and cost/benefit all still apply.

The gate that earns the autonomy — FOUR steps IN ORDER, run BEFORE building, every card. Do not skip a step because the card "looks obvious"; a later step's verdict is only trustworthy if the earlier steps passed. Record each step's finding on the card.

  1. Validity — GROUND TRUTH first (still needed AND not already done). Read the authoritative source (the code at the named location, the test suite, the live system, the history) and confirm the work is still real and not already shipped — the board is a claim, not proof, and can be stale in either direction (see "Verify-before-work" below). A card that is already-done / moot retires here before any parsimony debate. 1b. Config-first — can a SETTING fix it instead of code? Before any plan or build, check whether a configuration change solves it: a live runtime knob, a settings/options field, a per-entity config value, a third-party integration setting, or a documented operator action. Read the knobs' live values — don't recall them. If a setting fixes it, do or propose that and record on the card why code is unnecessary. (Field evidence: in one session three planned code changes turned out to be a knob turn, a knob turn, and a non-problem refuted by data.)
  2. Prior-art / reuse (REUSE-or-BUILD, cite the location). Before proposing to BUILD any new mechanism, scan for existing prior art and record REUSE (with the existing symbol's location) or BUILD (why nothing equivalent exists). The producer you are about to "build" often already exists.
  3. Parsimony — is the problem sharp and real (one falsifiable sentence)? Does the simplest version capture most of the benefit? Verdict BUILD / SIMPLIFY / PARK / DROP on the card.
  4. Cost/benefit — does the marginal benefit pay for the ingredient risk + review cost? If a low-tier change drags in a categorically risky ingredient (shared-primitive writes, cross-component state, a rare-fire code path), that is a signal to SIMPLIFY or to treat it as delicate — not to barrel ahead because "it's only a small change."

Verify-before-work — NO card is worked until it is proven not-already-done. This sits ABOVE the rest of the gate: read the card → verify against ground truth → THEN gate → then build. A card is a claim about the world, written at some past moment; the world changes without touching the board (a sibling cycle fixes the bug, a config change moots it, a device comes back, a later ship subsumes it). Treat every card's state assertion as unverified until checked this session, with an independent read of the authoritative source — not the card's own summary.

Card kindThe check that settles it
Code defect / missing behaviorread the current source at the named location — is the fix already on the main branch?
Shipped-feature follow-upthe history / release notes / validation record for that surface
Live-system symptomread the live state, DB row, or metrics — is it still happening?
Test / suite defectRUN the suite (or file) now; never trust a recorded pass/fail count
Config-only itemread the live config — it may already be set
Doc / board itemopen the file — the section may already exist

Both directions are failures. A card that says "open" but is done wastes a rebuild. A card that says "done / clean / fixed" but is not is worse — it silently drops out of every future sweep (observed: a card recorded "collection now clean"; one collect-only run the next morning returned two errors). Verification means confirm the card is true, in whichever direction.

Verdicts (recorded on the card with the command/observation that produced them): ALREADY-DONE · PARTIALLY-DONE (narrow to the residual, re-score effort) · MOOT (premise gone) · STILL-REAL (proceed, carrying the fresh evidence) · CARD-WAS-WRONG (mark the false claim WRONG with what refuted it — often co-occurs with STILL-REAL).

Retire before moving on. A verdict that resolves a card is cashed the SAME turn: write it, set the terminal status (done for ALREADY-DONE / MOOT / refuted), bump updated, re-render, and only then pick the next card. A resolved-but-still-open card is worse than never checking — the next session re-verifies settled work.

Board-wide, not just the card you're about to pick. Every open lane gets verified, and parked cards get their revival triggers checked the same way. Work highest-ranked first so the drive loop is never blocked on a complete sweep, and date each verdict so a later session can tell fresh evidence from stale assertions. Never trust an agent's or teammate's "still open / already fixed" summary — confirm the commit/code/state exists yourself. An approval does not bypass this: an approved card (board button or chat "go") still passes the validity check first; approval authorises the work, it does not exempt it from proving the work is still needed.

When the gate is AMBIGUOUS → escalate, don't guess. A clean BUILD/SIMPLIFY drives autonomously; a clean PARK/DROP parks with its revival trigger. But when the parsimony verdict is genuinely unclear, or the cost/benefit is a toss-up, do NOT silently pick and do NOT stall the whole queue: notify the operator (a real notification that reaches them) AND park the card as waiting_user with a crisp user-verb next (APPROVE / PICK A-or-B). Then move on to the next eligible card — one ambiguous card must not block the flow. The notification and the parked card are redundant on purpose: the notification prompts, the board holds the decision durably.

Still always pause — the gate does not override these: a review returns do-not-ship; the work grows beyond the card's scope (re-scope, don't silently widen); anything destructive / outward-facing / published; the operator flagged it delicate; hostile timing. These are few and specific, not a general licence to stop.

Keep going — the loop. When a card reaches done (or a clean park), do not stop and report for instructions — pick the next one. Rank per the section above, skip blocked / unmet-dependency / approval-pending cards, and drive the next eligible card through the same gate. Report at natural checkpoints — a ship, a batch cleared, an approval gate, a genuine question — not after every card. The board, not a chat prompt, is the source of "what's next."

Concurrency & builder isolation

Ranking answers what next; concurrency answers how many at once. A board worked strictly serially never empties, so treat parallelism as a first-class sequencing dimension. What safely parallelizes: disjoint surfaces (cards touching different files/subsystems), framing-disjoint reviews of the same diff, and read/scope work beside build work. What must NOT: anything in a dependency chain, two agents writing the same file, or work that depends on a diff still under review.

The hard requirement: every concurrent repo-writing dispatch runs in its own git worktree, and the orchestrator commits its own work before dispatching. The collision that bites is not only merge conflicts — a dispatched builder doing routine git hygiene (git reset --hard, a stash, a checkout -- .) in the shared checkout silently destroys the orchestrator's uncommitted edits and any other concurrent writer's work, with no recoverable trace for uncommitted tracked files. Two non-negotiable rules follow:

  1. Commit (or stash) your own work BEFORE dispatching any repo-writing agent. A committed change survives a reset --hard; an uncommitted one does not. The orchestrator's tree must be clean at dispatch time.
  2. Every repo-writing builder runs in its own worktree — even a single one, even a "quick" one. "Only one builder, so no collision" is the exact rationale that fails: the collision is builder-vs-orchestrator, not just builder-vs-builder.

The real bottleneck is orchestrator attention, not agent count: every concurrent agent returns a report that must be independently verified — never accept a builder's or reviewer's summary as fact. Fan out to the width you can actually verify, then stop.

Producer AND consumer — check both, always

If a rule set codifies only "who reads this value", that asymmetry becomes a blind spot: every reviewer looks downstream and nobody reads how the value is made. Observed failure: a household occupancy count doubled its own residents and flipped a whole-house mode, because a default-ON additive derivation silently overwrote a subtractive one while both of its dedup defenses had gone inert — their shared dependency (a recognition subsystem) had failed in a different, separately-investigated incident. Every audit asked who consumed the count. None asked how it was computed.

Both checks belong in any plan or investigation that touches a value:

  • Producer: How many derivations exist, and which one wins? What does each depend on — and is that dependency healthy right now? Is this a plumbing fix or an arithmetic fix ("the right inputs feed it" ≠ "it computes the right number")? Compare against external ground truth, never against another internal number that shares its assumptions.
  • Consumer + call site: Who reads it, on which path, trust-decision or display, and where is it wired in.

Corollary — acceptance criteria must discriminate. State what the observation looks like under the fix and under a plausible different failure. If they are identical, the criterion proves nothing: "the count now exceeds the identified total" was accepted as proof that a plumbing fix worked, when it was equally the signature of the double-count bug that had replaced it.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Auto Kanban AI skill do?

A capture-first kanban board for agent-driven work. Fights chat-to-plan context loss with one rule: every user push AND every agent mid-turn discovery becomes a card the SAME turn, before acting. Source of truth is a structured YAML data file (committed); markdown and HTML views are regenerated by a render script that shows a STALE banner when code or docs move without a board reconcile; the release script refuses to deploy without naming the cards being shipped and marks them shipped as part of the deploy flow; a hosted board's disposition buttons (done/deferred/declined + approve/investig...

Why use Auto Kanban on TypingMind?

Because you install it once and use it with any model. Auto Kanban is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Auto Kanban in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/ojiudezue/productmind-skills/tree/main/skills/auto-kanban. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Auto Kanban?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Auto Kanban?

As many as you like. As long as a model supports skills, you can use Auto Kanban with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Auto Kanban AI skill free?

It is published on GitHub by ojiudezue. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇