piyaz
Using Piyaz

Cookbook: ship a feature end to end

One narrative that takes a small feature from a rough idea to a merged PR using Piyaz, brainstorm through composer.

Cookbook: ship a feature end to end

This page follows one feature from a sentence in your head to a merged pull request, using Piyaz the whole way. You already have a project under way; this is about adding a feature to it. The feature is small and concrete: add CSV export to the reports page. Users can already view a report in the browser; they want a download button that writes the same rows to a CSV file.

You work in plain language. You talk to your agent; the agent calls the Piyaz tools. The story (the project, the feature, the task titles, the file paths) is illustrative, but the flow is real. The existing project's identifier is DEMO, so task refs look like DEMO-1.

1. Open the project and describe the feature

You already run a DEMO project ("Reports") in Piyaz. The base reports view shipped a while ago, so the project is active and its graph is populated. Now you want to add CSV export.

You open a session, type /piyaz, and describe the feature in a sentence.

/piyaz add CSV export to the reports page, a download button that exports the same rows the user sees

Because the project already exists and is active, Piyaz does not brainstorm a new one. It reads the current graph first, the categories already in use, the tag vocabulary, and the tasks that already shipped, so the new work reuses the project's conventions and wires into what is there. It asks one focused question per turn about the gaps (which report formats, who can export, where the button lives). You answer; it pushes back where a choice is weak and proposes a default where you have none.

2. Decompose the feature into a task cluster

When the feature is clear, Piyaz proposes a small cluster and shows it to you before writing anything: three tasks, the edges between them, and an edge into a task already in the graph.

DEMO-1  Add CSV serializer for report rows   backend   depends on: none
DEMO-2  Add the report export endpoint       api       depends on: DEMO-1
DEMO-3  Add the CSV download button          ui        depends on: DEMO-2
                                                        relates to: Render reports page

Each task it proposes carries a verb-plus-noun title, a short description, two to four binary acceptance criteria, one category, and the three tag dimensions. The depends_on edges carry a note that briefs whoever starts the task: the endpoint's edge note says to import the serializer rather than re-implement CSV escaping. The relates_to edge into the existing Render reports page task is shared context with no ordering constraint.

You approve the cluster and the agent writes it. A quick check confirms the shape:

what is ready, and what is the critical path?

DEMO-1 is the only ready task, because the other two depend on unfinished work, and all three sit on the critical path. For the granularity and edge rules behind this step, see Decompose into tasks.

3. Compose the first task

You hand the loop to composer.

/piyaz:composer

Composer bootstraps the session and asks once for a merge policy. You pick ask-each: composer will open and review each PR, then ask you before it merges, so you authorize every merge while the loop keeps moving. It picks the highest-value ready task on the critical path, here DEMO-1, gives a one-paragraph rationale, and runs it through a per-task workflow. Each phase is a fresh agent with its own context, and the phase agents own every status transition.

Research

The researcher reads the task, maps it to the codebase, checks library versions, and reads the project's conventions (test command, lint command, PR template). It sharpens the task in place, a tighter description and binary acceptance criteria, and returns a brief. It writes refinement fields only; it never touches status or the plan.

Its brief, in short: the serializer is a new file at src/reports/serialize.ts, it reuses the existing ReportRow type, the test command is bun test, and a PR template is present. Confidence is high.

Plan

The planner reads the brief and the planning context and writes the full implementation plan onto the task: goal, files to touch, build sequence, edge cases, verification commands. Writing the plan is what moves the task from draft to planned. It edits no code.

Implement

The implementer reads the plan, claims the task (planned to in_progress), branches, writes src/reports/serialize.ts, and runs bun test and bun run lint until green. It opens a PR using the repo's template with [DEMO-1] in the linked-task section, then marks the task in_review with the full Completion Protocol record: what it built, the decisions, the files, and each acceptance criterion checked against the work, plus the PR link.

in_review is the implementer's terminal write. No agent promotes its own work to done.

Review

A cheap watcher reports the PR's CI state to the workflow. The review agent then reads the review context and reasons across five lenses (security, performance, reliability, observability, codebase standards). It is read-only over Piyaz and returns one verdict, and it cannot approve while CI is red or pending.

Verdict: approve
DEMO-1 "Add CSV serializer for report rows"
PR #142 (CI green) | acceptance criteria 2/2 satisfied
Security: serializer takes typed rows, no raw input.
Reliability: escaping covers quotes, commas, newlines.

A request-changes verdict would send the findings back to the implementer through composer's fix loop, up to two rotations, before surfacing the result. On an approve like this one, composer runs the merge gate. Because you chose ask-each, it now asks.

4. Approve the merge, then propagate

Because the policy is ask-each, composer asks before it merges:

Merge DEMO-1? PR #142, verdict approve, CI green.

You read the PR on GitHub. The work is good, so you say yes. Composer merges it, and because the merge is what lands the work, it marks the task done for you. This is the one status transition the orchestrator makes, and only because your ask-each policy authorized it; the decision to merge stayed yours. See Human on the loop for why the gate sits with you.

Still in the same iteration, composer propagates: it reads the task's edges, finds the downstream dependents, and refreshes any edge note the merged work changed. With DEMO-1 done, DEMO-2 has all its dependencies satisfied and becomes ready.

5. Loop until the graph is done

Composer continues without pausing. It picks DEMO-2, the export endpoint, now ready. Same pipeline: the researcher finds the route conventions, the planner writes the plan, the implementer wires the endpoint to call the serializer (the edge note told it to import, not re-implement), CI goes green, and the reviewer checks auth on the new path. Composer asks, you approve the merge, it marks the task done, and propagation unblocks DEMO-3.

DEMO-3 adds the download button and the click handler that hits the endpoint. After composer merges it on your yes and marks it done, nothing is left ready or plannable. That is composer's backlog-drained stop condition, so the loop exits. The feature is shipped: three PRs, three reviewed merges, one honest dependency graph that recorded every decision along the way.

What carried the work

  • The task graph kept the order honest. DEMO-2 could not start until DEMO-1 shipped, and the edge note told its implementer to reuse the serializer.
  • The execution records and decisions meant each phase started from ground truth instead of guessing. The endpoint's implementer read why the serializer is a pure function before writing a line.
  • The human gate stayed yours. Agents researched, planned, implemented, and reviewed; composer merged only the PRs you approved, and marked each done only after your yes.

For the deep version of this pipeline, including failure handling, oversize detection, and the per-phase tool restrictions, read The composer pipeline. For parallel work across independent ready tasks, see Parallel dispatch.

On this page