Skip to content

Latest commit

 

History

History
66 lines (42 loc) · 21.9 KB

run-one-ticket.md

File metadata and controls

66 lines (42 loc) · 21.9 KB

Run one ticket

The reader of this page is the agent of a ticket. The base rule covers each command of this page that uses origin/<base branch>.

Run one ticket

The agent of the ticket runs steps 1 to 11. Each step gives the state of the task after its command succeeds.

  1. Run tasker doctor. Then read the issue with gh issue view <number>, and compare the issue body with the prompt of the agent. If the body differs from the prompt, report each change to the orchestrator. The body can change while the agent works. Each tasker command of steps 1 to 11 follows the command rules.
  2. If tasker status --issue <issue> already lists a task for the ticket, for example a parked task that came back (see the defer rule), follow the comeback rule instead of this step. Run tasker start <issue>. The task goes to workspace_ready. Read the output of tasker start, also stderr. The note based on <key>'s branch confirms a stacked task. If the note and the prompt do not agree (the prompt names a parent and the note is missing, or the note is present and the prompt names no parent), stop. If tasker start refuses with blocking issue is still open, stop. No task exists. Then make the task worktree as the own-worktree rule says. If the make fails, stop. The make changes no task. Then run tasker plan <issue>. The task goes to awaiting_plan_review.
  3. Read the plan with tasker show-plan and tasker show-questions. Compare the plan with the Requirements and the Docs sections of the issue. Then apply the stop rule and do the quote check.
  4. If the plan needs changes, run tasker refine <issue> "<feedback>". Add the repo-files rule to the feedback text. Before the first refine, do the fact test and the issue check. The task goes to awaiting_plan_review again. Then do steps 3 and 4 again until the plan needs no changes. Put the answers to the plan questions in the feedback text. tasker plan takes no feedback.
  5. Run tasker approve. The task goes to approved. Run tasker execute. The task goes to executed. Run tasker verify. If the verify commands pass, the task goes to awaiting_work_review. If they fail, follow the verify-failure rule. Run tasker review. When the review has findings, the task goes to reviewed. When it has none, the task stays in awaiting_work_review. If the review has no findings, go to step 9.
  6. Read the findings with tasker show-review. Decide for each finding if it is real. Then do the quote check.
  7. Dismiss each finding that is not real, with a reason: tasker dismiss-review <issue> --finding N "<reason>". The task stays in reviewed while a finding is still open. If you dismiss all the findings, the task goes to awaiting_work_review, and you go to step 9.
  8. If real findings are still open, run one tasker refine <issue> "<feedback>". It acts on all the open findings. Add the repo-files rule to the feedback text. The task goes to awaiting_plan_review. After the refine, do steps 3 and 4 for the new plan. Then do steps 5 to 8 again, starting with tasker approve. The "Review findings" section limits the number of loops.
  9. Run each tasker command of this step as the plain-form rule says. The rule also covers the tasker commands that change a task in the other steps. Before each tasker accept of this step, also the one after tasker update-branch, do the diff read. Run tasker accept. The task goes to accepted. tasker accept refuses when the branch does not contain the tip of origin/main. In that case, run tasker update-branch. The task goes to executed. Then run tasker verify and tasker review again as in step 5. If tasker verify fails, follow the verify-failure rule. If that review has findings, go to step 6. Otherwise, run tasker accept again. Run tasker merge. The task goes to landed. Then do the CI wait. The task stays in landed. If the CI wait passes, run tasker finish. The task goes to finished, and the issue closes. If a run failed, step 12 of the CI wait runs tasker finish. If the CI wait stops, do not run tasker finish, and do not do steps 10 and 11.
  10. After tasker finish, make sure that origin has no task branch of the ticket. Do not rely on tasker finish for this. Do this step after each tasker finish. At the end of this step, whatever its result, remove the task worktree as the own-worktree rule says. Each "then do step 11" of this step comes after that remove. The remove changes no task, and the task keeps its state, for example finished. In each case of this step that says "delete nothing" or "delete nothing more", report to the orchestrator, and then do step 11. In such a case, unless the case says otherwise, the task branch on origin can still exist, and the task keeps its state. If the agent followed docs/dev/rebase-conflicts.md and did not do its steps 15 to 20 yet, it does those steps first. If a step of that page stops before step 21, do not do the rest of this step. The shared failure paragraph before step 15 of that page names what stays behind, with the difference that the step names, and the task keeps its state. Report to the orchestrator. Then do step 11. After steps 15 to 20, step 21 of that page sends the agent back to this step. The agent then does the rest of this step and does not do steps 15 to 20 again. Run each command of this step in the local clone of the orchestrator. Run tasker show <issue>. It prints the task branch on the branch: line and the base branch on the base branch: line. If tasker show fails, delete nothing. If tasker show does not print the line state: finished, delete nothing. For example, the task is in cleanup_failed. In each case that follows, the task stays in finished. Run git fetch origin. If the fetch fails, delete nothing. Find out if origin has the task branch, with a read-only command: git ls-remote --exit-code --heads origin refs/heads/<task branch>. Give the full ref, because a short name also matches a longer branch name that ends with it. For example, x matches feature/x. The command exits with 0 when origin has the task branch. It exits with 2 when origin does not have the task branch. It exits with 128 when git cannot reach origin, for example when the path of origin does not exist. If the exit code is 2, the step is complete, and the task stays in finished. If the exit code is not 0 and not 2, delete nothing. While origin has the task branch, git fetch origin updates origin/<task branch>. A fetch without --prune keeps origin/<task branch> after origin deleted the branch. For this reason, the read of the tip and the next check run only after the exit code 0 of git ls-remote. If the exit code is 0, read the tip of the task branch on origin: git rev-parse --verify origin/<task branch>. The command prints the full hash of 40 characters of the tip. This step calls it <commit>. If the command fails, delete nothing. Then read the tip of the base branch: git rev-parse --verify origin/<base branch>. This step calls the hash <base>. If the command fails, delete nothing. Make sure that the base branch contains <commit>: git merge-base --is-ancestor <commit> <base>. This is the ancestor check of docs/dev/rebase-conflicts.md, with <commit> as <tip>. That check gives the exit codes and the meaning of exit code 1. If the exit code is 1, do the patch check of that page, with <commit> as <tip> and the same <base>. Do only the patch check and the take check, and do not do step 17 itself or steps 18 to 21 of that page. If git cherry exits with 0 and a line starts with +, and the agent followed docs/dev/rebase-conflicts.md for this task, do the take check of that page. The agent is then the operator of that page and recorded <taken> at its step 11. Use <commit> as the pushed tip, the same <base> and the landed commit that tasker merge printed. Use only the two facts of the take check. Step 17 of that page already compared the local tip before step 20 deleted the local task branch. If the agent did not follow that page for this task, do not do the take check. If the patch check fails and the take check does not pass, delete nothing. For example, a fact does not hold, or a command of the take check fails. The task branch on origin stays. If the exit code is not 0 and not 1, delete nothing. The task branch on origin stays. If the exit code is 0, or the exit code is 1 and the patch check or the take check passes, delete the task branch on origin with a lease: git push --force-with-lease=refs/heads/<task branch>:<commit> origin --delete <task branch>. With the lease, git deletes the branch only when the branch on origin is still at <commit>. As a result, the delete cannot remove a commit that someone pushed to the task branch after the check. If the push succeeds, it exits with 0, and git prints - [deleted] <task branch>. The step is complete, and the task stays in finished. If the push fails, for any reason, delete nothing more. For example, if someone pushed a new commit to the task branch after the check, the push exits with 1, and git prints ! [rejected] (delete) -> <task branch> (stale info). The task branch on origin stays with the new commit. If someone deleted the branch after the check, the push exits with 1, and git prints error: unable to delete '<task branch>': remote ref does not exist. For another failure, the task branch on origin can still exist.
  11. After tasker finish, post a comment on the issue that starts with ## Decisions made during implementation. List the choices that the issue did not state, with the reasons. Name each detail that the issue did not give. A list item of the comment has no bold text at its start. The agent writes the comment in its final form before it posts it, because GitHub keeps the history of each edit.

The final report

At the end of its work on the ticket, the agent gives a final report to the orchestrator. The agent gives the final report as its final answer, not with SendMessage. The work of the agent on the ticket ends after step 11, or when the orchestrator tells the agent to end its work, for example in step 1 of the defer rule. A final answer that the agent gives before the end of its work is an interim report, not the final report. That final answer gives the state of the task, says if the agent stopped, and says that the agent waits. Examples are the final answer of the answer-wait rule and the end of the turn after a quota stop in "What the agent does" in "Quota". The report gives these items:

  • The result: the landed commit, the number of review loops, the files that landed and, for each doc that landed, the sections that changed. If the work of the agent ended before tasker finish, for example after the orchestrator told the agent to end its work, the result gives the state of the task and the reason for the end of the work.
  • Each finding that the agent dismissed, with its reason.
  • The edge cases that the agent left out (see "Review findings").
  • Each claim of the issue that was no longer true and each conflict (see the issue check). For a false claim, the bullet gives the current fact and the command that shows it. For a conflict, it gives the requirement, the conflicting rule or decision, the command or the doc that shows it, and the resolution: the change in the feedback text of the refine of step 4, the text of the plan that already resolves the conflict, or the answer of the user. If the task branch already held commits at the issue check, also the files that the agent read from the base commit and how. The bullet also gives each claim that the agent cannot test, because the issue names no ticket and no date for an output of the installed tasker.
  • Each task worktree or local task branch that stays, with its path. The own-worktree rule says when one stays.
  • The lessons.

The orchestrator sorts the lessons. A lesson that is a rule for the repo or for agents goes where the new-rule bullet of "The prompt of an agent" says.

The comeback rule

This rule covers a ticket that already has a task in flight when its agent starts, for example a parked task that came back (see the defer rule). The task already exists, so the agent does not run tasker start or tasker plan. If the issue has a comment that starts with ## Parked task (step 6 of the defer rule), the agent reads the last such comment. Then it runs tasker show <issue>. Then the agent does the remote setup. Then the agent makes the task worktree as the own-worktree rule says. The branch-exists case can apply. The make changes no task. If the task is in quota_blocked, interrupted or awaiting_quota_approval, the agent follows "What the agent does" in "Quota", and it does not do the rest of this rule. Otherwise, the agent runs git merge-base --is-ancestor origin/<base branch> tasker/<task branch>. If the exit code is 1, the base branch moved. In that case, if tasker show <issue> lists update-branch, the agent runs tasker update-branch. If tasker show <issue> does not list update-branch, the agent does not run it. The diff read before tasker accept finds the move later. If tasker update-branch reports a rebase conflict, the agent follows docs/dev/rebase-conflicts.md, as "Land the work" says. If a step of that page stops, a command fails, or the exit code is not 0 and not 1, the agent stops. Otherwise, the agent continues "Run one ticket" from the state that tasker show <issue> prints. After tasker update-branch, "Land the work" gives the next commands for the states that it names. For another state, for example failed, the agent follows the commands that tasker show <issue> prints.

The base rule

This rule covers each command of the orchestration pages that uses origin/<base branch>. A stacked task is a task that tasker start based on the branch of its parent (see the stacked-ticket rule).

Before each such command, the agent reads the base branch: line of tasker show <issue>. The agent does these steps:

  1. If the line has a plain name, use origin/<base branch> as the command says.
  2. If the line has the form refs/heads/<parent branch>, the task is stacked. Right before the command, run git fetch tasker. Then use tasker/<parent branch> in place of origin/<base branch>. If the step already ran git fetch tasker or git fetch --multiple tasker origin right before the command, it needs no second fetch.
  3. If a step uses tasker/<parent branch> in more than one command, read its hash one time with git rev-parse --verify, as the shared-clone rule says.

A tasker update-branch with no conflict moves a stacked task onto the base of the parent after the parent lands.

An agent of a stacked task meets a landed parent at tasker verify in executed. It also meets a landed parent at tasker refine in awaiting_plan_review, after tasker finish of the parent. The facts of the installed tasker say what happens in each case.

These steps use the base: the comeback rule, the diff read, the issue check, the broken-commit steps, the commit check, the same-patch rule, and steps 3 to 5 of docs/dev/rebase-conflicts.md when those rules do them.

Step 4 of docs/dev/rebase-conflicts.md does not stop for a stacked task when the diff read, the comeback rule or the commit check does the steps of that page. The manual fix and the procedure for a rebase conflict keep the stop.

The add-work rule

If the task is in awaiting_work_review and the agent must add work, the agent runs tasker review <issue> "<feedback>". The agent adds the repo-files rule to the feedback text. The task reaches awaiting_work_review after a review with no findings in step 5 or step 9, or after the agent dismisses all the findings in step 7. In this state, tasker refine refuses to run. The work can come from the orchestrator, for example. After tasker review <issue> "<feedback>", the task goes to refining, and tasker makes a new plan revision. Then the task goes to awaiting_plan_review. Then the agent does steps 3 and 4 for the new plan, and steps 5 to 8 again, starting with tasker approve.

The diff read

Each time before the agent runs tasker accept in step 9, the agent reads the full diff of the task branch against the base branch. The agent does this also after a review with no findings. In one milestone, this read found real duplication and false doc text on four tickets where the review found nothing. In the local clone of the orchestrator, the agent does the remote setup. The remote setup is steps 1 to 5 of docs/dev/rebase-conflicts.md. The clone gets the read-only tasker remote, and the agent reads the base branch. The fetch of step 5 fetches both remotes. It reads the tasker clone through the read-only tasker remote, and it changes nothing there. Then the agent does the update rule in the task worktree. The agent reads whole files of the task there. Then the agent runs git diff origin/<base branch>...tasker/<task branch>. The task branch is on the branch: line of tasker show <issue>. The agent reads the full diff. The agent also searches each test file of the diff for a helper name that is defined two times, for example in the test file and in test/helpers/. A clean review missed such copies on more than one ticket. Such a copy is a duplication. If the agent finds a duplication, a fact that the docs lost, or a doc sentence that is false, it adds the work with the add-work rule. "Review findings" limits the number of loops. Right before tasker accept, after the agent read the diff, the agent fetches again, as the base rule says: git fetch --multiple tasker origin for a stacked task, and git fetch origin for a plain base. Then it runs git merge-base --is-ancestor origin/<base branch> tasker/<task branch>. This command uses origin/<base branch> one time, so it needs no hash read. If the exit code is 0, the task branch contains the tip of the base branch, and the agent runs tasker accept. If the exit code is 1, the base branch moved, for example origin/main. The agent does not run tasker accept. It runs tasker update-branch and continues step 9 as it says after tasker update-branch. The last fetch and git merge-base are commands of the diff read. An exit code of git merge-base that is not 0 and not 1 is a failure. A failed step of the update rule is a failed command of the diff read. If a step or a command of the diff read fails or stops, the agent stops. Nothing changes in the repo or the worktrees of tasker. The report of the stop takes the place of the person who decides on that page.

The measure rule

This rule covers an issue that asks for a measure of the work, for example a test loop with a count of failures. The agent of the ticket takes the measure itself. It takes the measure in each diff read, after it reads the full diff and before the last fetch of the diff read. The agent takes the measure in the task worktree, after the update of the diff read. If the issue asks for a measure at a named point of the work, the agent takes that measure on the commit of that point. For example, a measure "after the fix of the test race" runs on the commit of that fix, before the later commits of the task. The agent checks out that commit in the task worktree and names its hash with the numbers. After the measure, the agent runs git switch <task branch> in the task worktree. A failed switch is a failed command of the diff read, so the diff read stops as it says. A measure with no named point runs as this rule says. The result of the measure is an answer, not a failure of the diff read. For example, a count of failures, or a test command that exits with a code that is not 0, is a result. The agent records the result and continues the diff read. A command of the measure that cannot start, for example because npm ci fails, is also a failed command of the diff read. The diff read then stops, as it says. The agent does not rely on the execute session for the numbers. No read-only tasker command prints the last message of that session. A direct read of a transcript of tasker follows the own-worktree rule. On #111, the agent measured the loops of the test again in its own worktree of the task branch. The agent gives the commands and the numbers of the last measure in the comment of step 11.