Sync to your tracker

Plan, then --apply: scope, ticket, publish, board, sync and bootstrap mirror your planning files and Zurdo's run results onto your tracker.

Carol v0.1.22

Six commands project an initiative onto your tracker, which today is GitHub. You type each one yourself, with your own gh login. Together they mirror the PRD loop: scope and ticket before a PRD exists, publish and board once it's written, and sync after zurdo run.

What exists on GitHubMade byFrom
The label vocabularycarol bootstrapCarol's built-in list
A pinned scope issue, plus a Projects board named after the initiativecarol scopescope.md
One issue per ticket, under the scope issuecarol ticket (and carol scope)tickets/*.md
A milestone, an epic issue, and one task issue per PRD taskcarol publishThe PRD
The PRD's issues as cards on the board, with a Statuscarol boardThe PRD and zurdo report
Outcome comments, labels, closed tasks, and the epic's status tablecarol synczurdo report

Plan, then apply

Every command here computes one plan from a single snapshot of the repository, prints it, and stops:

$ carol sync docs/billing/prds/prd-01-invoices.md
sync: acme/shop (3 ops)
  add_issue_labels zurdo:failed [<!-- zurdo-github prd=docs/billing/prds/prd-01-invoices.md task=task-03 -->]
  add_comment [<!-- zurdo-github prd=docs/billing/prds/prd-01-invoices.md task=task-03 -->]
  set_issue_body [<!-- zurdo-github prd=docs/billing/prds/prd-01-invoices.md epic -->]

Add --apply to run the same plan, not a recomputed one: what you read is what gets written. After each write Carol reads the item back. If a field didn't stick, Carol stops with exit 5 and names the field. Add --format json to get the plan as one envelope ({"schema_version": 1, "command": …, "data": {"repo": …, "ops": […]}}) for scripts and agents. A plan with nothing to do is 0 ops, which exits 0.

carol plan and carol apply do the same for several files at once. Each file's mode comes from its path: scope.md is planned as scope, a file under tickets/ as ticket, and any other .md as publish. An op that two files both plan appears only once. carol apply asks apply N ops? [y/N] when run in a terminal, unless you pass --yes.

carol plan  docs/billing/scope.md docs/billing/prds/prd-02-refunds.md
carol apply docs/billing/scope.md docs/billing/prds/prd-02-refunds.md

Re-running is safe

Each item Carol creates carries a hidden marker naming the file, and the task, it came from. The marker is the item's identity, not its number or title, so a re-run finds the item and plans only what changed. Rename a task and its existing issue is renamed. Nothing is ever duplicated.

Warning

Don't copy an issue body that Carol wrote into another issue. Two issues with the same marker make Carol refuse the plan with exit 4, naming the marker. Delete or edit the copy by hand, then re-run.

The marker formats are listed in Labels & markers, and how Carol uses them is in Internals.

carol bootstrap

Creates the base labels. If the repository has no description and no topics, --about "<text>" also sets the description.

LabelMeaning
zurdo:scope, zurdo:research, zurdo:grillingScope and ticket issues
zurdo:epic, zurdo:taskA PRD's epic and its tasks
zurdo:pending-reviewThe task passed, but zurdo is waiting on a [manual] sign-off
zurdo:failedThe task failed in its last run
ready-for-agentA task with no Depends-on, so an agent can start it now
needs-triage, needs-info, ready-for-human, wontfixStates for issues people file by hand. See Triage.

publish adds an effort:<tier> label for each effort tier the PRD uses. The engine loop adds its own carol:* and priority:* labels as it needs them. Every label is listed in Labels & markers.

carol scope

carol scope docs/billing/scope.md [--project "<board title>"] [--apply]

Creates or updates the scope issue and pins it the first time. The issue body carries the destination, notes, decisions, and open questions, plus the Phases table, which gains Epic and Milestone columns linking to what publish created. In the same plan, scope:

  • processes every ticket in tickets/ in file-name order, as carol ticket would;
  • projects every contract in contracts/ as one issue under the scope issue;
  • wires the graph: each published phase's epic becomes a sub-issue of the scope issue, each ticket's blocked-by becomes a blocked by edge, and a ticket that blocks a phase blocks that phase's epic. A phase with no epic yet is skipped with a defer: notice and wired on a later run;
  • sets up the initiative's Projects board, named after the scope title unless you pass --project. It links the board to the repository, sets its description to the destination's first paragraph and its README to the scope issue's body, and adds the scope and ticket issues as cards.

carol ticket

carol ticket docs/billing/tickets/tax-rules.md [--apply]

Creates or updates one ticket issue as a sub-issue of the scope issue. Edges between tickets need every ticket's issue number, so carol scope creates them. A resolved ticket gets its findings posted as a comment and is then closed. If the scope issue doesn't exist yet, Carol stops with exit 4 and tells you to run scope first.

carol publish

carol publish docs/billing/prds/prd-01-invoices.md [--scope <issue number>] [--apply]

Publishes a PRD as:

  • a milestone named after the PRD's title;
  • an epic issue (zurdo:epic) that links to the scope issue and has a table of tasks with their Status;
  • one task issue per ## Task: (zurdo:task, effort:<tier>). Each body holds the description and the acceptance criteria as a checklist, with every hint in backticks, so reviewers see exactly what zurdo will check. A task with no Depends-on also gets ready-for-agent.

Tasks become sub-issues of the epic, and each Depends-on becomes a blocked by edge, so GitHub shows the same dependency graph zurdo schedules. For a PRD under docs/<initiative>/prds/, Carol finds the scope issue itself, and you only need --scope for a PRD stored elsewhere. Re-publishing after you edit the PRD updates titles, bodies, and milestones in place, and keeps each task's Status cell in the epic. It also removes what the PRD no longer says: an effort:* label for an old tier, and a blocked by edge between two of the PRD's tasks that Depends-on no longer lists. A PRD whose issues already match plans nothing.

carol board

carol board docs/billing/prds/prd-01-invoices.md [--project "<board title>"] [--apply]

Adds the PRD's task issues to a Projects (v2) board and sets each card's Status from zurdo's run state. The default board is the initiative's (the scope.md title). Use --project to name another one. board adds the Pending Review and Failed Status options if the board doesn't have them. If no run has happened yet, every card is Todo.

This needs the project scope on your gh login. Without it, board exits 3 and tells you to run gh auth refresh -s project. The board is only a view: Carol writes it and never reads your plan back from it.

carol sync

carol sync docs/billing/prds/prd-01-invoices.md [--apply]

Reads zurdo report <prd> --format json, and for each task with a result:

zurdo task statusLabelCommentIssueEpic table / board
passedremoves zurdo:pending-review, zurdo:failedAttempts, last model, tokens in and out, estimated costClosedDone
passed-pending-reviewzurdo:pending-reviewSame as aboveStays open until you sign off in zurdo review, or under watch with carol:signedPending Review
failedzurdo:failedThe failing criteria: the report's failed_hintsStays openFailed
in_progress———In Progress

Each comment carries a marker naming the PRD, the task, and the run's started_at. Syncing the same run twice posts nothing new, and a new run posts once more. sync never removes ready-for-agent and never reopens a closed issue.

If the PRD has never been run, there's no report to read, so sync exits 6. Run carol board after sync to move the cards too.

zurdo run docs/billing/prds/prd-01-invoices.md
carol sync  docs/billing/prds/prd-01-invoices.md --apply
carol board docs/billing/prds/prd-01-invoices.md --apply

To have Carol take these steps for you, as a GitHub App, see The engine loop.

Next: The engine loop