diff --git a/GLOSSARY.md b/GLOSSARY.md index c26a4961f..0a3732cf8 100644 --- a/GLOSSARY.md +++ b/GLOSSARY.md @@ -4,6 +4,8 @@ A factory that turns a GitHub issue into a ready-for-review pull request, or on ## Language +### Issues and triage + **Day shift**: The human half of the workflow: shaping work into issues the factory can take on (grilling, specs, tickets), and reviewing the pull requests it delivers, except those a **Merge run** merges itself. _Avoid_: planning phase @@ -12,6 +14,41 @@ _Avoid_: planning phase The GitHub issue link the factory is given to implement, e.g. `https://github.com///issues/`. _Avoid_: ticket, spec link +**Spec**: +An issue describing a multi-session piece of work, what is being built rather than how each session does its share, made of **Tickets**: its GitHub sub-issues. See [Spec](https://www.aihero.dev/ai-coding-dictionary/spec) in Matt Pocock's AI Coding Dictionary. +_Avoid_: PRD, parent issue + +**Ticket**: +An issue scoping one session of work, standing alone or as a sub-issue of a **Spec**. A Ticket in a Spec can block or be blocked by sibling Tickets; the order of work falls out of those GitHub "blocked by" links. See [Ticket](https://www.aihero.dev/ai-coding-dictionary/ticket) in Matt Pocock's AI Coding Dictionary. +_Avoid_: task, sub-task + +**Ready issue**: +An open issue a **Pickup run** may take: labelled `ready-for-agent`, written by a **Trusted account**, with its most recent `ready-for-agent` labelling made by a Trusted account and no edit to its title or body since then by an account that is not one, with no label that makes an **Unready Ticket** and no **Claim**, not a sub-issue, not a **Base fix**'s or a **Security run**'s fix issue, with no open blocker, either never started (no **Issue branch** and no pull request) or handed back by the **Day shift** applying `ready-for-agent` after the last **Claim** ended, as recorded in its label history, not a **Spec** whose **Tickets** are all closed, left untouched long enough that whoever is shaping it has finished, and, if it is a Spec, with a **Startable Ticket**. On a Spec, the label says its Tickets are published. A `ready-for-agent` Ticket inside a Spec is not one: it is reached through its Spec, when the Spec is itself a Ready issue. +_Avoid_: queued issue, backlog item + +**Trusted account**: +The repository's owner, a member of the organization that owns it, or a collaborator on it: an issue author's `authorAssociation` of `OWNER`, `MEMBER` or `COLLABORATOR`, or equivalent repository membership for an actor with no association field. The rule is fixed, with no **User config** setting. A **Spec run** stops before starting the Run of a **Ticket** whose author is not a Trusted account, or whose title or body an account that is not one edited after the later of the Ticket's and its Spec's last `ready-for-agent` labellings by a Trusted account. A Ticket needs no `ready-for-agent` labelling of its own: the labelling that counts is its Spec's, checked when a **Pickup run** takes the Spec. Before each session of a **Run**, a **Resume** included, its issue is checked again: a title or body edit by an account that is not a Trusted account, made since a few minutes before the Run started, fails the Run instead of starting the session. Each session that works on an issue gets the issue from thirdshift, written into its worktree again before the session starts: its title, its body, and only the comments by Trusted accounts, each other comment replaced by a line saying it was left out. The **Session prompt** and **Factory skills** tell the session to work from that and not to fetch the issue's comments itself. + +**Unready Ticket**: +An open **Ticket** labelled with a triage role that says it is not agent work: `ready-for-human`, `needs-info`, `wontfix` or `needs-triage`. A **Spec run** never starts a **Run** for one, nor for a Ticket it blocks. An open Ticket with no triage label is taken. A Ticket with sub-issues of its own is treated as one too. + +**Startable Ticket**: +An open **Ticket** in its **Spec**'s repository, with no sub-issues of its own, no open blocker, and not an **Unready Ticket**: one a **Spec run** could start if no Ticket were running. A Spec run starts only these, and a **Spec** with none is not a **Ready issue**. + +**Claim**: +The mark that the factory has taken an issue: thirdshift labels the issue `in-progress`, in place of `ready-for-agent` if it has that, when a **Run** or a **Spec run** starts on it, whether started on its **Issue URL** or by an **Architect run**, a **Pickup run** or a **Security run**. A **Ticket**'s Run in a Spec run and a **Base fix** make none. Ending a Claim finishes even after Command interruption. A failed Security fix keeps its Claim even with nothing on `origin`, so it stays with the Day shift. For other Runs, a Claim is released, `ready-for-agent` put back, only when the Run ends with nothing on `origin` to take over and was not ended by a **Stop**: no **Issue branch** and no pull request. Otherwise it stays while the issue is open, whether its pull request is ready for review or the Run failed, until the **Day shift** relabels it, and thirdshift takes the label off once the issue is closed. +_Avoid_: lock (a lock is per machine and ends with its process), assignment + +**Claim limit**: +The number of open issues carrying a **Claim** at which a **Pickup run** takes no more, set in the **User config**. It keeps a broken **Base branch** from failing every **Ready issue** in turn, and pull requests from piling up unreviewed. +_Avoid_: WIP limit, concurrency (it counts issues waiting on the **Day shift**, not Runs in flight) + +**Sweep**: +A **Pickup run**'s removal of `in-progress` from every closed issue in the repository that still has it, such as one whose pull request was merged by hand, with the issue's other labels kept. Each Pickup run that is not skipped for the lock makes one, before it holds the repository against its **Claim limit**. A Sweep that fails is a warning, never a failure. +_Avoid_: cleanup, garbage collection + +### Repository and branches + **Launch directory**: The directory a **Run** is started from. It must pass **Origin match**, and its checked-out branch is normally the **Base branch**. Base branch validation and optional pulling share one sampled origin commit; **Worktree** acquisition samples independently. A Run works in its own worktree, never in the Launch directory. _Avoid_: originating workspace, launch repo @@ -22,6 +59,14 @@ The rule that the **Issue URL** must belong to the same GitHub repository as the **Base branch**: The branch the work branches off and the pull request targets. Normally the branch checked out in the **Launch directory**; for an **Architect run** or a **Pickup run** whose command names a branch, that branch, whatever is checked out; for a **Ticket**'s **Run** in a **Spec run**, the **Spec branch**; in a **Continuation** with an open pull request, that pull request's base instead. +**Worktree**: +A [factory-owned checkout](docs/guide.md#worktree-ownership-and-cleanup), on an **Issue branch** for a **Run** or detached for an **Architecture review**. It is retained whenever ownership is uncertain or the Run's work could not be preserved elsewhere. + +**Issue branch**: +A branch a **Run** works on for one issue: `issue-` (the first), then `issue--branch-` for k ≥ 2. A number counts as used once its pull request is merged or closed, even if the branch itself was deleted. + +### Agent sessions + **Factory skills**: The skills in `skills/`, each named `thirdshift-` and placed in each **Run**'s worktree for its **Harness** to find: adapted copies of Matt Pocock's skills, designed to run headless with no human in the loop. _Avoid_: the skills (ambiguous with `.claude/skills/`) @@ -41,37 +86,18 @@ The model the **Harness** runs its sessions on, such as Opus 5.5 or GPT-6.1-Sol. How hard the **Model** reasons in each session, such as `high` or `max`. One per **Command**, chosen the way the Model is. _Avoid_: reasoning level, thinking budget -**Standards finding**: -A finding from the Standards axis of a code review: the change breaks a documented coding standard or shows a baseline code smell. - -**Spec finding**: -A finding from the Spec axis of a code review: the change is missing, gets wrong, or goes beyond what the issue asked for. - -**Security finding**: -A vulnerability a **Security review** or a **Security audit** found. One the **Run**'s own change introduced, left unaddressed, holds a **Self-merge** into the **Base branch**. One already on the Base branch is never written up in public before it is fixed: it is recorded privately for the **Day shift**, as a draft security advisory on a public repository or a labelled issue on a private one. Once recorded, it waits for the Day shift, unless it is reproduced and fixing is allowed, until the Day shift triages it: by closing its draft advisory, publishing it or giving it a severity, or by taking `needs-triage` off its issue. That decision also settles whether it was real. -_Avoid_: vulnerability report, security issue - -**Unaddressed finding**: -A **Standards finding** or **Spec finding** the agent chose not to fix, listed in the pull request body with what refutes it: a line of code, a plan decision, an ADR or a run that exercises the finding. When a Spec or the Day shift must decide, the entry instead links the `needs-triage` issue filed for that decision, or the open issue already covering it. A **Security finding** the change itself introduced, which the **Security review** left unfixed, is listed there too, and holds a **Self-merge** into the **Base branch**. +**Resume**: +A continuation of the same agent session, started once when that session ended its turn with background work still running, which was killed with it: thirdshift takes it as work the session was waiting on. Its **Session prompt** asks the agent to re-run that work in the foreground and finish. A Resume that ends the same way gets no second Resume and does not fail the **Run**: the work may have been abandoned rather than awaited, so thirdshift names it in a progress line and carries on, and the steps that follow decide the outcome. If the Run is then a **Failed run**, its cause names the killed work ahead of the step that failed. A Resume is not a **Repair** and does not count against the Repair cap. -**Spec**: -An issue describing a multi-session piece of work, what is being built rather than how each session does its share, made of **Tickets**: its GitHub sub-issues. See [Spec](https://www.aihero.dev/ai-coding-dictionary/spec) in Matt Pocock's AI Coding Dictionary. -_Avoid_: PRD, parent issue +### Runs -**Ticket**: -An issue scoping one session of work, standing alone or as a sub-issue of a **Spec**. A Ticket in a Spec can block or be blocked by sibling Tickets; the order of work falls out of those GitHub "blocked by" links. See [Ticket](https://www.aihero.dev/ai-coding-dictionary/ticket) in Matt Pocock's AI Coding Dictionary. -_Avoid_: task, sub-task +**Command**: +One invocation of thirdshift that does factory work: a **Run** or **Spec run** started on an **Issue URL**, an **Architect run**, a **Pickup run**, a **Security run**, or a **Scoring run**. A child Run, a **Ticket**'s Run or a **Base fix**, is part of the command that started it, not one of its own. Interruption stops its ordinary CLI work and prevents more from starting, while Failed run salvage, confirmed Self-merge completion, Claim ending and Spec accounting still finish; finishing never clears the recorded interruption. +_Avoid_: invocation, job **Run**: One invocation of the factory on a single issue that is not a **Spec**, from launch to cleanup, ending in one pull request. Started directly on an **Issue URL**, by a **Spec run** for one of its **Tickets**, by an **Architect run** for the Ticket its **Architecture review** published, by a **Pickup run** for the **Ready issue** it took, or by a **Security run** for a **Security finding** it fixes. -**Worktree**: -A factory-owned checkout, on an **Issue branch** for a **Run** or detached for an **Architecture review**. Acquisition accounts for partial local effects: failed-acquisition recovery rechecks clean-only, instance-specific authority before and after every destructive attempt, including retries, advances only on verified transitions, and retains and names remaining work or uncertain partial effects. Failed-acquisition retention survives later Architecture review attempts. Successful acquisition carries checkout and registration identity through its lifetime; ordinary synchronization, observations and Failed run preservation share acquired-instance checks before and after every Git subprocess attempt, including retries, acting only on that acquired checkout and selected Issue branch and refusing changed or uncertain ownership. Failed run preservation retains work when ownership has changed or is uncertain and finishes after Command interruption without clearing it; ordinary synchronization remains interruptible. Confirmed Self-merge branch deletion uses the captured Launch repository independently of checkout validity. Cleanup checks stage-specific disposal authority before and after every destructive Git attempt, including retries: acquired identity and the captured cleanup head for checkout removal, removed-path absence and an unused expected head for local branch removal, then ref absence and the exact original local subsection for branch configuration removal. Only successful, verified transitions advance disposal; partial failures retain and name every remaining or uncertain resource. Live cleanup finishes after Command interruption without clearing it; stale disposal stays interruptible. Stale Architecture review scratch is disposable only with evidence of successful detached acquisition and unchanged ownership; unmarked or uncertain checkouts are retained. - -**Claim**: -The mark that the factory has taken an issue: thirdshift labels the issue `in-progress`, in place of `ready-for-agent` if it has that, when a **Run** or a **Spec run** starts on it, whether started on its **Issue URL** or by an **Architect run**, a **Pickup run** or a **Security run**. A **Ticket**'s Run in a Spec run and a **Base fix** make none. Ending a Claim finishes even after Command interruption. A failed Security fix keeps its Claim even with nothing on `origin`, so it stays with the Day shift. For other Runs, a Claim is released, `ready-for-agent` put back, only when the Run ends with nothing on `origin` to take over and was not ended by a **Stop**: no **Issue branch** and no pull request. Otherwise it stays while the issue is open, whether its pull request is ready for review or the Run failed, until the **Day shift** relabels it, and thirdshift takes the label off once the issue is closed. -_Avoid_: lock (a lock is per machine and ends with its process), assignment - **Spec run**: One invocation of the factory on a **Spec**'s **Issue URL**: it works through the Spec's **Tickets** in dependency order, starting a **Run** for each Ticket once the Tickets blocking it are done, several at once when the graph allows. _Avoid_: batch run, spec implementation @@ -80,14 +106,6 @@ _Avoid_: batch run, spec implementation One invocation of the factory with no **Issue URL**: an **Architecture review** of the **Base branch**, then, unless asked to stop there, a **Spec run** or a **Run** on the **Architect plan** it published. One pass per invocation. It is skipped, doing nothing, when another **Pass** on the same repository is still running on the machine, its Spec run or Run included, when an earlier Architect plan is still open, when an **Architect idea** is waiting for triage, or when the repository has a **Ready issue**, so that work a human shaped goes first. Skipped is not a failure, and sends no **Run notification**, so that it can be started every few minutes and so follow the last one as soon as its plan is merged. _Avoid_: improve run, architecture run -**Weeding**: -The factory clearing the detritus that features leave in a repository's codebase as they land, with no human starting it: **Architect runs** started often enough that each follows the last as soon as its **Architect plan** is merged. It yields to work a human shaped, and pauses for the **Day shift** whenever a plan fails or an **Architect idea** waits for triage. -_Avoid_: upkeep, continuous architect, daemon, loop - -**Fencing**: -The factory finding and fixing vulnerabilities in a repository's codebase with no human starting it: **Security runs** started as often as the operating system's scheduler is set to start them, with fixing allowed. Like **Weeding**, it yields to work a human shaped, and pauses for the **Day shift** whenever a fix fails or a **Security finding** waits for triage. -_Avoid_: patrol, continuous security, security loop - **Pickup run**: One invocation of the factory with no **Issue URL**: it takes the lowest-numbered **Ready issue** in the repository and starts a **Spec run** or a **Run** on it, as the command on that issue's URL would. One issue per invocation, and thirdshift never schedules itself: the operating system's scheduler starts each one. Before dispatch, it reserves the issue across machines and rechecks that it is Ready with no intervening **Claim** since selection. The reservation lasts through the dispatched run's ending, then is released only by its owner; after a crash it waits for the **Day shift** to confirm the owner has stopped and release it. It is skipped, doing nothing, when another **Pass** on the same repository is still running on the machine, its Spec run or Run included, when there is no Ready issue, when the repository is at its **Claim limit**, or when the selected issue is reserved or its selection is stale. Skipped is not a failure, and sends no **Run notification**. _Avoid_: watch, daemon, queue run, poll @@ -100,20 +118,19 @@ _Avoid_: Secure run (it reads as a run that is secure), audit run, security pass An **Architect run**, a **Pickup run** or a **Security run**: a **Command** started with no **Issue URL**, which decides before any work whether it is skipped. _Avoid_: tick, cycle -**Claim limit**: -The number of open issues carrying a **Claim** at which a **Pickup run** takes no more, set in the **User config**. It keeps a broken **Base branch** from failing every **Ready issue** in turn, and pull requests from piling up unreviewed. -_Avoid_: WIP limit, concurrency (it counts issues waiting on the **Day shift**, not Runs in flight) +**Merge run**: +A **Run** asked to end with its pull request merged rather than left for review, by the command it was started with or by the **User config**. It does everything a **Run** does, then a **Self-merge**. A **Ticket**'s Run in a **Spec run** is always a Merge run into the **Spec branch**; the command's ask applies to the **Spec PR**. +_Avoid_: auto-merge (GitHub's own feature, which thirdshift does not use) -**Sweep**: -A **Pickup run**'s removal of `in-progress` from every closed issue in the repository that still has it, such as one whose pull request was merged by hand, with the issue's other labels kept. Each Pickup run that is not skipped for the lock makes one, before it holds the repository against its **Claim limit**. A Sweep that fails is a warning, never a failure. -_Avoid_: cleanup, garbage collection +**Weeding**: +The factory clearing the detritus that features leave in a repository's codebase as they land, with no human starting it: **Architect runs** started often enough that each follows the last as soon as its **Architect plan** is merged. It yields to work a human shaped, and pauses for the **Day shift** whenever a plan fails or an **Architect idea** waits for triage. +_Avoid_: upkeep, continuous architect, daemon, loop -**Ready issue**: -An open issue a **Pickup run** may take: labelled `ready-for-agent`, written by a **Trusted account**, with its most recent `ready-for-agent` labelling made by a Trusted account and no edit to its title or body since then by an account that is not one, with no label that makes an **Unready Ticket** and no **Claim**, not a sub-issue, not a **Base fix**'s or a **Security run**'s fix issue, with no open blocker, either never started (no **Issue branch** and no pull request) or handed back by the **Day shift** applying `ready-for-agent` after the last **Claim** ended, as recorded in its label history, not a **Spec** whose **Tickets** are all closed, left untouched long enough that whoever is shaping it has finished, and, if it is a Spec, with a **Startable Ticket**. On a Spec, the label says its Tickets are published. A `ready-for-agent` Ticket inside a Spec is not one: it is reached through its Spec, when the Spec is itself a Ready issue. -_Avoid_: queued issue, backlog item +**Fencing**: +The factory finding and fixing vulnerabilities in a repository's codebase with no human starting it: **Security runs** started as often as the operating system's scheduler is set to start them, with fixing allowed. Like **Weeding**, it yields to work a human shaped, and pauses for the **Day shift** whenever a fix fails or a **Security finding** waits for triage. +_Avoid_: patrol, continuous security, security loop -**Trusted account**: -The repository's owner, a member of the organization that owns it, or a collaborator on it: an issue author's `authorAssociation` of `OWNER`, `MEMBER` or `COLLABORATOR`, or equivalent repository membership for an actor with no association field. The rule is fixed, with no **User config** setting. A **Spec run** stops before starting the Run of a **Ticket** whose author is not a Trusted account, or whose title or body an account that is not one edited after the later of the Ticket's and its Spec's last `ready-for-agent` labellings by a Trusted account. A Ticket needs no `ready-for-agent` labelling of its own: the labelling that counts is its Spec's, checked when a **Pickup run** takes the Spec. Before each session of a **Run**, a **Resume** included, its issue is checked again: a title or body edit by an account that is not a Trusted account, made since a few minutes before the Run started, fails the Run instead of starting the session. Each session that works on an issue gets the issue from thirdshift, written into its worktree again before the session starts: its title, its body, and only the comments by Trusted accounts, each other comment replaced by a line saying it was left out. The **Session prompt** and **Factory skills** tell the session to work from that and not to fetch the issue's comments itself. +### Architecture **Architecture review**: The agent session that opens an **Architect run**: it scans the **Base branch** for deepening opportunities, skips any already covered by an open issue, and publishes the top recommendation as the **Architect plan**, but only when that recommendation is Strong. Otherwise it files the top recommendation as an **Architect idea** for the **Day shift**, or names the open issue that already covers it, and nothing is implemented. It changes nothing in the repository. @@ -127,9 +144,7 @@ _Avoid_: plan, plan doc The issue an **Architecture review** ends on when its top recommendation is not Strong: the one it filed, or the open issue that already covered it. thirdshift labels it `architect-idea` and `needs-triage`, the second put back on an issue that already covered the idea and had been triaged, since the factory again takes it for the best next move. While any Architect idea is open and still labelled `needs-triage`, every **Architect run** on the repository is skipped: the factory has run out of Strong ideas, and waits for the **Day shift** to triage one, whatever the decision. _Avoid_: weak plan, suggestion -**Security audit**: -The agent session that opens a **Security run**: it audits the **Base branch** for vulnerabilities, and records each **Security finding** privately for the **Day shift**. It changes nothing in the repository, and writes nothing public about a vulnerability. -_Avoid_: security scan, security review (a **Security review** reviews one Run's change) +### Spec coordination **Spec branch**: The **Issue branch** of the **Spec** in a **Spec run**, branched off the **Base branch**. Each **Ticket**'s **Run** is a **Merge run** into it, so the Spec's work gathers there before it reaches the Base branch. @@ -141,44 +156,52 @@ The pull request from the **Spec branch** into the **Base branch** that closes t **Tickets checklist**: The part of the **Spec PR**'s body, between fixed markers, that thirdshift writes: one line per **Ticket**, ticked once it is done, with its pull request, or saying whether it is not started, running, failed, interrupted, blocked, in a cycle or unready. It is rewritten as each Ticket starts and ends, and put back after the **Spec review** rewrites the body. -**Unready Ticket**: -An open **Ticket** labelled with a triage role that says it is not agent work: `ready-for-human`, `needs-info`, `wontfix` or `needs-triage`. A **Spec run** never starts a **Run** for one, nor for a Ticket it blocks. An open Ticket with no triage label is taken. A Ticket with sub-issues of its own is treated as one too. - -**Startable Ticket**: -An open **Ticket** in its **Spec**'s repository, with no sub-issues of its own, no open blocker, and not an **Unready Ticket**: one a **Spec run** could start if no Ticket were running. A Spec run starts only these, and a **Spec** with none is not a **Ready issue**. - **Spec review**: The agent session a **Spec run** starts once every **Ticket** is done: it reviews the whole **Spec branch** against the **Base branch** and the **Spec**, fixes what it agrees with, and writes the **Spec PR**'s description, listing the rest as **Unaddressed findings**. -**Security review**: -When a flag or the **User config** asks for one, the agent session a **Run** starts after its opening session, or a **Spec run** starts on its **Spec PR** after the **Spec review**: it reviews the branch's change against the **Base branch** for vulnerabilities, and fixes each **Security finding** it can show with a failing test. A **Ticket**'s Run gets none. A **Base fix** gets one when its Command asked for one, whichever Run started it, a Ticket's Run included. It runs on the User config's `security.harness` when that is set, whatever **Harness** the Command chose, and on the Command's Harness otherwise. A Security review that a model refused, or that ended early, holds a **Self-merge** as an unaddressed Security finding does. -_Avoid_: security axis, security audit (a **Security audit** covers the whole Base branch) - **Failed spec run**: A **Spec run** that ends, including by interruption, with any of its **Tickets** not done, or with its **Spec PR** not ready, mergeable and green (or, when asked to merge, not merged). It still takes every Ticket it can reach, and a failed Ticket stops only the Tickets it blocks. After Command interruption it starts no new Ticket or Spec review, drains its active Tickets, and finishes publishing their final Tickets checklist and outcome lines. -**Merge run**: -A **Run** asked to end with its pull request merged rather than left for review, by the command it was started with or by the **User config**. It does everything a **Run** does, then a **Self-merge**. A **Ticket**'s Run in a **Spec run** is always a Merge run into the **Spec branch**; the command's ask applies to the **Spec PR**. -_Avoid_: auto-merge (GitHub's own feature, which thirdshift does not use) +### Reviews and findings -**Run notification**: -A message thirdshift sends when a **Run**, a **Spec run**, an **Architect run** or a **Security run** ends, whatever its outcome (ready, merged, failed or interrupted; for an Architect run that dispatched nothing, plan published, idea filed, idea already filed or review failed), to the address given with the email flag or the default in the **User config**. Its body tells everything its subject does, so the body alone carries it. Each sends one only when asked to, by the flag or by the User config; a Spec run's notification lists each **Ticket**'s outcome, and a Ticket's **Run** never sends one of its own. After an **Inherited failure** it carries, beside the cause, what the Run says on stderr: where the checks fail on the **Base branch**, and the offer of a **Base fix** if nobody decided against one. An Architect run's notification tells how its **Architecture review** ended, naming the plan or idea issue, and how the Spec run or Run it dispatched ended, which sends none of its own; a skipped one sends none. A **Pickup run** that took a **Ready issue** sends the one the Spec run or Run it dispatched would have sent, which sends none of its own; a skipped one sends none. A **Security run**'s notification lists each **Security finding**'s severity, title and private link, never its write-up, since the message passes through a third party. When a Run leaves a reproduced finding unfixed and nobody decided against fixing, it offers both the command and the User config setting that allow fixing; a skipped one sends none. Its Session models section collects Model evidence kept beside each **Session log**, belonging to the exact owning **Command** across child Runs. Stream evidence survives interruption and is replaced by completed retained evidence only when a report is available; a present report with no observed Models is authoritative. Requested **Model** and **Effort** choices remain distinct from observed Models, with requested/default fallback wording when none were reported. Failing to collect evidence or send one never changes the outcome. -_Avoid_: completion email, alert +**Standards finding**: +A finding from the Standards axis of a code review: the change breaks a documented coding standard or shows a baseline code smell. -**User config**: -The per-machine settings file in the user's home folder that sets thirdshift's defaults for every **Run** started on that machine, such as the **Run notification** address, whether every Run is a **Merge run**, whether a Run may start a **Base fix**, whether a Run first brings the **Launch directory**'s checkout of the **Base branch** up to date with `origin`, and the **Harness**, with a **Model** and **Effort** for each Harness. With no User config, or one that says nothing about a setting, a Run does only what its command asks for. +**Spec finding**: +A finding from the Spec axis of a code review: the change is missing, gets wrong, or goes beyond what the issue asked for. -**Credentials**: -The per-machine secrets file next to the **User config**, readable only by its owner, that holds the Resend API key a **Run notification** is sent with, and the **Console**'s sign-in emails. The key in the environment wins over it; it is what lets a **Run** started from cron, `nohup` or an agent's shell find the key. Only commands that send email read it, so the User config holds no secret. -_Avoid_: secrets file, key file +**Security finding**: +A vulnerability a **Security review** or a **Security audit** found. One the **Run**'s own change introduced, left unaddressed, holds a **Self-merge** into the **Base branch**. One already on the Base branch is never written up in public before it is fixed: it is recorded privately for the **Day shift**, as a draft security advisory on a public repository or a labelled issue on a private one. Once recorded, it waits for the Day shift, unless it is reproduced and fixing is allowed, until the Day shift triages it: by closing its draft advisory, publishing it or giving it a severity, or by taking `needs-triage` off its issue. That decision also settles whether it was real. +_Avoid_: vulnerability report, security issue -**Setup**: -Writing the **User config** by answering a few questions, one per setting that matters most, with every other setting written out at its default so the file shows everything that can be changed. With **Run notifications** on, it also asks for the Resend API key and writes the **Credentials** when one is entered. Offered by the first **Run** on a machine with no User config, and run again at any time to change the answers. -_Avoid_: init, onboarding, configure +**Unaddressed finding**: +A **Standards finding** or **Spec finding** the agent chose not to fix, listed in the pull request body with what refutes it: a line of code, a plan decision, an ADR or a run that exercises the finding. When a Spec or the Day shift must decide, the entry instead links the `needs-triage` issue filed for that decision, or the open issue already covering it. A **Security finding** the change itself introduced, which the **Security review** left unfixed, is listed there too, and holds a **Self-merge** into the **Base branch**. + +**Security audit**: +The agent session that opens a **Security run**: it audits the **Base branch** for vulnerabilities, and records each **Security finding** privately for the **Day shift**. It changes nothing in the repository, and writes nothing public about a vulnerability. +_Avoid_: security scan, security review (a **Security review** reviews one Run's change) + +**Security review**: +When a flag or the **User config** asks for one, the agent session a **Run** starts after its opening session, or a **Spec run** starts on its **Spec PR** after the **Spec review**: it reviews the branch's change against the **Base branch** for vulnerabilities, and fixes each **Security finding** it can show with a failing test. A **Ticket**'s Run gets none. A **Base fix** gets one when its Command asked for one, whichever Run started it, a Ticket's Run included. It runs on the User config's `security.harness` when that is set, whatever **Harness** the Command chose, and on the Command's Harness otherwise. A Security review that a model refused, or that ended early, holds a **Self-merge** as an unaddressed Security finding does. +_Avoid_: security axis, security audit (a **Security audit** covers the whole Base branch) + +### Delivery and recovery + +**Delivery**: +The [workflow](docs/guide.md#delivery-and-pull-request-identity) that takes a **Run**'s work, or a **Spec run**'s **Spec PR**, from its opening session to a ready-for-review or merged pull request. It includes publication, the **Repair loop** and, in a **Merge run**, the **Self-merge**. **Self-merge**: The step at the end of a **Merge run** in which thirdshift itself merges Delivery's captured pull request by number in its repository, with a merge commit at the exact head whose CI it watched. A fresh observation validates its expected **Issue branch** and **Base branch**, open state, readiness and mergeability immediately before the request. GitHub guards the requested head, but offers no atomic expected-base guard against a retarget between that observation and the server merge. No human reviews it first. A failed or interrupted request counts as merged only when a completion observation of the same number confirms the requested head and expected branches. Completion then continues even after Command interruption. It ends with the **Issue branch** deleted, the issue closed by thirdshift, unless it is already closed, and the issue's **Claim** removed. +**Repair loop**: +The rounds a **Delivery** goes through until the pull request's head is mergeable with the **Base branch** and its CI is green or absent. Each round merges the Base branch in (and, in a **Merge run**, any **Foreign commits**), pushes, watches CI, and starts a **Repair** for a conflict or for the branch's own red checks. When the Base branch moved while green or absent CI ran, a Merge run goes round again to merge it in. A Delivery that leaves the pull request ready for review stops on that head if GitHub reports the pull request mergeable, and the move is not counted; otherwise it goes round again. Repairs and upstream moves have fixed budgets. + +**Repair**: +A follow-up agent session a **Run** starts after the pull request exists, or a **Spec run** starts on its **Spec PR** after the **Spec review**: to resolve a merge conflict with the **Base branch** or the **Issue branch** on `origin`, to fix failing CI checks, or, in a **Merge run**, to review and fix **Foreign commits**. + +**Foreign commit**: +A commit that appears on the **Issue branch** during a **Run** and was made neither by one of that Run's sessions nor by thirdshift itself. Commits already on the branch when a **Continuation** starts are not Foreign commits. A **Merge run** merges one only after a **Repair** has reviewed its resulting tree, unless that tree is identical to the Run's own head before reconciliation and is already covered by its existing review. A tree-identical batch still counts as an upstream move, but uses no Review Repair. + **Policy refusal**: A **Self-merge** blocked by a required review, or a merge it tried that failed where the round of the Repair loop that followed found nothing to fix: the **Base branch** unchanged, no conflict, CI green or absent, the pull request mergeable. The cause is a repository setting or rule, such as merge commits disallowed or a review required. thirdshift never reads GitHub's error text to decide it. A blocking review ends the Run as **review required** without a merge attempt or another Repair round. The **Merge run** is a **Failed run** that leaves the pull request ready for review. @@ -186,7 +209,7 @@ A **Self-merge** blocked by a required review, or a merge it tried that failed w A CI-fix **Repair** that found nothing on the branch to fix, for example because the failure is not the branch's but was not recognised as an **Inherited failure**, since the **Base branch** commit had no finished result for that check: once the Repair ends and the **Base branch** is merged in again, the head of the **Issue branch** is still the commit whose CI just failed. That head gets its one **Check re-run** for the **Delivery**; if its own checks are red again, or they cannot be re-run, the **Run** is a **Failed run** with the cause `CI red on and the Repair found nothing to fix on the branch`, rather than spending its remaining Repairs. Own checks found red on that head in any later round, including after a refused **Self-merge**, fail with the same cause without another CI-fix Repair or Check re-run. Inherited-only failures keep their usual handling, and a different head may receive its own CI-fix Repair and Check re-run. **Check re-run**: -The one time per full head commit across one **Delivery** that thirdshift asks GitHub to re-run the branch's own failed checks and watches CI on that head again: when a CI-fix **Repair** has left the head unchanged, and before the **Run** fails as a **Declined CI fix**. The allowance is consumed before the request and stays consumed through green CI, **Inherited failures**, a **Base fix**, upstream moves, later rounds and refused **Self-merge** reconciliation, even after visiting another head and returning. Later watches still obtain fresh CI facts; own checks red on a consumed head mean a Declined CI fix without another CI-fix Repair. A different head has its own allowance, and a separately started **Continuation** begins a new Delivery with fresh allowances. It lets a check that failed for a reason that does not repeat, such as a flaky test, pass. If GitHub refuses a request, the outcome comes from fresh checks on that same head: green continues the Run, pending is watched, and its own checks still red mean a Declined CI fix. Checks that cannot be read or disappear after known failures cannot establish success. What the Repair concluded is never read. It needs every one of those checks to be a GitHub Actions job, starts no Repair and counts against no budget, and never re-runs a check for being an Inherited failure. It is separate from the re-run of **Abandoned jobs**, which comes before any Repair. +The [one re-run](docs/guide.md#check-re-run-allowance) of a branch's own failed checks allowed per head commit within a **Delivery**, after a CI-fix **Repair** leaves that head unchanged and before a **Declined CI fix**. It gives a transient CI failure one chance to pass without another Repair. It is separate from the re-run of **Abandoned jobs**, which comes before any Repair. _Avoid_: retry, re-trigger, CI re-run **Abandoned job**: @@ -207,37 +230,28 @@ A **Run** that ends, including by interruption, without an open pull request fro **Recovery**: The lines a **Failed run** ends with, saying where it stopped, what work was preserved and where, and the command that continues or retries it; built only from factory-owned facts, never agent output. -**Issue branch**: -A branch a **Run** works on for one issue: `issue-` (the first), then `issue--branch-` for k ≥ 2. A number counts as used once its pull request is merged or closed, even if the branch itself was deleted. - **Continuation**: A **Run** that picks up an existing **Issue branch**, one with no pull request or an open one, instead of starting fresh. When a pull request is open, its base is the **Base branch**. -**Repair**: -A follow-up agent session a **Run** starts after the pull request exists, or a **Spec run** starts on its **Spec PR** after the **Spec review**: to resolve a merge conflict with the **Base branch** or the **Issue branch** on `origin`, to fix failing CI checks, or, in a **Merge run**, to review and fix **Foreign commits**. - -**Delivery**: -What a **Run**, or a **Spec run** for its **Spec PR**, does from its worktree once its work begins. It runs the opening session (the implement session, or the **Spec review**), pushes, marks the pull request ready, keeps it mergeable and green through the **Repair loop**, and, in a **Merge run**, does the **Self-merge**. For a Spec PR, Delivery ends Ticket accounting's capture before the Spec review, allowing that session to replace the PR. The first successful observation after the opening session, or during Failed run completion after an opening failure, captures one pull request number and URL in the issue's repository; all later observations and transitions use that identity. Readiness and every mergeability poll validate its expected **Issue branch** and **Base branch**, open state and readiness where required. A missing, closed or retargeted captured PR fails Delivery; a replacement from the same branch is never substituted. A Delivery that fails takes the **Failed run** path, drafting that same captured open PR after preserving work. Spec PR checklist restoration uses that Delivery capture before readiness and for final accounting after failure. +### Configuration -If a Delivery gate observes that its pull request has already merged into the expected Base branch, and its merged head includes all local work (the exact local head, with no uncommitted changes), the Run ends as merged, even when it originally asked only for ready for review. Delivery stops further publication, PR edits and Self-merge work. A merged PR that leaves local work out still fails and retains that work; a merged state alone never establishes completion. +**User config**: +The per-machine settings file in the user's home folder that sets thirdshift's defaults for every **Run** started on that machine, such as the **Run notification** address, whether every Run is a **Merge run**, whether a Run may start a **Base fix**, whether a Run first brings the **Launch directory**'s checkout of the **Base branch** up to date with `origin`, and the **Harness**, with a **Model** and **Effort** for each Harness. With no User config, or one that says nothing about a setting, a Run does only what its command asks for. -**Repair loop**: -The rounds a **Delivery** goes through until the pull request's head is mergeable with the **Base branch** and its CI is green or absent. Each round merges the Base branch in (and, in a **Merge run**, any **Foreign commits**), pushes, watches CI, and starts a **Repair** for a conflict or for the branch's own red checks. When the Base branch moved while green or absent CI ran, a Merge run goes round again to merge it in. A Delivery that leaves the pull request ready for review stops on that head if GitHub reports the pull request mergeable, and the move is not counted; otherwise it goes round again. Repairs and upstream moves have fixed budgets. +**Credentials**: +The per-machine secrets file next to the **User config**, readable only by its owner, that holds the Resend API key a **Run notification** is sent with, and the **Console**'s sign-in emails. The key in the environment wins over it; it is what lets a **Run** started from cron, `nohup` or an agent's shell find the key. Only commands that send email read it, so the User config holds no secret. +_Avoid_: secrets file, key file -**Foreign commit**: -A commit that appears on the **Issue branch** during a **Run** and was made neither by one of that Run's sessions nor by thirdshift itself. Commits already on the branch when a **Continuation** starts are not Foreign commits. A **Merge run** merges one only after a **Repair** has reviewed its resulting tree, unless that tree is identical to the Run's own head before reconciliation and is already covered by its existing review. A tree-identical batch still counts as an upstream move, but uses no Review Repair. +**Setup**: +Writing the **User config** by answering a few questions, one per setting that matters most, with every other setting written out at its default so the file shows everything that can be changed. With **Run notifications** on, it also asks for the Resend API key and writes the **Credentials** when one is entered. Offered by the first **Run** on a machine with no User config, and run again at any time to change the answers. +_Avoid_: init, onboarding, configure -**Resume**: -A continuation of the same agent session, started once when that session ended its turn with background work still running, which was killed with it: thirdshift takes it as work the session was waiting on. Its **Session prompt** asks the agent to re-run that work in the foreground and finish. A Resume that ends the same way gets no second Resume and does not fail the **Run**: the work may have been abandoned rather than awaited, so thirdshift names it in a progress line and carries on, and the steps that follow decide the outcome. If the Run is then a **Failed run**, its cause names the killed work ahead of the step that failed. A Resume is not a **Repair** and does not count against the Repair cap. +### Logs and records **Session log**: The full transcript of one agent session, one per session, a **Resume** and each **Repair** included. Kept with its repository's other logs, named for the session's kind and stamped with the local time its command started, so all of a command's Session logs sort together. The start stamp is a display and grouping fact; distinct Commands have distinct storage ownership even when their stamps agree. Model evidence is kept beside each Session log and belongs to the exact owning **Command**, including across child Runs. It survives an interrupted stream and is replaced by completed retained evidence only when a report is available, even when that report has no observed Models; an absent report leaves the stream evidence intact. Requested **Model** and **Effort** choices are recorded separately from observed Models. A session that ran the code review has its reviewers' reports kept beside its Session log. _Avoid_: transcript, session file -**Command**: -One invocation of thirdshift that does factory work: a **Run** or **Spec run** started on an **Issue URL**, an **Architect run**, a **Pickup run**, a **Security run**, or a **Scoring run**. A child Run, a **Ticket**'s Run or a **Base fix**, is part of the command that started it, not one of its own. Interruption stops its ordinary CLI work and prevents more from starting, while Failed run salvage, confirmed Self-merge completion, Claim ending and Spec accounting still finish; finishing never clears the recorded interruption. -_Avoid_: invocation, job - **Command log**: Everything one **Run**, **Spec run**, **Architect run**, **Pickup run** or **Security run** printed, kept in a file of its own with its repository's other logs, stamped like its **Session logs**. The start stamp is for display and grouping; Commands with the same start time still have distinct storage ownership for their Command logs, Session logs and **Command records**. An Architect run's, Pickup run's or Security run's covers the Spec runs or Runs it dispatched, and a Spec run's covers its **Tickets**' Runs, as a Run's covers its **Base fix**: none of those keeps one of its own. It is kept once the command starts work: a Pickup run, Architect run or Security run skipped before doing any work keeps none, and neither does a Run that fails before it starts work, such as on **Origin match**. _Avoid_: cron log, output log, run log (a **Run** is one kind of command) @@ -246,14 +260,20 @@ _Avoid_: cron log, output log, run log (a **Run** is one kind of command) One running record per repository of what the factory did there: a line when a **Run**, **Spec run**, **Architect run**, **Pickup run** or **Security run** starts work, naming its **Command log**, a line when it is given a **Stop**, naming who asked and whether from the CLI or the **Console**, and a line when it ends, with its outcome. A skipped Architect run, Pickup run or Security run writes a line only when its reason differs from the last one recorded for its kind, so a repository that sits idle shows one line, not one per pass. It is what thirdshift writes about a scheduled pass, in place of output to the scheduler. _Avoid_: cron log, pass log, history -**Console**: -The web page a machine serves that shows every **Command** started on it, opening on its **Inbox**, with each one's child **Runs**, their stages and their logs, and from which a live Command can be stopped. Each machine serves its own, behind a sign-in. It does nothing the CLI can't do: every view and action it offers is also a command. -_Avoid_: dashboard, floor, UI, web UI - **Command record**: What a **Command** keeps on its machine about where it is: its process, its issue if it has one, each child **Run** with the stages it has been through and when each began, and, once it ends, its outcome. Kept beside its **Command log** after the Command ends, so the **Console** and the CLI can show live and past Commands alike. A record whose process is gone, with no outcome, belongs to a Command that died at its last stage. _Avoid_: live record, state file, status file +**Run notification**: +A message thirdshift sends when a **Run**, a **Spec run**, an **Architect run** or a **Security run** ends, whatever its outcome (ready, merged, failed or interrupted; for an Architect run that dispatched nothing, plan published, idea filed, idea already filed or review failed), to the address given with the email flag or the default in the **User config**. Its body tells everything its subject does, so the body alone carries it. Each sends one only when asked to, by the flag or by the User config; a Spec run's notification lists each **Ticket**'s outcome, and a Ticket's **Run** never sends one of its own. After an **Inherited failure** it carries, beside the cause, what the Run says on stderr: where the checks fail on the **Base branch**, and the offer of a **Base fix** if nobody decided against one. An Architect run's notification tells how its **Architecture review** ended, naming the plan or idea issue, and how the Spec run or Run it dispatched ended, which sends none of its own; a skipped one sends none. A **Pickup run** that took a **Ready issue** sends the one the Spec run or Run it dispatched would have sent, which sends none of its own; a skipped one sends none. A **Security run**'s notification lists each **Security finding**'s severity, title and private link, never its write-up, since the message passes through a third party. When a Run leaves a reproduced finding unfixed and nobody decided against fixing, it offers both the command and the User config setting that allow fixing; a skipped one sends none. Its Session models section collects Model evidence kept beside each **Session log**, belonging to the exact owning **Command** across child Runs. Stream evidence survives interruption and is replaced by completed retained evidence only when a report is available; a present report with no observed Models is authoritative. Requested **Model** and **Effort** choices remain distinct from observed Models, with requested/default fallback wording when none were reported. Failing to collect evidence or send one never changes the outcome. +_Avoid_: completion email, alert + +### Console + +**Console**: +The web page a machine serves that shows every **Command** started on it, opening on its **Inbox**, with each one's child **Runs**, their stages and their logs, and from which a live Command can be stopped. Each machine serves its own, behind a sign-in. It does nothing the CLI can't do: every view and action it offers is also a command. +_Avoid_: dashboard, floor, UI, web UI + **Stop**: Ending a live **Command** on request, from the CLI or the **Console**. It is an interruption, and the Command cleans up as after any other, but its issue is left for the **Day shift**: labelled `needs-triage`, with `ready-for-agent` not put back, unless the Stop asks for the issue to go back in line. Stop waits for the Command to end, then reports its outcome and any branch or pull request it left. The **Activity log** records who asked for it. A Stop of a **Spec run** stops its **Tickets**' Runs with it. _Avoid_: kill, cancel, abort @@ -290,6 +310,8 @@ _Avoid_: average, baseline, estimate How the **Console** looks, its colours, fonts, shapes, effects and motion, over a layout that every Theme shares. thirdshift comes with some, and a user can make their own. Choosing one changes how the page looks, never what it shows. _Avoid_: skin, style, variant +### Evals + **Eval**: A test of how well thirdshift's agents do their work: offline, on an **Eval suite** in an **Experiment**, or online, on a sample of merged work in a **Scoring run**. _Avoid_: evaluation, benchmark diff --git a/docs/guide.md b/docs/guide.md index aa01d351b..9e1f58496 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -41,6 +41,38 @@ From a clone of the issue's repository, `thirdshift `: 7. In a **Merge run** (`thirdshift merge `), does the **Self-merge**: once the pull request is open, ready for review, mergeable and green, thirdshift merges it into the Base branch with a merge commit, on exactly the head commit whose CI it watched (`gh pr merge --merge --match-head-commit `). Just before each attempt, it reads the PR's `reviewDecision`: `REVIEW_REQUIRED` or `CHANGES_REQUESTED` ends the Run as **review required**, a policy refusal, without attempting the merge or taking another Repair round. An empty or `APPROVED` decision, or a failed read, keeps the existing merge behavior. It never uses GitHub's auto-merge ([ADR-0004](adr/0004-self-merge-by-thirdshift-not-github-auto-merge.md)). A merge that fails goes back round step 6, within the same budgets, and is tried again on the new green head. If that round finds nothing to fix, the refusal is a **policy refusal**, such as merge commits being disallowed or a review being required. After the merge, thirdshift deletes the Issue branch on `origin`, and closes the issue if it is still open, with the comment `Closed by #, merged into by a thirdshift Merge run.` GitHub closes it on its own only for a merge into the repository's default branch, and then thirdshift leaves it alone. Once the issue is closed, either way, thirdshift takes `in-progress` off it, [removing the Claim](#when-the-claim-ends). 8. Cleans up: removes the worktree, the local Issue branch and the temporary directory the Factory skills were written out to, whether the Run succeeded or not. The one exception is a **Failed run** whose work could not be pushed: see below. +### Worktree ownership and cleanup + +A factory-owned checkout, on an **Issue branch** for a **Run** or detached for an **Architecture review**. + +Acquisition accounts for partial local effects: failed-acquisition recovery rechecks clean-only, instance-specific authority before and after every destructive attempt, including retries, advances only on verified transitions, and retains and names remaining work or uncertain partial effects. Failed-acquisition retention survives later Architecture review attempts. + +Successful acquisition carries checkout and registration identity through its lifetime; ordinary synchronization, observations and Failed run preservation share acquired-instance checks before and after every Git subprocess attempt, including retries, acting only on that acquired checkout and selected Issue branch and refusing changed or uncertain ownership. Failed run preservation retains work when ownership has changed or is uncertain and finishes after Command interruption without clearing it; ordinary synchronization remains interruptible. Confirmed Self-merge branch deletion uses the captured Launch repository independently of checkout validity. + +Cleanup checks stage-specific disposal authority before and after every destructive Git attempt, including retries: acquired identity and the captured cleanup head for checkout removal, removed-path absence and an unused expected head for local branch removal, then ref absence and the exact original local subsection for branch configuration removal. Only successful, verified transitions advance disposal; partial failures retain and name every remaining or uncertain resource. Live cleanup finishes after Command interruption without clearing it; stale disposal stays interruptible. + +Stale Architecture review scratch is disposable only with evidence of successful detached acquisition and unchanged ownership; unmarked or uncertain checkouts are retained. + +See [ADR-0014](adr/0014-successful-review-acquisition-authorizes-stale-disposal.md) for the ownership evidence that authorizes stale review disposal. + +### Delivery and pull request identity + +What a **Run**, or a **Spec run** for its **Spec PR**, does from its worktree once its work begins. It runs the opening session (the implement session, or the **Spec review**), pushes, marks the pull request ready, keeps it mergeable and green through the **Repair loop**, and, in a **Merge run**, does the **Self-merge**. + +For a Spec PR, Delivery ends Ticket accounting's capture before the Spec review, allowing that session to replace the PR. The first successful observation after the opening session, or during Failed run completion after an opening failure, captures one pull request number and URL in the issue's repository; all later observations and transitions use that identity. Readiness and every mergeability poll validate its expected **Issue branch** and **Base branch**, open state and readiness where required. A missing, closed or retargeted captured PR fails Delivery; a replacement from the same branch is never substituted. + +A Delivery that fails takes the **Failed run** path, drafting that same captured open PR after preserving work. Spec PR checklist restoration uses that Delivery capture before readiness and for final accounting after failure. + +If a Delivery gate observes that its pull request has already merged into the expected Base branch, and its merged head includes all local work (the exact local head, with no uncommitted changes), the Run ends as merged, even when it originally asked only for ready for review. Delivery stops further publication, PR edits and Self-merge work. A merged PR that leaves local work out still fails and retains that work; a merged state alone never establishes completion. + +### Check re-run allowance + +A **Check re-run** is allowed once per full head commit across one **Delivery**. The allowance is consumed before the request and stays consumed through green CI, **Inherited failures**, a **Base fix**, upstream moves, later Repair rounds and refused **Self-merge** reconciliation, even after visiting another head and returning. + +Later watches still obtain fresh CI facts. If the branch's own checks are red on a head whose allowance has been consumed, the Run ends as a **Declined CI fix** without another CI-fix Repair or Check re-run. A different head has its own allowance, and a separately started **Continuation** begins a new Delivery with fresh allowances. Inherited-only failures keep their usual handling. + +The trigger, eligible GitHub Actions checks, refusal handling and CI watching are described in step 6 above and [ADR-0010](adr/0010-one-check-re-run-before-a-declined-ci-fix.md). A Check re-run starts no Repair, counts against no Repair or upstream-move budget, and never re-runs a check for being an Inherited failure. + ### The Claim The **Claim** is the mark that the factory has taken an issue, so the issue list shows what it is working on. When a Run or a [Spec run](#spec-runs) starts on an issue, thirdshift labels the issue `in-progress`, in place of `ready-for-agent` if it has that. An issue with no `ready-for-agent` label still gets `in-progress`, so the label means the same thing however the Run was started. diff --git a/site/docs/index.html b/site/docs/index.html index 1c7bdb510..149ee9417 100644 --- a/site/docs/index.html +++ b/site/docs/index.html @@ -95,6 +95,28 @@
  • Cleans up: removes the worktree, the local Issue branch and the temporary directory the Factory skills were written out to, whether the Run succeeded or not. The one exception is a Failed run whose work could not be pushed: see below.

  • +

    Worktree ownership and cleanup

    +
    +

    A factory-owned checkout, on an Issue branch for a Run or detached for an Architecture review.

    +

    Acquisition accounts for partial local effects: failed-acquisition recovery rechecks clean-only, instance-specific authority before and after every destructive attempt, including retries, advances only on verified transitions, and retains and names remaining work or uncertain partial effects. Failed-acquisition retention survives later Architecture review attempts.

    +

    Successful acquisition carries checkout and registration identity through its lifetime; ordinary synchronization, observations and Failed run preservation share acquired-instance checks before and after every Git subprocess attempt, including retries, acting only on that acquired checkout and selected Issue branch and refusing changed or uncertain ownership. Failed run preservation retains work when ownership has changed or is uncertain and finishes after Command interruption without clearing it; ordinary synchronization remains interruptible. Confirmed Self-merge branch deletion uses the captured Launch repository independently of checkout validity.

    +

    Cleanup checks stage-specific disposal authority before and after every destructive Git attempt, including retries: acquired identity and the captured cleanup head for checkout removal, removed-path absence and an unused expected head for local branch removal, then ref absence and the exact original local subsection for branch configuration removal. Only successful, verified transitions advance disposal; partial failures retain and name every remaining or uncertain resource. Live cleanup finishes after Command interruption without clearing it; stale disposal stays interruptible.

    +

    Stale Architecture review scratch is disposable only with evidence of successful detached acquisition and unchanged ownership; unmarked or uncertain checkouts are retained.

    +

    See ADR-0014 for the ownership evidence that authorizes stale review disposal.

    +
    +

    Delivery and pull request identity

    +
    +

    What a Run, or a Spec run for its Spec PR, does from its worktree once its work begins. It runs the opening session (the implement session, or the Spec review), pushes, marks the pull request ready, keeps it mergeable and green through the Repair loop, and, in a Merge run, does the Self-merge.

    +

    For a Spec PR, Delivery ends Ticket accounting's capture before the Spec review, allowing that session to replace the PR. The first successful observation after the opening session, or during Failed run completion after an opening failure, captures one pull request number and URL in the issue's repository; all later observations and transitions use that identity. Readiness and every mergeability poll validate its expected Issue branch and Base branch, open state and readiness where required. A missing, closed or retargeted captured PR fails Delivery; a replacement from the same branch is never substituted.

    +

    A Delivery that fails takes the Failed run path, drafting that same captured open PR after preserving work. Spec PR checklist restoration uses that Delivery capture before readiness and for final accounting after failure.

    +

    If a Delivery gate observes that its pull request has already merged into the expected Base branch, and its merged head includes all local work (the exact local head, with no uncommitted changes), the Run ends as merged, even when it originally asked only for ready for review. Delivery stops further publication, PR edits and Self-merge work. A merged PR that leaves local work out still fails and retains that work; a merged state alone never establishes completion.

    +
    +

    Check re-run allowance

    +
    +

    A Check re-run is allowed once per full head commit across one Delivery. The allowance is consumed before the request and stays consumed through green CI, Inherited failures, a Base fix, upstream moves, later Repair rounds and refused Self-merge reconciliation, even after visiting another head and returning.

    +

    Later watches still obtain fresh CI facts. If the branch's own checks are red on a head whose allowance has been consumed, the Run ends as a Declined CI fix without another CI-fix Repair or Check re-run. A different head has its own allowance, and a separately started Continuation begins a new Delivery with fresh allowances. Inherited-only failures keep their usual handling.

    +

    The trigger, eligible GitHub Actions checks, refusal handling and CI watching are described in step 6 above and ADR-0010. A Check re-run starts no Repair, counts against no Repair or upstream-move budget, and never re-runs a check for being an Inherited failure.

    +

    The Claim

    The Claim is the mark that the factory has taken an issue, so the issue list shows what it is working on. When a Run or a Spec run starts on an issue, thirdshift labels the issue in-progress, in place of ready-for-agent if it has that. An issue with no ready-for-agent label still gets in-progress, so the label means the same thing however the Run was started.