100 Commits
Author SHA1 Message Date
istosandClaude Opus 5 2a4652a15b tasks: card 63 — a phase in flight is work happening
From a board showing 11 of 14 merged with member 31 in review/ and its
CI still running: the phase was advancing and every surface keyed to a
running agent said the board was idle. The tab title went back to the
plain project name, the live chip fell through to "you, working", and
the member the phase was waiting on wore "waiting on you" — which is
the opposite of true, since the phase merges it by itself on green.

The reading already exists client-side (phasesInFlight()), and the
snapshot already carries running/halted/stopped plus per-member states.
Nothing is missing but the question being asked, in three places that
answer it with runningAgents() instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 11:57:18 +02:00
istosandClaude Opus 5 869b7018b4 tasks: card 62 — running a halted phase again resumes it
Found on a board that was hosted by a shell that got killed: the phase
halted at the member whose agent went down with it, and no number of
presses of run phase could get past that member. What cleared it was
launching the member's work agent by hand and only then running the
phase, which is a two-step the board never mentions.

The runner already intends the opposite — _this_run() scopes the log so
that a new run may relaunch a member whose run died, and says so — but
_member_state() reads any existing branch as evidence the phase already
dealt with the card, and a run that died always leaves one. So the
intent is written down and unreachable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 08:05:15 +02:00
istosandClaude Opus 5 dff4a42a86 site: the redirect is a 307, and card 43's line numbers had moved
Two small corrections found while checking 0.4-alpha's deploy.

wrangler.jsonc claimed the slashless form redirects with a 301; measured
against the live site it is a 307. The code is the host's choice rather
than anything this repo sets, so the post-deploy check now says to
confirm that it redirects at all — the property the site depends on —
and records the observed code beside it rather than asserting one.

Card 43 already describes the two test_boards_sync failures a team-mode
checkout sees, and still describes them correctly; only its pointer into
the test file had drifted — reload() sits at 598 now, not 481.
config.py:53-69 is still exact.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 07:02:41 +02:00
istosandClaude Opus 5 080d2d767e 0.4-alpha: phases
Phases are the release, so AGENTS.md stops burying them. The six sections
that were `###`s inside "Task file format" — where they had split that
section's own prose in half, header table above and Assignee below —
become a `## Phases` section of their own, between "Pull requests" and
"Stages" because that is the order they are learned in. Nothing in them
changed: the diff is a move plus the section's opening paragraph.

Which gives the site three pages to cut rather than a tail nobody would
find at the bottom of "Task files": /concepts/phases/ (the model),
/concepts/running-a-phase/ (the branch, the beat, the halt, the ending)
and /concepts/phases-on-the-board/ (what the Board stops drawing, and the
Phases view that draws it instead). They sit after "PRs and review" in
the Concepts flow, which is the order AGENTS.md now reads in — the
manifest and the source cannot disagree about that without the build
saying so.

The landing page's third reason says it too, since "parallel work, zero
collisions" was only half of what the board now does, and the README's
opening paragraph gains the sentence it was missing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 06:55:39 +02:00
istos ed1d217c0d board: 61 → done (istos) 2026-08-03 06:40:14 +02:00
istos d069b742e6 board: 55, 54, 46 → done with phase 61 (istos) 2026-08-03 06:40:14 +02:00
Ronald AshriandGitHub 69447f92da Merge pull request #54 from 12vectors/phase/61-what-an-agent-is-told-before-it-starts
61 — Phase: what an agent is told before it starts
2026-08-03 06:39:59 +02:00
istos f3ed4c2b48 board: 61 PR opened (istos) 2026-08-02 18:37:56 +02:00
istos 446bf2cebc board: 46 PR review filed (istos) 2026-08-02 16:52:38 +02:00
istos 50332f5974 board: 54 PR review filed (istos) 2026-08-02 16:51:50 +02:00
istos 783d8c385d board: 61 → review (istos) 2026-08-02 13:43:21 +02:00
istos 6a7534cea2 board: 61 phase log (istos) 2026-08-02 13:43:21 +02:00
istos 21ec786674 board: 61 phase log (istos) 2026-08-02 13:43:19 +02:00
istos e5dee0f868 phase: merge task/46-a-board-with-no-test-command-says-so into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 13:43:17 +02:00
istos eb186cc1ef phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 13:43:15 +02:00
istos cd0000194f board: 46 PR opened (istos) 2026-08-02 13:43:09 +02:00
istos 2f76313d90 board: 46 → review (istos) 2026-08-02 13:43:01 +02:00
istos 5a15a822ec board: 46 Work report filed (istos) 2026-08-02 13:43:01 +02:00
istos 64f3e2b3bd A board whose agents cannot run anything says so
BOARD_AGENT_COMMANDS is the one setting a headless agent cannot work
around, and since the install stopped asking for it a project the
detector does not recognise starts with it empty — correctly, but
silently, until a run ended with an agent explaining it could not verify
its work.

Say it twice, in the two places it is learnable: a quiet `no agent
commands` chip in the header (`--idle`, like the drive's "no driver",
never `--alarm` — nothing is failing, something is unconfigured), and a
note appended to the ticker line of the launches that would have run
those commands, work and act-pr. Neither blocks anything: an agent that
only edits files is still useful.

What counts as empty is answered once, by `config.agent_commands()`,
which splits exactly as the adapters' own `split_commands()` does — so
whitespace and a lone comma are nothing configured on the board as well
as at the launch, and the page reads the server's boolean rather than
the raw setting.
2026-08-02 13:42:38 +02:00
istos 6a58880f7c phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 13:33:33 +02:00
istos d2243ac4f2 board: 61 phase log (istos) 2026-08-02 13:33:01 +02:00
istos f40ba67f44 board: 46 → in-progress (istos) 2026-08-02 13:33:01 +02:00
istos 80f1b10cd6 board: 61 phase log (istos) 2026-08-02 13:33:00 +02:00
istos 0768a866e5 phase: merge task/54-a-work-agent-must-refuse-a-phase-card into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 13:32:58 +02:00
istos 393ab32c9e phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 13:32:56 +02:00
istos b0fcb1373b board: 54 PR opened (istos) 2026-08-02 13:32:45 +02:00
istos 2cc0dd5c7e board: 54 → review (istos) 2026-08-02 13:32:37 +02:00
istos 341edf2132 board: 54 Work report filed (istos) 2026-08-02 13:32:37 +02:00
istosandClaude Opus 5 ccffbec831 A work agent refuses a phase card
`▸ run phase` guarded its own door and left the neighbour's open:
`/api/agent/start` accepted a phase card, cut `task/<stem>` and handed a
list of other cards to a work agent as a brief. It did that once, and the
agent implemented two cards at once in a worktree nobody was watching.

The refusal is a server rule, in `_validate` with the stage check — ahead
of the claim and well ahead of the worktree, so it costs nothing and
leaves nothing to clean up — and it names ▸ run phase rather than just
saying no. Which headless kinds a phase card may host is now decided kind
by kind where the guard lives: ▸ start work and ↻ act on PR refuse it
(both are work agents), while ◔ still true? and ◔ review PR are allowed —
the latter now told the phase's own branch, since its PR is from
`phase/<stem>` and `task/<stem>` was never cut. The guard is about
starting, so a card retyped under a running agent is left alone.

And the card says which state it is in: an `in-progress/` phase nobody has
started read exactly like one mid-run, the header chip being absent in
both cases. It now wears `not started` (or `held`) in the settled
register, with the line under it saying what ▸ run phase would do — never
the accent, the breathing mark or the caret, which mean work is happening.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 13:32:08 +02:00
istos 4a12da8d1b phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 13:07:39 +02:00
istos 8dc83d221b board: 55 PR review filed (istos) 2026-08-02 13:07:16 +02:00
istos 8cb89d8653 phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 12:52:29 +02:00
istos 95ec6df0df board: 61 phase log (istos) 2026-08-02 12:51:57 +02:00
istos f798c17f3a board: 54 → in-progress (istos) 2026-08-02 12:51:56 +02:00
istos 0412c78f39 board: 61 phase log (istos) 2026-08-02 12:51:56 +02:00
istos a5f05ea29d phase: merge task/55-a-headless-run-is-one-turn-and-must-say-so into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 12:51:54 +02:00
istos c6752efc3c phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 12:51:51 +02:00
istos 4d5cd19f7e board: 55 PR opened (istos) 2026-08-02 12:51:48 +02:00
istos eccaa415ed board: 55 → review (istos) 2026-08-02 12:51:40 +02:00
istos 331e5acc21 board: 55 Work report filed (istos) 2026-08-02 12:51:40 +02:00
istosandClaude Opus 5 f676c9fe2a prompts: say that a headless run is one turn
A work agent ended its turn to wait for a four-minute test suite it had backgrounded, and the run ended with it: 314 lines of passing work staged and never committed, an empty branch, a halted phase. Nothing in the prompts said the run was a single non-interactive turn, so waiting looked like a sensible strategy.

All four core prompts now open with the same block: this is one turn, the process exits with your reply, and nothing you meant to finish afterwards survives. It names the trap directly — do not background a command and end the turn to wait for it, do not promise to come back — and each template follows it with what its own run loses: work.md commits around long-running commands, act-pr.md commits and pushes, review-pr.md posts its verdict inside the turn, review.md writes its report there.

The block sits before the task body and carries no braces, so str.format still renders it and the NOT READY / ADDRESSED / PR REVIEW / RELEVANCE REVIEW marker lines keep their place after it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 12:39:07 +02:00
istos 24b7fdd9cf phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 12:37:52 +02:00
istos a445b660b5 board: 50 → archived (istos) 2026-08-02 12:37:29 +02:00
istos 46e4f143d2 board: 51 → archived (istos) 2026-08-02 12:37:26 +02:00
istos 343df6604f board: 52 → archived (istos) 2026-08-02 12:37:22 +02:00
istos d61b06f50c phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 12:37:18 +02:00
istos a44dfc2fb8 board: 56 → archived (istos) 2026-08-02 12:37:18 +02:00
istos 43ffa1c0ec board: 58 → archived (istos) 2026-08-02 12:37:14 +02:00
istos 88e5e6ea9a board: 59 → archived (istos) 2026-08-02 12:37:12 +02:00
istos 19e134e8f9 board: 53 → archived (istos) 2026-08-02 12:37:01 +02:00
istos 5a38f10f66 phase: merge origin/main into phase/61-what-an-agent-is-told-before-it-starts 2026-08-02 12:36:11 +02:00
istos 2691d8ff80 board: 61 phase log (istos) 2026-08-02 12:35:54 +02:00
istos 98d4157135 board: 55 → in-progress (istos) 2026-08-02 12:35:54 +02:00
istos dab8d97ecb board: 61 phase log (istos) 2026-08-02 12:35:52 +02:00
istos db418d47bf board: 61 → in-progress (istos) 2026-08-02 12:35:35 +02:00
istos 90c1ccd7ea board: 61 → to-do (istos) 2026-08-02 12:35:32 +02:00
istos d2b44ca133 board: 57 → archived (istos) 2026-08-02 12:35:14 +02:00
istos 11e84d94c0 board: 20 → archived (istos) 2026-08-02 12:34:34 +02:00
istos f4104d605d board: 19 → archived (istos) 2026-08-02 12:34:31 +02:00
istos b421291f15 tasks: phase 61 — what an agent is told before it starts
Runs 55 (the prompt says the run is one turn), then 54 (start_agent
refuses a phase card), then 46 (a board with no runnable commands says
so). No card depends on another; 55 is prompt-only and goes first, 54
and 46 both edit board.html so they run adjacent.

Also the first exercise of the Phases view: 56-59 landed after phase 53
finished, so hiding, the lane, the move refusal and the sweep have not
yet been watched on a live run.
2026-08-02 12:34:29 +02:00
istos c012987490 board: 18 → archived (istos) 2026-08-02 12:34:28 +02:00
istos a32ee33653 board: 17 → archived (istos) 2026-08-02 12:34:24 +02:00
istos d97fc4f34d board: 16 → archived (istos) 2026-08-02 12:34:21 +02:00
istos b20ef0344f board: 10 → archived (istos) 2026-08-02 12:34:18 +02:00
istos 0b975ce502 board: 04 → archived (istos) 2026-08-02 12:34:11 +02:00
istos e488a73832 board: 01 → archived (istos) 2026-08-02 12:34:02 +02:00
istos 8a69df87de board: 59 → done (istos) 2026-08-02 12:31:28 +02:00
Ronald AshriandGitHub 0745e68883 Merge pull request #50 from 12vectors/task/59-finishing-a-phase-finishes-its-cards
59 — Finishing a phase finishes its cards, and clears up after them
2026-08-02 12:31:20 +02:00
istos f601a078d5 board: 59 PR review filed (istos) 2026-08-02 12:21:04 +02:00
istos 7b6ccc8f86 board: 59 PR opened (istos) 2026-08-02 10:08:58 +02:00
istos f162a79822 board: 59 → review (istos) 2026-08-02 10:08:49 +02:00
istos a7e9f6aae2 board: 59 Work report filed (istos) 2026-08-02 10:08:49 +02:00
istosandClaude Opus 5 b690060be2 Finishing a phase finishes its cards, and clears up after them
Merge & clean up on a phase card now ends the phase: after the merge into
main has actually succeeded, every member the phase merged moves to done/
and its workspace is cleared the way completing an ordinary card clears
its own — worktree removed, local branch deleted, branch on the remote
deleted.

Only what the phase merged. A member is swept when its card settled into
review/ or done/ and its branch is contained in the phase branch (or
there was never a branch to bring) — the same pair the runner reads a
member as merged by. One that halted, was held or was walked back keeps
its card, its worktree and its branch: there is work in them.

Nothing uncommitted is thrown away: a member's worktree comes out without
--force, and a dirty one is reported in the ticker and kept with its
branch rather than forced.

One ending, told once. taskfiles.move_together moves the cards in a
single commit naming all of them (`board: 47, 52 → done with phase 53`,
so it publishes in team mode like any other board commit), and the moves
are marked quiet so the watcher does not also scroll five identical move
lines behind the one line the ending gets.

The other endings are untouched: "just move the card" and archiving the
phase card move no member, because neither puts anything in main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 10:08:00 +02:00
istos 064ed1f505 board: 59 → in-progress (istos) 2026-08-02 09:33:18 +02:00
istos f0b6cbf01c board: 58 → done (istos) 2026-08-02 09:33:07 +02:00
Ronald AshriandGitHub 97ea130063 Merge pull request #49 from 12vectors/task/58-a-phase-card-will-not-move-while-its-work-runs
58 — A phase card will not move while its work is running
2026-08-02 09:32:59 +02:00
istos d08723c72f board: 58 PR review filed (istos) 2026-08-02 09:29:49 +02:00
istos 69b1b4938a board: 58 PR opened (istos) 2026-08-02 09:23:55 +02:00
istos 292d1f93c9 board: 58 → review (istos) 2026-08-02 09:23:48 +02:00
istos a7243f0d20 board: 58 Work report filed (istos) 2026-08-02 09:23:48 +02:00
istosandClaude Opus 5 8fbfc1085d A phase card does not move while its work runs
Dragging a phase card between stages while one of its members has an
agent in it is a move nobody can mean: the card lands somewhere its
branch, its worktree and its live agent are not. The board refuses it,
and names the way through rather than the wall — which member is
working, and that ‖ hold stops the phase and the agent it has in flight
while leaving the branch, the merges and every worktree as they were.

- phases.assert_not_working() is the refusal: it reads the one file
  first, so an ordinary card never reaches the question, then resolves
  the phase's list and asks what is actually running.
- agents.working_on() answers that from the processes themselves, not
  from the registry's status alone — the reaper flips that a moment
  after a run ends, and a rule that only refuses must not hold a card
  hostage to a run that has already died. stop_phase() now reads the
  same helper.
- httpd asks it on /api/move, /api/archive (archiving is a move) and
  /api/task/complete, so a stale page cannot get past it.
- The toast wraps, is bounded to the viewport and stays up for as long
  as its text takes to read: a refusal you cannot finish reading is the
  wall this was written against.

What still moves: a phase between members, a halted phase, a held one,
a member card, and every ordinary card.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 09:23:23 +02:00
istos 208077073e board: 58 → in-progress (istos) 2026-08-02 09:07:04 +02:00
istos 00f2a91ccf board: 57 → done (istos) 2026-08-02 09:07:03 +02:00
Ronald AshriandGitHub 8b6ba0c67f Merge pull request #48 from 12vectors/task/57-the-phases-view-a-swimlane-each
57 — The Phases view: a swimlane each
2026-08-02 09:06:55 +02:00
istos 41d30097c3 board: 57 PR update filed (istos) 2026-08-02 09:06:24 +02:00
istosandClaude Opus 4.8 99fb248615 Phases view: a held run sorts above the phases nobody has started
laneRank() lumped a held (stopped) phase in with unstarted phases at
the same rank, so an actionable "stopped — held by …" lane could sort
below phases nobody has started. The snapshot already carries
snap.stopped, so give a held run its own rank just below running,
keeping it near the top where a person can resume it. Addresses the
Copilot review point on PR #48.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 09:06:10 +02:00
istos 6e5e212e9b board: 57 PR opened (istos) 2026-08-02 08:55:47 +02:00
istos 6d7894a901 board: 57 → review (istos) 2026-08-02 08:55:39 +02:00
istos 7024c45d46 board: 57 Work report filed (istos) 2026-08-02 08:55:39 +02:00
istosandClaude Opus 5 a3388ed2ea The Phases view: a swimlane each
Card 56 took a phase's members off the Board; this is where they went. A fourth view beside Board, Sessions and Focus, holding one lane per phase card — every phase there is, not only the running ones, because a phase whose cards are all merged and which is waiting on its own PR still owns them.

A lane is a head, five stage columns and the phase's log. The head carries the phase, its progress, the member in flight and its own controls — hold, the phase branch, the phase card — and nothing that ends a phase, which stays a board move on the phase card. Four columns are the board's stages; the fifth is 'Merged in', not done/, because a member merged into the phase branch is finished as far as the phase is concerned and is not in main yet. Which members the branch holds is the runner's last pass while a phase runs, and the phase log once there are no more passes, so a phase in review/ still draws the work where it landed. The cards are the cards: cardFor() builds them here exactly as it builds them for the Board, agent line, chips, position-in-the-run chip and hover actions intact. The phase log sits under the lane, the runner's decisions in the order it made them, read off the card's own '## Phase log' — the only thing that can tell "not reached yet" from "started and ended badly".

A halted lane says so at the top of itself, names the card it stopped on, and offers run again beneath the reason. That action left the Board's phase card for the same reason: clearing a halt should mean having read what caused it, so the card offers a way into the view instead, and hold, which needs nothing read. The crossing the other way is the switcher, which carries how many phases are running and an alarm mark while one has halted — on every view, alongside the toast and the ticker line that already fire.

Covered by tests/test_phases_view.py: collect() reads a throwaway tasks/ tree and the page's own lane rules run over that reading in node (ordering, placement, the last column, the log, the all-merged phase in review/), plus source-level wiring invariants for the DOM half. test_phase_watch, test_card_actions and test_scroll_kept updated where this moves what they pin. Full suite green: 939 tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 08:55:17 +02:00
istos a4fdb4f34d board: 57 → in-progress (istos) 2026-08-02 08:29:14 +02:00
istos 0868a942e2 board: 56 → done (istos) 2026-08-02 08:29:08 +02:00
Ronald AshriandGitHub 2f0e7f410b Merge pull request #47 from 12vectors/task/56-phase-members-leave-the-main-board
56 — Phase members leave the main board
2026-08-02 08:29:04 +02:00
istos b9400263fb board: 56 PR opened (istos) 2026-08-02 07:57:24 +02:00
istos ecef8ca7f2 board: 56 → review (istos) 2026-08-02 07:57:16 +02:00
istos 07fae2b801 board: 56 Work report filed (istos) 2026-08-02 07:57:16 +02:00
istos 3365919ca4 Phase members leave the Board view
The Board view stops drawing a phase's members: the phase card stands for them there, and the columns go back to counting what you can see. Nothing is deleted, moved or marked — a member keeps its stage, its file, its agent and its actions.

heldByPhase()/columnCards()/columnNote() in board.html: the count is the length of the list drawn, and '+2 in phases' beside it says where the rest went, only where members are actually hidden. Membership is the only thing that hides a card, so removing it is the un-hiding: an archived phase card and an edited '## Cards' list stop deriving it, and a phase in done/ holds nothing. A card wearing phase drift is never hidden. The phase card carries the summary it now owes: a '1 of 2 merged' chip opening its own sheet, the member in flight on its activity line, and a halt worn in --alarm. Only the Board hides; Sessions, Focus, the header's live chip and the tab title still see an agent working on a hidden member.

Covered by tests/test_phase_members_hidden.py — collect() reads a throwaway tasks/ tree and the page's own rules run over that reading in node, plus source-level wiring invariants. Full suite green.
2026-08-02 07:56:59 +02:00
istos dee9bbb1a4 board: 56 → in-progress (istos) 2026-08-02 07:40:22 +02:00
istos bea169ee0b board: 60 → archived (istos) 2026-08-02 07:40:13 +02:00
istos e8732e93f9 board: 59 → to-do (istos) 2026-08-02 07:39:52 +02:00