Skip to content

feat(tasks): Tasks screen becomes a Specs-style list with Play - #176

Merged
kaanozhan merged 15 commits into
kaanozhan:mainfrom
BerkayYilmaz11:feat/tasks-list-view
Oct 15, 2026
Merged

kaanozhan merged 15 commits into
kaanozhan:mainfrom
BerkayYilmaz11:feat/tasks-list-view

Conversation

@BerkayYilmaz11

@BerkayYilmaz11 BerkayYilmaz11 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

What this adds

The Tasks screen stops being a three-column Kanban and takes the Specs screen's shape: All / Active / Done segments with counts, tiles in the Specs grid, and In progress above Pending. A pending task gets a Play button, and a task's drawer gets status actions. Nothing on the screen is draggable any more.

Before After
Layout Pending / In Progress / Completed columns Specs-style grid; In progress, Pending and Completed sections
Changing status Drag a card Play, drawer actions (Mark complete, Back to pending, Reopen), or the agent closing the task
Starting a task Only from Home or a task tab Play on any pending tile, same run flow
Spec tasks Mixed in, draggable Hidden by default; "Include spec tasks" lists them read-only, marked SPEC
Narrowing Active — In progress / Pending chips, as on Specs
New Task form Title, description, priority, category Title, request (saved verbatim as userRequest), priority, category

Why

  • Dragging broke specs. Spec tasks (source: spec:<slug>:T##) sat on the same board with nothing to set them apart. A spec's phase is derived from its tasks, so dropping a spec's last open card in Completed marked the spec done with no implement run. Dragging one back out reopened a done spec. In this repo, 530 of 639 tasks are spec tasks.
  • A drop rewrote the whole file. A drop sent REORDER_TASKS with the status of every card in every column, hidden ones included.
  • Two screens, two models. Specs gives each item one primary action. Tasks had no action at all, although the tour promises "the play button on a task".
  • Two task formats. Agent-written tasks follow the tasks.json schema, but the New Task form wrote only a title and a description. Play's prompt carried only the title and description, so the agent never learned what "done" meant. 13 of this repo's 55 open hand-made tasks have no acceptance criteria.

Design decisions worth reviewing

  • A grid, not a fixed-up Kanban. Keeping the board and blocking drags on spec tasks would leave a screen that still has no action. The Specs shell gives one model across both screens, and the screen reuses its classes (toolbar, segments, chips, .specs-card, the older-done ghost tile).
  • Spec tasks are hidden by default and read-only when shown. Ticking "Include spec tasks" lists them in their status sections with your own tasks.
    • Each one carries a SPEC chip and a <slug> · T## label.
    • They have no Play and no status actions. Their drawer shows "Open spec" and no Delete, because a deleted spec task is re-imported on the next sync.
    • Built, then replaced: the first version revealed them in a separate section at the bottom, grouped per spec, behind a "Spec tasks n" chip. In use, it read as a second list hung under the main one, so it was dropped. Plan decision D4 is marked as overturned.
    • Also considered and rejected: one summary tile per spec in Completed. It changed the screen's structure more than the problem needed.
  • The format is completed at Play, not at creation. New Task stays an instant form and saves the request verbatim. When Play starts a task missing description or acceptanceCriteria, the prompt first asks the agent to write them into tasks.json, show the criteria and wait for confirmation.
    • The rejected alternative: hand the new task to an agent at creation, as New Spec does. That writes criteria before the relevant code is in view.
    • Every prompt now carries the acceptance criteria.
  • One prompt for every Play. The Tasks screen, Home's Active Tasks widget and the task tab's Start Working all go through tasksPanel.openRunFlow. The builder moved into the pure src/renderer/tasks/runPrompt.js, so all three get the same prompt. The rejected alternative, a Tasks-only prompt, would mean two prompt paths that drift.
  • Order writes send ids only. Sort's Permanent Save sends REORDER_TASKS { order: [{ id }] }. reorderTasks already keeps a task's status when an entry has none, so a sort can never move a task between statuses. Spec tasks keep their slots in the file, so a spec's T01…Tn order survives.
  • The status chips copy the Specs phase chips. They show only while Active is picked, one at a time; a second click clears the pick and any scope pick resets it. The segment counts do not move with the pick.
  • Two pure modules. src/renderer/tasks/listModel.js decides what the grid lists and src/renderer/tasks/runPrompt.js builds the prompt, mirroring specs/filterModel.js. tasksPanel.js requires electron, so the prompt builder could not be tested where it was.

Before merging — things for the maintainer

  1. Play changes for every surface, not just this screen. A hand-made task without a description or acceptance criteria now opens with the format step and a confirmation pause, from Home and the task tab too. That is deliberate (one run flow), but it changes what existing users see the first time they press Play on such a task. Spec tasks are exempt: their body lives in tasks.md.
  2. The New Task form loses its Description field. It records userRequest instead, and description stays empty until Play fills it. The retired side panel's own task modal still has Description; it is out of scope here.
  3. One main-process change: tasksManager.addTask now keeps a non-blank userRequest. Before, it dropped the field.
  4. The Specs screen's own task-row buttons still move spec tasks, and with them the spec's phase. That screen is out of scope here and unchanged. This PR closes the drag path on Tasks only.
  5. .frame/tasks.json carries this spec's 10 imported tasks, and .frame/STRUCTURE.json is regenerated. If main has moved in either file, expect a conflict there; keeping both sides is correct.
  6. The public capabilities page text changed: entry 04.01 in docs/capabilities/index.html, plus its diagram label "kanban state" became "task statuses".

Testing

  • npm test: 1309 pass, 0 fail (1292 on main).
    • New: test/tasksListModel.test.js covers each scope's sections, spec tasks hidden and included, the done window, filter, sort and status chips. It also sweeps every scope and status chip to check that each count equals what that control lists.
    • New: test/taskRunPrompt.test.js checks readiness and the spec-task exemption, and the format step's presence and order. It pins a ready task's prompt against a verbatim copy of the old builder: the old prompt plus the criteria line.
    • Extended: test/tasksManager.test.js covers addTask with and without userRequest. It also checks that reorderTasks with id-only entries leaves status, updatedAt and completedAt untouched.
  • npm run build passes.
  • Not covered by tests: the screen's DOM (tasksDashboard.js, markup, CSS), because the repo has no DOM harness. I checked it by loading the real index.html markup, CSS and module into a scratch Electron window with fixture tasks. I clicked through the scope segments, the status chips and the "Include spec tasks" checkbox, checked counts, Play placement and the drawer actions, and checked the IPC messages the screen sends.
  • Not exercised end to end: Play → run modal → agent dispatch in a running app. That path is the existing openRunFlow, unchanged apart from the prompt text.

BerkayYilmaz11 and others added 15 commits October 15, 2026 15:17
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
buildListModel splits tasks into scope sections, spec groups (revealed on
demand), the done window and segment counts, the way specs/filterModel.js
does for the Specs grid. Not wired yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The prompt builder moves to the pure tasks/runPrompt.js. A task missing
its description or acceptance criteria now opens with a step that has the
agent write them and confirm the criteria before starting; a ready task's
prompt is the old one plus its criteria. Every Play surface shares it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A non-blank userRequest is saved exactly as typed. Tests also pin that
reorderTasks with id-only entries leaves every status untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Kanban columns and drag-and-drop are gone. The screen takes the Specs
shell: All / Active / Done segments with counts, In progress / Pending /
Completed sections of tiles from the list model, and the older-done ghost
tile. Filter and Sort move to the toolbar; Permanent Save sends ids only,
so a sort can never change a status, and spec tasks keep their slots.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Play opens the shared run flow; the task turns in progress only after the
dispatch succeeds. A non-spec task's drawer offers Play / Mark complete /
Back to pending / Reopen by status. Spec tasks get none of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A "Spec tasks n" chip reveals them in their own section, grouped by spec
with an Open spec link. Their tiles and drawer are read-only: no Play, no
status action, no Delete. The reveal resets with the project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The form's Description becomes Request, saved verbatim as userRequest;
Play has the agent write the description and acceptance criteria. Tiles
show the request until a description exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The texts that described the Kanban now describe the grid, Play on a
pending task, and spec tasks hidden until revealed. Spec closed with its
digest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec tasks join the status sections behind an "Include spec tasks"
checkbox (D4 overturned), and Active gets In progress / Pending chips
(D18).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Spec tasks chip and its section at the bottom give way to an
"Include spec tasks" checkbox; included spec tasks sit in In progress,
Pending and Completed with the others, labelled <slug> · T##, still
without Play. Overturns D4 of the tasks-list-view plan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While Active is picked, two chips after the scope segments narrow the
list to one section, the Specs phase-chip pattern: one at a time, a
second click clears it, any scope pick resets it. Spec phase back to
done; digest covers T09 and T10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A long spec slug squeezed the tile foot: the date wrapped and the T
number was cut. The slug now truncates on its own, the number and the
date keep their width, and the badge row opens with a SPEC chip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Outside a Frame terminal (or project) the session report hook exits
without reading stdin, so the test's write of the payload races the
child's exit; when sh wins, execFileSync throws EPIPE. It failed this
way on CI's Ubuntu runner. The two no-op runs now go through spawnSync
and assert exit 0 and nothing written, treating EPIPE as expected.
Forcing the race with a 1 MB payload fails the old tests and passes
these.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kaanozhan
kaanozhan merged commit ba38bb0 into kaanozhan:main Oct 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants