issues-fs.sgit.ai / lite / five minutes

Five minutes, nothing installed

Three tasks opened, one blocked and later unblocked, one closed — with the actual commands and the actual files. Every command below is mkdir, a heredoc, mv, find or git. Nothing was installed to run it, and nothing needs to be for you to follow it.

The corpus has the protocol and no walkthrough. This page is the walkthrough. It is written from the specification rather than transcribed from a live vault, so the file contents are illustrative while every command is real.

Minute 0 — the whole setup

mkdir -p issues/{open,blocked,done}

That is the install. There is no step two.

Minute 1 — OPEN three tasks

You are an agent that has just been handed a brief. It generates three pieces of work. Each becomes a file, numbered from your own counter.

cat > issues/open/001-extract-lite-spec.md <<'EOF'
---
created: 2026-08-22T09:12:00Z
source: briefs/00__BRIEF.md
priority: urgent
estimated_effort: medium
---

# Extract the lite specification into a standalone page

## What needs doing

The spec is §7 of email-fs-lite-v0.6.md, lines 625-747, in a different repo.
Reproduce it faithfully, drop the mail/{agent}/ prefix assumption, and state
the source licence (CC BY 4.0) because it crosses a boundary.

## How I'll approach it

1. Read §7 in full and check the extract against the source line by line
2. Generalise the layout to {your-workspace}/issues/
3. Add what a standalone page needs: an upgrade path, and a worked example

## Acceptance criteria

- Every operation in §7 appears
- The provenance and licence note is on the page itself
EOF

cat > issues/open/002-verify-pypi-table.md <<'EOF'
---
created: 2026-08-22T09:15:00Z
source: briefs/04__what-ships.md
priority: high
estimated_effort: small
---

# Verify every row of the package table against live PyPI

## What needs doing

Eight packages. For each: query pypi.org/pypi/<name>/json, and where it
exists download the wheel and count what is actually in it.

## How I'll approach it

Not sure yet whether the two suspected empty wheels are empty or just small.
Unzip both and list every file before writing a word about them.
EOF

cat > issues/open/003-document-dsl.md <<'EOF'
---
created: 2026-08-22T09:18:00Z
priority: normal
estimated_effort: large
---

# Write the first prose documentation of the .issues DSL

## What needs doing

11 source files, ~55 tests, 3 live examples, zero prose anywhere.

## How I'll approach it

**I don't know yet.** There is no specification to work from - the parser
tests and the three live files are the only spec that exists. Read all
three files and the test suite before deciding what shape the page takes.
EOF

Look at 002 and 003. Neither has a confident plan, and both say so — “Not sure yet whether…”, I don't know yet. That is the specification working as intended: “Be honest — if you don't know how to approach it yet, write that. Future you (or a different runtime) will read this.” A file that invents a plan it does not have costs the next session more than an empty one.

Minute 2 — BLOCK one

Task 002 hits something outside your control: the two suspect wheels look empty, but their PyPI summaries promise code, and whether to publish that finding is not your call. Two moves — a mv, and a blocked_on.

mv issues/open/002-verify-pypi-table.md issues/blocked/

# then edit the front-matter to add one field, and the body to say why:
#   blocked_on: awaiting decision on whether to publish the empty-wheel finding
---
created: 2026-08-22T09:15:00Z
source: briefs/04__what-ships.md
priority: high
estimated_effort: small
blocked_on: decision from the project lead - publish the empty-wheel finding, or report upstream first
---

# Verify every row of the package table against live PyPI

...

## Blocked 2026-08-22T10:40:00Z

Both wheels confirmed at 8 files with no functional code. Their PyPI summaries
describe a FastAPI server and a Python client respectively. Publishing that is a
statement about someone else's published artefact, so it needs a decision I do
not own. Everything else in the table is verified and ready.

The blocker is recorded twice on purpose: blocked_on is for a machine scanning front-matter, the body section is for whoever reads the file. Neither is redundant — the field cannot hold the reasoning and the prose cannot be queried.

Minute 3 — the team view, free

$ find . -path '*/issues/open/*.md'
./issues/open/001-extract-lite-spec.md
./issues/open/003-document-dsl.md

$ find . -path '*/issues/blocked/*.md'
./issues/blocked/002-verify-pypi-table.md

$ grep -h '^blocked_on:' issues/blocked/*.md
blocked_on: decision from the project lead - publish the empty-wheel finding, or report upstream first

Across a whole team of agents, the same two commands answer what is everybody doing and what is everybody stuck on. That is the team view, and it falls out of the layout.

Minute 4 — UNBLOCK, then CLOSE

The decision comes back: publish it, and open an upstream request alongside. Task 002 moves back to open/ with an appended note, and task 001 — which you finished while waiting — closes.

mv issues/blocked/002-verify-pypi-table.md issues/open/
# append to the body:
#
#   ## Unblocked 2026-08-22T14:05:00Z
#   Decision: publish, and open N3 upstream asking for the wheels to be
#   filled or yanked. Removing blocked_on.

mv issues/open/001-extract-lite-spec.md issues/done/
# append to the body:
#
#   ## Closed 2026-08-22T14:20:00Z
#   Published at /lite/. Checked line by line against email-fs-lite-v0.6.md
#   §7 (lines 625-747). Source licence stated on the page. Added the two
#   things a standalone page owes and the corpus lacks: the upgrade path
#   (there is no converter - said so) and this worked example.

When you remove blocked_on, remove it — do not set it to an empty string. The convention is that the field's presence means the task is waiting for something, and an empty value is a third state nobody defined.

Minute 5 — the commit

This is the step that makes the rest worth doing.

$ git add issues/ lite/
$ git commit -m "publish /lite/; verify the package table"
$ git show --stat --name-status HEAD

R100  issues/open/001-extract-lite-spec.md  → issues/done/001-extract-lite-spec.md
R096  issues/blocked/002-verify-pypi-table.md → issues/open/002-verify-pypi-table.md
A     issues/open/003-document-dsl.md
A     lite/index.html

Git reports the state changes as renames, with a similarity score, because that is exactly what they are. A reader of this commit can reconstruct what the agent understood and planned without reading the brief — which is the property the whole protocol exists to produce.

The whole thing, on one screen

mkdir -p issues/{open,blocked,done}       # setup, complete

cat > issues/open/001-slug.md            # OPEN     (front-matter + your plan)
mv issues/open/001-slug.md issues/blocked/    # BLOCK   (+ blocked_on:, + body note)
mv issues/blocked/001-slug.md issues/open/    # UNBLOCK (- blocked_on:, + body note)
mv issues/open/001-slug.md issues/done/       # CLOSE   (+ body note: the outcome)

find . -path '*/issues/open/*.md'        # every open task, anywhere
find . -path '*/issues/blocked/*.md'     # everything stuck

For an agent

Copy the block above. Setup is one mkdir. One file per task in issues/open/, NNN-kebab-slug.md, front-matter with created and priority at minimum. State changes are mv and nothing else, and each one appends a dated section to the body saying what happened — never rewrite what is already there. Add blocked_on: when you move a file into blocked/ and delete the field when you move it out. Commit issue changes together with the work that caused them, so the commit carries the reasoning. If you do not know how to approach a task, write that in the body instead of inventing a plan.