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>.
This rule applies to each tasker verify on the orchestration pages, in step 5 of Run one ticket, in step 9 and after tasker update-branch in "Land the work". If tasker verify fails, the task goes to failed. In failed, tasker show <issue> lists refine, update-branch, retry and abort. A fix of a failed tasker verify does not count as a loop of "Review findings". The limits of this rule count each refine and each retry after the last tasker verify that passed, for any cause. If the task is in failed after a command other than tasker verify or tasker retry, this rule does not apply. In that case, the agent follows the paragraph after this list, which starts "If a command fails". The agent reads the output of tasker verify and finds the cause of the failure. Then the agent does the first case of this list that applies:
- If the failure comes from the code and the agent already sent the refine of the next case, the agent stops.
- If the failure comes from the code, the agent runs one
tasker refine <issue> "<feedback>".tasker refineaccepts a task infailedonly when the task has a plan revision. The feedback gives the cause of the failure. It tells the plan to go through the commits of the task branch one at a time. It also tells the plan to fix each broken commit in that commit, not in a new commit on top. More than one commit can be broken, so the refine fixes all of them. The broken-commit steps give the git commands for this feedback. The agent adds the repo-files rule to the feedback text. The task goes toawaiting_plan_review. Then the agent does steps 3 and 4 for the new plan, and steps 5 to 8 again, starting withtasker approve. As the other choice, the agent does not refine. The agent stops for a manual fix. If the orchestrator then tells the agent to do the manual fix, the agent follows the broken-commit steps. For a failure from the code, the agent does not runtasker retry, because the same check fails again on the same code. The agent also does not runtasker retry --resume-execute. That flag resumes execute with no new feedback, so the plan does not get the cause of the failure. - If the agent already ran
tasker retry, the agent stops. If thetasker verifythattasker retryran failed, the task stays infailed. Iftasker retryitself failed, the task stays in the state thattasker show <issue>prints. - If the failure does not come from the code, the agent runs
tasker retry <issue>one time. For example, a test failed one time for a reason outside the code.tasker retryaccepts a task infailed. By default,tasker retryrunstasker verifyagain on the same code. If that verify passes, the agent runstasker show <issue>, and the task is in the state that it prints. Then the agent runs the command that comes aftertasker verifyin the place that ran it. In each place on the orchestration pages, that command istasker review.
If a command fails or the task is in another state, run tasker show <issue> and follow the commands that it prints.
To find the next command, use these:
tasker --helplists the commands.tasker <command> --helpshows the states where the command is valid.tasker show <issue>shows the state of the task and the next commands.
These steps give the git commands for a failure from the code in the verify-failure rule. A broken commit is an implementation commit that fails npm run check, or the tip of the task branch when it fails npm run check. The tip has no next commit, so it must pass, whatever its prefix. The cause commit of a broken commit is the commit that adds the cause of its failure. It is the broken commit itself, an earlier broken commit, or an earlier commit that the check skips, for example a test: commit that adds a test configuration. It is never under the last commit that passed the check, or under the base commit. The Commits section of docs/dev/rules.md defines an implementation commit and gives the rule. The fix of a broken commit goes into its cause commit, not into a new commit on top. The steps do not change the limits or the cases of the verify-failure rule.
The base commit is the commit under the first commit of the task branch. tasker update-branch moves the task branch onto a newer base, so the base commit changes. For this reason, each commit check of the agent finds the base commit again. The refine feedback gives the base commit of the last commit check, and the session steps use the base commit of the feedback. The one exception is the refine of step 4 of Run one ticket after a tasker update-branch: there the base commit comes from git merge-base directly, not from a commit check.
In the refine of the verify-failure rule, the agent first does the commit check on the local task branch, in the task worktree. If the commit check finds no broken commit, each implementation commit and the tip pass, so the failure does not come from the code. The agent does not send the refine. It follows the cases of the verify-failure rule for a failure that does not come from the code. Otherwise, the feedback names each broken commit of the check, by its hash and its subject. The commit check names each broken commit, but not its cause commit. A named feat:, fix: or refactor: commit is not the cause when its failure comes from an earlier commit that the check skips. For this reason, the feedback also names the commits that the check skipped under each broken commit, back to the last commit that passed the check or to the base commit. These commits and the earlier broken commits of the list are the other candidates for the cause commit. It gives the base commit of the check. If the agent runs tasker update-branch after it sends the refine and before tasker approve, the agent does not run the commit check again. The hashes and the base commit in the feedback are then out of date. The session finds the broken commits again with its own commit check, so the names in the feedback only describe the failure. In the refine of step 4, the agent gives the new base commit: the agent runs git fetch --multiple tasker origin, then git merge-base tasker/<task branch> origin/<base branch>. If a command fails, the agent stops. This refine of step 4 is part of the same fix, not a new refine of the verify-failure rule, so the limits of that rule do not change. Then the agent continues as usual. tasker verify runs after tasker approve and tasker execute, as the steps of "Run one ticket" say. If that tasker verify fails, the agent follows the verify-failure rule, which looks for broken commits again. If it passes, the agent continues as usual. The feedback tells the session (the execute session that tasker starts) to fix the cause commits with these steps:
- Do the session check. The result is the list of broken commits, oldest first. If the session check stops, stop and report, as the session check says.
- If the list is empty, the session ends. Each commit passes, whatever repaired it, for example an earlier fix or
tasker update-branch. - On the task branch, take the oldest commit on the list. In the first round, find its position. The position of a commit is the number that
git rev-list --count <base commit>..<commit>prints (1 for the first commit after the base commit). A later commit has a higher position. The hashes change after each autosquash, so the session compares positions, not hashes. If the command fails, stop and report. The task branch stays as it was. In later rounds, keep the position that step 5 found. Then read the failure of the oldest commit and find its cause commit, as the definition above says. Stage the fix and rungit commit --fixup=<cause commit>. This also applies when the cause commit is the tip or atest:commit. If the command fails, stop and report. The staged fix stays, and git makes no fixup commit. - At once, run
GIT_SEQUENCE_EDITOR=: git rebase --autosquash <base commit>on the task branch.GIT_SEQUENCE_EDITOR=:makes sure that the rebase does not wait for an editor. With git 2.47.3, the--autosquashflag works without-i, and the rebase does not depend on therebase.autoSquashconfiguration. The rebase squashes the fixup commit into the commit that it names. As a result, the fix is part of the history before the session looks at the next commit. If the rebase fails, for example with a conflict, rungit rebase --abort, then stop and report. The branch goes back to its state before the rebase, with the fixup commit on top. - Do step 1 again. A commit that is not on the new list needs no fix. If the new list is empty, go to step 2. Otherwise, find the position of the oldest commit on the new list with the command of step 3, and keep it for the next round. If the oldest commit on the new list is not later on the branch than the oldest commit of the list before, the session stops and reports. The fixes so far stay in their commits. Otherwise, do steps 2 to 5 again. The position test ends the session after at most as many rounds as the task branch has commits after the base commit.
If the session stops, the execute run fails. The agent then follows the verify-failure rule as it already says. For a task in failed after a command other than tasker verify or tasker retry, that rule sends the agent to the paragraph that starts "If a command fails".
After the refine, the agent continues as the verify-failure rule says. When the tasker verify after the fix passes, the agent does the commit check before tasker review, unless the agent ran tasker update-branch after the failed tasker verify. This check runs only because a tasker verify failed before the fix. When tasker verify passes and no failed tasker verify came before it, the agent runs no commit check. After tasker update-branch, the agent runs no commit check until tasker verify fails. tasker verify runs after tasker update-branch as step 9 and "Land the work" say. If the commit check fails, the agent stops and reports the list of broken commits. The agent does not run another refine, because the verify-failure rule permits one refine.
The pushed-branch rule covers a task whose task branch was pushed to origin at step 9 of docs/dev/rebase-conflicts.md. After that push, a fixup commit and an autosquash rebase change the task branch of tasker, and origin keeps the pushed commits. The fix of a broken commit under the tip still goes into its cause commit. On #201, the next tasker update-branch worked again only after the old task branch on origin was deleted with a lease. The agent does the rule after step 11 of that page. It does the rule before each later tasker update-branch of the task, until step 21 of that page ends. The tasker update-branch <issue> --take-remote of step 11 is not a command of the rule. The rule applies to each change of the pushed commits, whatever its cause.
The agent of the ticket does each step in the local clone of the orchestrator, on main. No step runs in the tasker clone or in a worktree of tasker. The git commands change no task, for example a task in awaiting_work_review, reviewed, awaiting_plan_review or failed. The agent does these steps:
- Run
git fetch --multiple tasker origin. If the fetch fails, stop. Nothing changes. - Run
git ls-remote --exit-code --heads origin refs/heads/<task branch>. Step 10 of "Run one ticket" gives its exit codes. If the exit code is 2,originhas no task branch. Go to step 7. If the exit code is 0, go on with step 3. If the exit code is another code, stop. Nothing changes. - Read
<commit>withgit rev-parse --verify origin/<task branch>. Read<current>withgit rev-parse --verify tasker/<task branch>. If a read fails, stop. Nothing changes. - Run
git merge-base --is-ancestor <commit> <current>. If the exit code is 0, the task branch of tasker contains the pushed commits. Go to step 7. If the exit code is 1, tasker changed the pushed commits. Go on with step 5. If the exit code is another code, stop. Nothing changes. - Make sure that
<commit>is the same hash as the<taken>of the last step 11 of rebase-conflicts.md. If that step recorded no<taken>, stop. If the two hashes differ, stop. Nothing changes. - Delete the task branch on
originwith a lease:git push --force-with-lease=refs/heads/<task branch>:<commit> origin --delete <task branch>. If the push fails, for any reason, stop. Step 10 of "Run one ticket" gives two examples: a stale lease, and a branch that is already gone. For another failure, the task branch onorigincan still exist. The agent holds no<deleted>. If the push succeeds, keep<commit>as<deleted>.<deleted>lives until step 21 of rebase-conflicts.md ends, or until the next push of step 9 of that page. That push ends the old<deleted>, and the agent holds no<deleted>until a later delete of this rule. - Run the
tasker update-branchthat the step that started the rule asked for, as the plain-form rule says. That step gives the state of the task after the command.
Right after step 6, origin has no task branch. While the agent holds <deleted>, the take check in step 17 of rebase-conflicts.md uses it. If nobody pushed the task branch again, step 21 of that page finds exit code 2 in step 10 of "Run one ticket", so that step is complete. If the agent holds no <deleted>, steps 15 to 21 of that page run as they are written.
The session check runs the rebase of the commit check directly on the task branch. The check commands only run the tests and change no commit. The last paragraph of the commit check gives the facts of this rebase during and after its run. At the end, HEAD is on the task branch. If the rebase stops for another reason, git rebase --abort puts the task branch back at its tip, with HEAD on the task branch.
If the session stops in the middle of the rebase, the worktree stays in the rebase. Step 2 covers this case when the session goes on.
The session does these steps in its worktree, on the task branch, with the base commit of the feedback:
- Do steps 5, 6 and 8 of the commit check: the
git rebase --execcommand, the notes andgit rebase --continue, and the tip check. Step 2 takes the place of step 7 of the commit check. If the rebase exits with 0, the result is the list of broken commits, oldest first. The list can be empty. Then no rebase is in progress, so step 2 does nothing, and step 3 does not stop. If the rebase stops for another reason, or another error occurs, for example the rebase does not start or a command of step 8 of the commit check cannot run, go on with step 2. - If a rebase is still in progress after step 1, run
git rebase --abort. A rebase is in progress when the folder$(git rev-parse --git-path rebase-merge)exists. If the abort fails, stop and report. The worktree stays in the rebase, and the task branch stays at its tip. - If step 1 ended with such a stop or error, stop and report. The task branch stays at its tip, with HEAD on the task branch.
The agent does the manual fix only when the orchestrator tells it to, after the stop for a manual fix in the verify-failure rule. The agent never changes the tasker clone (the clone of this repo that tasker keeps, see docs/dev/rebase-conflicts.md) or its worktrees by hand (see the own-worktree rule). The agent does these steps:
- Do the remote setup. Then do step 6 of docs/dev/rebase-conflicts.md. The agent works in the task worktree. Step 6 of that page uses it. The local-commit rule holds from step 2 of this list. If a step fails, stop.
- Do the commit check on the local
<task branch>to find the broken commits and the base commit. If the check finds no broken commit, stop and report this. If the check stops with an error, stop. In both cases, the worktree and the local task branch stay. - In the worktree, do the session steps of the broken-commit steps on the local
<task branch>, with the base commit of the last commit check. If the session steps stop, stop. The worktree and the local task branch stay. - Do the commit check on the local
<task branch>again. This check also covers step 8 of docs/dev/rebase-conflicts.md, because it checks the tip. If the check lists a broken commit, fix the cause commits of the listed commits one time with step 3, with the base commit of this check. Then do the commit check one more time. If that check still lists a broken commit, stop and report the list. If a check stops with an error, stop. In each of these cases, the worktree and the local task branch stay. Nothing reached tasker yet. - Do steps 9 to 21 of docs/dev/rebase-conflicts.md: the push to
origin,tasker update-branch <issue> --take-remote, the next commands, and the cleanup aftertasker finish.
The commit check makes sure that each implementation commit and the tip of the task branch pass npm run check. It gives the list of broken commits and the base commit. The agent does it in the task worktree, on the local task branch:
- Do steps 1 to 4 of the remote setup. If a step fails, stop. Nothing changes.
- Run
git fetch --multiple tasker origin. If the fetch fails, stop. Nothing changes. - Work in the task worktree, on the local task branch. This step makes no worktree. Outside the manual fix, do the update rule. In the manual fix, the local-commit rule holds, so run no update. If a step fails, stop. Nothing changes.
- In the task worktree, find the base commit:
git merge-base HEAD origin/<base branch>. If the command fails, stop. - Run
git rebase --exec 'L=$(git rev-parse --git-path npm-ci-lock); { cmp -s "$L" package-lock.json || { npm ci && cp package-lock.json "$L"; }; } && case "$(git log -1 --format=%s)" in feat:*|fix:*|refactor:*) npm run check ;; esac' <base commit>. The command runs after each commit. It runsnpm ciwhenpackage-lock.jsondiffers from the copy of the last install. It keeps that copy in the git folder of the worktree (git rev-parse --git-path npm-ci-lock), sogit statusstays clean. Then it runsnpm run checkafter each implementation commit. The rebase skipstest:anddocs:commits. Ifnpm cifails, the command fails after that commit, and step 6 notes that commit. Because the branch already starts on the base commit, the rebase keeps the same commits. - If the rebase stops and prints
warning: execution failed, the command failed after the commit thatgit log -1 --format='%h %s'names. Note that commit as a broken commit. Then rungit rebase --continue, and the rebase checks the next commits. Do this step again each time the rebase stops this way. A commit after a broken commit can fail only because of the earlier commit. The session fixes the oldest broken commit first and then runs the check again, so a fix of the earlier commit can also remove a later commit from the list. - If the rebase stops for another reason, run
git rebase --abort. The worktree goes back to the branch at the old tip. Then stop and report the error. If the abort fails, the ref of the branch is still at the old tip, and the worktree stays in the rebase. Stop and report the output ofgit -C <path> status. - When the rebase exits with 0, it kept the same commits, and the worktree is at the tip. If the tip is not an implementation commit, run
npm run checkone time in the worktree. The worktree already has the packages of the tip, because the rebase ran the command after the tip too. Ifnpm run checkfails, note the tip as a broken commit. - The commit check passes when it noted no broken commit. Otherwise, the check fails and gives the list of broken commits and the base commit of step 4. The step that ran the check gives the next step.
During the rebase, HEAD is detached inside the task worktree, and the branch ref stays at the old tip. When the rebase ends, it keeps the same commits, so the branch is at the same tip.