Repository navigation
Commit 954148f
* F: publish a finished task's pull request in production (#103)
TaskPublishing (runner/publishing.ts) publishes the task's PR with the real
publisher: GhAlreadyFixedGateway, GhPullRequestGateway and a GitBranchPusher
that pushes from the runner-owned repository to the configured repository on
GH_HOST (never a configured URL), overwriting only ledger-owned commits.
- Mode by status: a running task whose plan items have all run gets a ready
PR; a task in needs human gets a draft PR with what sent it there.
- When: after a start/resume run ends; when a refused start/resume moves the
task to needs human; on the new `publish` runner action; once at startup,
after the CLI re-verifies the lock, if a publish is owed.
- Schema v10 `publish_outcomes`: the last outcome, shown as `publish` in
GET /api/runner and replayed by the publish action. Tasks already running
or in needs human at the upgrade are recorded as `not published`.
- Shutdown: publishes are aborted in step 1 and awaited before the Store
write gate closes. Start, resume and a second publish are refused while a
publish runs. Demos never publish.
- github.baseBranch is required with a runner block, checked before the lock.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* D: show a push left running by a crash is harmless; document it (#112)
A crashed or killed codeboost can leave its git push running, and nothing
records its process group. The push is leased to the branch value its own
run read, so it lands only while the branch still holds that value:
- before a newer publish reads the branch: read as codeboost's commit;
- between that read and its push: the newer push is refused as stale, and
the next publish moves on;
- after the newer publish moved the branch: the leftover is refused.
pushArguments is now the one place that builds the push, used by the pusher
and by tests that replay a leftover push against a real bare remote in each
order. Dropping the lease fails the two lease tests. The docs also cover a
branch that returns to the read value (moved back by a person, or the same
commit pushed again). No process group is recorded (decision on #112).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: review fixes for publishing (#103): finding before budget, one gh env, CLI test
- A draft PR's problems name the current attempt's safety finding before a
spent budget, so a budget that ran out later cannot hide the violation.
- The already-fixed and PR gateways take the setup's env, the same as the
push, so GH_HOST and credentials agree; recorded errors are redacted with
that env's token values (RunnerAssembly.env, TaskPublishing).
- A CLI test shows the startup publish runs after the lock is verified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* D: document and test a leftover push recreating a deleted branch (#112)
A run that read no branch pushes with an empty lease, which matches again
once a newer publish's branch has been deleted (by a person, or by GitHub
after the PR merged): the leftover recreates the branch at its own codeboost
head, with no PR, overwriting nothing. Copilot review on PR #116.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: settle a publish action whose process stopped before its outcome (#103)
The publish action's ID lived only in memory, so a crash after its
'publishing' reply committed and before the publish recorded an outcome
left the replay saying 'publishing' for ever. A reply that still says
'publishing' now counts as unsettled: any later outcome of the task
settles it (one publish runs per task), and startup settles it as
'stopped' (interrupted) when no publish is owed. Copilot review on PR #110.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: record every publish as in flight before it starts; settle a leftover record at startup (#103)
An automatic publish (after a run, at startup) had no durable in-flight
marker: a crash after its PR opened and moved the task to in review, but
before its outcome was written, left publish.last empty or stale for good,
since startup then saw nothing owed and no unsettled action. Every publish
now records 'publishing' before its first external call (and does not run
if that write fails); startup publishes again when one is owed and
otherwise settles a leftover 'publishing' record as 'stopped'. Copilot
review on PR #110 (previously missed finding).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: pay what an earlier run owes before publishing; check the github block before the lock (#103)
- A task whose earlier run owes a safety escalation or a scope pause (its
write failed, or the process stopped after the item settled) is not
finished work, but every item has run, so no later run would pay it and a
ready PR would show unreviewed out-of-scope changes. Publishing refuses it
(mode), and a run's end, startup and a refused publish action have the
executor pay it first (ItemExecutor.owes/payOwed).
- The CLI refuses a runner with no github block before taking the lock, so
the missing block is reported as itself, not as a lock conflict.
Copilot review on PR #110.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from an independent crash-point review of publishing (#103)
- A ready publish needs every item of the current plan revision completed
at that revision, checked in the Store's publish guard before every
guarded write: a revision that adds an item during a publish's first
GitHub lookups no longer gets a ready PR.
- Only a publish action refused because of owed work pays it; a refusal
for a stale view, a busy task or a replay starts nothing.
- A task recorded as 'not published' at the v10 upgrade stays unpublished
until a person asks, whatever changes since.
- A failure while paying owed work no longer stops startup from settling
an in-flight record or a stuck reply.
- A publish refused while a lost opening settles is retried at that
opening's deadline (settleRemaining).
- Startup settles a reply that is the only thing stuck with the outcome on
record, leaving that record (and its version stamp) as it is.
- The owed-work scan runs only for a status that could publish, not on
every poll.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from round 2 of the independent review of publishing (#103)
- A publish that ends with an opening still in flight (its own reply was
lost, not only a refusal while one settles) is retried at the opening's
deadline; a list-lag OpeningUnsettled is retried after 30 s.
- 'not published' (v10) holds only until a run starts after the upgrade.
- Only the publish action's own owed-work refusal pays that work; a stale
request or any replay applies nothing.
- A draft waits only for an owed safety finding, not an owed scope pause
(which a needs-human task cannot record).
- startup() leaves a publish of this process alone; the stopped record it
writes keeps the interrupted publish's draft flag; the retry decision
cannot throw out of run().
- owes() reads only owed findings in memory and completed out-of-scope
attempts (Store.scopeFindingHeads), not every attempt, on a poll.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from round 3 of the independent review of publishing (#103)
- Bound the automatic retry (AGENTS.md: back off recurring external
polling): one timer per task; a lost opening is waited for only while its
deadline is ahead, so one still stuck after it (two PRs carry its marker,
the repository changed, GitHub keeps failing) no longer re-publishes
every second; the list-lag retry runs once per chain.
- A person's start or resume that moves an upgraded task (v10 'not
published') ends that hold, so a refused resume that sends it to needs
human gets its draft.
- Owed work is paid only where a run would (running, queued) or a draft
waits on it (needs human).
- The 'not published' tests space their timestamps, which are compared.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from round 4 of the independent review of publishing (#103)
- Retry budget per chain (until a publish settles): at most one retry at a
lost opening's deadline and one short retry, so a GitHub outage that
fails every open no longer republishes every settle time for ever.
- An 'opened' outcome that left the PR or the task where the publish did
not mean them (GitHub showed another head, so the PR was drafted and the
task stayed running; a draft change failed) is recorded with
`reconcile`: still owed, and given the short retry.
- A refusal just as an opening's deadline passes gets the short retry.
- The short retry's delay is a test seam (RunnerAssembly.shortRetryMs);
tests now cover the list-lag retry, the outage bound and reconciling.
- Tests that proved less than they claimed: the owed-work failure test now
reaches the failure; the CLI baseBranch half holds the lock; the CLI
startup test stops only after the outcome is recorded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from round 5 of the independent review of publishing (#103)
- A run's end, a person's action or a restart starts a new retry chain with
its own budget (AGENTS.md: reset on a lifecycle change or user action);
a retry timer's own publish does not, so retries stay bounded.
- No short retry while a lost opening's deadline is still ahead (it would
only be refused again).
- `reconcile` only while the task can still be published; the action reply
carries it; the settleHead comment no longer overstates.
- The owed-work path of a refused publish action carries the person's
intent (personAsked), like start/resume.
- publishOwed runs the lock check itself, first: no order of the CLI's
lines can start a startup publish before the lock is verified.
- Tests: the one-short-retry bound, the new chain on a person's action, and
the lock check running first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from round 6 of the independent review of publishing (#103)
- A person's publish action drops a retry the old chain armed, so it cannot
fire later on the new chain's budget (at most two automatic publishes per
chain, not three).
- Tests for two round-5 fixes that no test covered: no reconcile for a task
that can no longer be published, and the action reply carrying reconcile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from round 7 of the independent review of publishing (#103)
- Tests for the owed-safety-finding gate: a ready publish is refused while
a finding is owed, the action pays it and the draft follows; a
needs-human task's owed finding is paid at startup before its draft; a
replay of that refusal pays nothing.
- The draft of a task whose owed finding was paid names that finding: the
executor settles it in memory only, so TaskPublishing keeps the reason
payOwed returned (it was lost before).
- A run's end starting a new chain drops the old chain's armed retry, as a
person's action does (#newChain): one timer per task, tested.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from round 8 of the independent review of publishing (#103)
A paid safety finding names a draft only while the task stays in needs
human on the same current attempt; a later return has its own reason.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* F: fixes from round 9 of the independent review of publishing (#103)
A publish refused by a guard (a race) gets the one short retry; a draft
names a finding whose save failed even after the budget ran out; a
needs-human task pays only an owed finding, not a scope pause.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent dddb9f6 commit 954148f
3 files changed
Lines changed: 83 additions & 6 deletions
File tree
- docs/implementation
- runner
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
139 | 151 | | |
140 | 152 | | |
141 | | - | |
| 153 | + | |
142 | 154 | | |
143 | 155 | | |
144 | 156 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
60 | 73 | | |
61 | 74 | | |
62 | 75 | | |
| |||
110 | 123 | | |
111 | 124 | | |
112 | 125 | | |
113 | | - | |
114 | | - | |
| 126 | + | |
115 | 127 | | |
116 | | - | |
117 | | - | |
| 128 | + | |
118 | 129 | | |
119 | 130 | | |
120 | 131 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| |||
109 | 109 | | |
110 | 110 | | |
111 | 111 | | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
112 | 166 | | |
113 | 167 | | |
114 | 168 | | |
| |||
0 commit comments