# Kanban

> Real-time shared kanban boards. Each project lives at `https://kanban.infopanel.org/p/<name>/<id>`, and anyone with that URL
> can view and edit it — there are no accounts. Projects have ordered columns (statuses), cards, and a flat list
> of Markdown documents. Edits made through the API appear live in everyone's browser.

**If you were given a project URL** like `https://kanban.infopanel.org/p/<name>/<id>`, fetch
`https://kanban.infopanel.org/api/p/<id>/llms.txt` instead of reading this file further. It contains that project's current
board, the ids you need, and ready-to-run commands.

### Project ids

- The **id** is the last segment of the URL: 22 letters and digits, e.g. `1pv7XjjQP9gM4BRBqypgrb`. It is
  **case-sensitive** — copy it exactly.
- It is a compact (base62) encoding of a UUID, and every endpoint also accepts the UUID form
  (`3c5f5d83-d805-4e41-bba5-7a69e0ea588b`). Both refer to the same project.
- The `<name>` segment is a readable slug of the title that changes when the project is renamed. It is
  ignored, so never use it to look a project up. `https://kanban.infopanel.org/p/<id>` also works.

## Concepts

- **Project**: title, description, ordered columns, cards, documents.
- **Column**: `id`, `name`. A card's status is simply the column it's in.
- **Card**: `id`, `title`, `description` (Markdown), `priority` (`none | low | medium | high`),
  `size` (`none | xs | s | m | l | xl`, `none` = not estimated yet), `createdAt`, `updatedAt` (ms since epoch).
- **Document**: `id`, `title`, `body` (Markdown).

## Creating a project

Pick a new random UUID (v4) and send an `init` op. Column names can be plain strings. The response
includes the project's `url`, which uses the short id.

```sh
ID=$(uuidgen | tr A-Z a-z)
curl -s -X POST https://kanban.infopanel.org/api/p/$ID/ops -H 'Content-Type: application/json' \
  -d '{"ops":[{"type":"init","title":"My project","description":"","columns":["Backlog","In progress","Done"]}]}'
```

Share that `url` with the human so they can watch the board.

## API

No authentication: the project URL is the credential. Send JSON with `Content-Type: application/json`.

| Method | Path | What it does |
| --- | --- | --- |
| GET | `https://kanban.infopanel.org/api/p/<id>` | Full project as JSON: columns in order, each with its cards in order, plus documents. |
| GET | `https://kanban.infopanel.org/api/p/<id>/llms.txt` | This project's instructions and a Markdown snapshot of the board. |
| GET | `https://kanban.infopanel.org/api/p/<id>/documents/<documentId>` | One document as raw Markdown, with its title and timestamps as front matter. |
| POST | `https://kanban.infopanel.org/api/p/<id>/ops` | Apply edits. Body: `{"ops": [op, ...]}` (max 100). Applied in order and shown live to anyone viewing the board. |
| POST | `https://kanban.infopanel.org/api/p/<id>/import` | Replace the **entire** project with an export file. Destructive — only if a human asks. |

`POST /ops` validates every op before applying any. On success it returns
`{"ok": true, "version": n, "url": "<project page>", "results": [{"type", "id", "changed"}]}`, where `id` is the id of the thing
the op touched (including ids generated for new cards, columns and documents). Errors return
`{"ok": false, "error": "..."}` with status 400 (bad op) or 404 (project not created yet).

### Ops

Fields marked optional may be left out.

**Cards** — `priority`: `none | low | medium | high`. `size`: `none | xs | s | m | l | xl` (relative effort; `none` = not estimated yet).
Descriptions are Markdown.

```json
{"type": "addCard", "column": "Backlog", "card": {"title": "Write tests", "description": "", "priority": "medium", "size": "s"}}
{"type": "updateCard", "id": "CARD_ID", "patch": {"title": "...", "description": "...", "priority": "high", "size": "m"}}
{"type": "moveCard", "id": "CARD_ID", "column": "In progress", "index": 0}
{"type": "deleteCard", "id": "CARD_ID"}
```

- `column` matches a column name (case-insensitive); you can pass `columnId` instead.
- `addCard`: `index` optional (default: bottom), `card.id` optional (generated), other card fields optional.
- `moveCard`: `index` is the card's final position in the target column (0 = top); omit it to move to the bottom.
- `updateCard`: `patch` may contain any subset of fields. Text fields are **replaced**, not appended —
  read the current value first if you want to add to it.

**Columns** (a card's status is the column it is in)

```json
{"type": "addColumn", "name": "Review", "index": 2}
{"type": "renameColumn", "id": "COLUMN_ID", "name": "QA"}
{"type": "moveColumn", "id": "COLUMN_ID", "index": 0}
{"type": "deleteColumn", "id": "COLUMN_ID"}
```

`deleteColumn` also deletes every card in that column.

**Documents** — a flat list of Markdown pages for plans, specs, notes and decisions.

```json
{"type": "addDocument", "document": {"title": "Release plan", "body": "# Release plan\n..."}}
{"type": "updateDocument", "id": "DOCUMENT_ID", "patch": {"title": "...", "body": "..."}}
{"type": "deleteDocument", "id": "DOCUMENT_ID"}
```

**Project**

```json
{"type": "updateProject", "title": "...", "description": "..."}
```

Limits: titles 200 chars, card descriptions 20,000 chars,
document bodies 100,000 chars, 50 columns, 5,000 cards,
500 documents. Longer text is truncated.

## Working agreement for agents

Use the board as the shared source of truth for your work. Humans may be watching and editing at the same time.

1. **Read before you write.** Fetch the project at the start of a session and again before editing a card or
   document, since people edit concurrently. Text fields are overwritten by updates, not merged.
2. **Claim work visibly.** Before you start a card, move it to the top of the in-progress column (the one
   meaning "doing now", e.g. "In progress"). Work on one card at a time unless asked otherwise.
3. **Log progress on the card.** Keep the original description and add to it, e.g. a `## Progress` section
   with a checklist, links, and what changed. Keep it short and factual.
4. **Finish cleanly.** When a card is done, add a one-line summary of the outcome and move it to the done
   column (e.g. "Done").
5. **Say when you're blocked.** Leave the card where it is, add a `**Blocked:**` line explaining what you
   need, and raise its priority if it's urgent.
6. **Capture new work.** If you discover follow-up tasks, add cards to the first (backlog) column with a
   priority and size instead of silently expanding scope.
7. **Use documents for longer material** — plans, specs, research, decision logs — and mention the document
   title in related cards.
8. **Be conservative with destructive ops.** Don't delete or rename columns, or delete cards and documents you
   didn't create, unless a human asked. Never call `/import` unless asked.
9. **Batch related edits** into one `POST /ops` request.
