Releases: jhfnetboy/DevLoop
Release list
0.6.11
Release 0.6.11
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.11 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.11. This document is the release note, not a second semver.
New in 0.6.11
The DevLoop view closes the loop on everything it needs a second window
for: answering a blocked halt, registering a project, and cleaning up
branches and worktrees all moved in, and the "Open dashboard" button
that used to stand in for them is gone.
- Answer a blocked halt from the view (#158).
The question, its evidence, and the same retry/review/accept/stop
options the standalone page offers, read straight off theGate
object — now sent on the project list itself, not just the detail
fetch, since it was already computed on every read. - Register a project from the view (#159).
Browse one directory level at a time, pick a repository, add it —
the sameGET /api/browse/POST /api/projectsthe standalone
page's own picker uses, now inline. - Clean up branches and worktrees from the view (#160).
The same scan-and-plan the standalone page's repository panel reads,
with a checkbox per offered branch; the host rebuilds the plan fresh
at the moment of deleting regardless of what was shown. - The "Open dashboard" button is gone. With all three of the gaps it
stood in for closed, the view links out to the standalone page
nowhere. The sidebar launcher's own page fallback — for a profile
with no DevLoop tab to press at all — is unchanged.
New in 0.6.10
A native DevLoop view in the app itself, and elapsed time on whatever task
is running right now.
- A DevLoop tab beside Chat and Trajectory (#154).
The sidebar button only ever opened/devloop/in a window — DevLoop lived
beside the app, never in it. This renders the whole main view area instead:
every project with its lane, today's spend, task counts and halt reasons in
the loop's own words, Pause/Resume, and arming an unarmed root with a typed
goal. Same routes, same auth, same revision-guarded writes as the standalone
page; no new endpoint. The page itself remains, reachable from the sidebar
button, for what the view does not cover (goal gates, registering a
repository, cleanup). - Elapsed time on the task in progress (#155, #156).
Until now the dashboard only showed the last completed transition;
nothing said how long the current one had been running. EachProjectLoop
now tracks what it is dispatching, in memory, while a backend call is in
flight, and both surfaces (the standalone page and the new DevLoop tab) show
it as a "running Xm" chip, on the same 5-second refresh they already had.
New in 0.6.9
A native sidebar entry for DSH Desktop and the browser, and the loop writing
its own planning documents instead of pointing at a skill it cannot invoke.
- A sidebar button, composed from this one package (#149).
On a profile with a Harness chrome (a browser tab or DSH Desktop), an icon
in the sidebar footer opens/devloop/in a new window — no second package
to install, no decision to make. A headless profile never composes a client
bundle at all. Ported fromjhfnetboy/dsh-devloop-ui, the standalone
package that verified this was feasible before folding it in. - Writing the planning documents is the goal's first reviewed task (#150, #152).
The readiness panel used to point atpilot planfor missing planning
documents — a skill this loop's headless CLI-spawn architecture cannot
invoke. Whendocs/agent/(or.pilot.yml's configured directory) is
empty, the host now prepends a real task — "write the planning documents",
reviewed and merged through the normal worktree pipeline like any other —
before the planner's own tasks. Nothing writes docs unreviewed.
New in 0.6.8
A one-click fix for the readiness panel's most common block, and a worked
install example for people who aren't building from source.
- Create and switch to a work branch from the page (#146).
When the readiness panel blocks ontrunk.onTrunkorbranch.detached, it
now shows a name field and a button next to the failing check. It runs the
samegit switch -cthe check already names, refuses once the project is
armed (pausing the loop is what that's for), and refuses an unusable name,
the trunk itself, or a name already taken. New route:
POST /devloop/api/projects/<id>/branch. - npm install and a worked example in the README (#147).
A one-linedsh plugin --profile web add @jhfnetboy/dsh-devloop@0.6.8
install, and a fullcordis.patch.ymlfor the common setup this project
runs in production: Codex plans, DeepSeek Flash implements, Claude Opus
reviews locally, forge opens a PR per task.
New in 0.6.7
DeepSeek work defaults to DeepSeek V4.1 Flash, by the API id DeepSeek
published for it (notice of 2026-09-10) and DeepSeek Harness 0.1.5's own
default agent model: deepseek-flash.
- Default routes (#144).
routing.T1androuting.T2default todeepseek-flashinstead of
deepseek-v4-flash(deprecated, routed to V4.1 Flash for now) and
deepseek-v4-pro(served by V4.1 Flash from 2026-09-14 12:00 Beijing
time). A profile that names its routes is unchanged. - Prices (#143).
deepseek-flashis priced from the V4.1 Flash card;deepseek-v4-flash
anddeepseek-v4-proat the same card, each with a note saying why; all
are billed asdeepseek-flash. docs/Pricing.md lists the ids.
The model id passes through to DeepSeek's API, so dsh builds before 0.1.5
use deepseek-flash too (as a text-only route); dsh 0.1.5 adds its image
input and in-history system prompt updates.
New in 0.6.6
One repository, worked on goal after goal, every change reviewed. Found by
running 0.6.5 end to end on a live dashboard and a sandbox forge repository,
and shaped after LoopX, where a goal is long-lived and
finished work stays with it.
- The next goal on the same repository (#128–#131).
A finished project's page shows a "Next goal" box. The finished goal is
archived under.devloop/archive/NNNN/(GOAL, STATE, PLAN, REVIEW,
PROGRESS) under the state lock, and the next is planned on the same work
branch; spend carries over, per-task counters restart. Where the forge
merges, the next goal waits for the finished one's release to merge, its
task ids get ag<N>-prefix so its branches never meet an earlier goal's,
and its release is matched by number, never by an earlier goal's merge. - Each project pushes to its own forge repository (#132, #135, #136).
Before a registered project first starts on the forge route, the page shows
its checkout's origin (read withoutinsteadOf) for the operator to
confirm; it is kept in the project registry, never re-read from the
checkout, and the project's loop runs with it. Also fixes the forge route
failing to start when a profile never namedforge.localReview. - Mechanical checks fix before review (#133).
A commit the pre-PR checker blocks on a rule, or whose acceptance command
fails, goes back to the worker with what the check said, bounded by the
task's attempts; only size alone (split the task) or no verdict still asks
the operator. The PR record shows how many tasks passed their first review
(#139). - Safer with a repository that is already in use (#127, #137, #140).
A branch named for a task that holds other work is never reset: the task
holds and asks (task_branch_taken). A forge merge removes the task's
worktree..devloop/is added to the localinfo/exclude. Ahead/behind
is counted against the remote's trunk. - Say what the task is (#134, #138).
Task commits are<task id>: <title>; the task pull request lists the
contract's acceptance and allowed paths; the release links each task's
pull request.
New: .devloop/archive/, STATE goal and Task.pullRequest, registry
pushUrl, hold reason task_branch_taken, POST /api/projects/<id>/next.
Checked before release by a forge E2E in the sandbox: two goals in a row on
one work branch, four pull requests reviewed and merged by DevLoop.
New in 0.6.5
Hardening and polish of 0.6.4's per-task pull requests, from PR-daemon's
reviews of it. No new mode; local mode gains the git and credential fixes too.
- Models run without the host's credentials (#111).
Every worker, reviewer and planner (dsh, claude, codex) starts without any
inheritedGIT_*,GH_*,GITHUB_*or ...
0.6.10
Release 0.6.10
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.10 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.10. This document is the release note, not a second semver.
New in 0.6.10
A native DevLoop view in the app itself, and elapsed time on whatever task
is running right now.
- A DevLoop tab beside Chat and Trajectory (#154).
The sidebar button only ever opened/devloop/in a window — DevLoop lived
beside the app, never in it. This renders the whole main view area instead:
every project with its lane, today's spend, task counts and halt reasons in
the loop's own words, Pause/Resume, and arming an unarmed root with a typed
goal. Same routes, same auth, same revision-guarded writes as the standalone
page; no new endpoint. The page itself remains, reachable from the sidebar
button, for what the view does not cover (goal gates, registering a
repository, cleanup). - Elapsed time on the task in progress (#155, #156).
Until now the dashboard only showed the last completed transition;
nothing said how long the current one had been running. EachProjectLoop
now tracks what it is dispatching, in memory, while a backend call is in
flight, and both surfaces (the standalone page and the new DevLoop tab) show
it as a "running Xm" chip, on the same 5-second refresh they already had.
New in 0.6.9
A native sidebar entry for DSH Desktop and the browser, and the loop writing
its own planning documents instead of pointing at a skill it cannot invoke.
- A sidebar button, composed from this one package (#149).
On a profile with a Harness chrome (a browser tab or DSH Desktop), an icon
in the sidebar footer opens/devloop/in a new window — no second package
to install, no decision to make. A headless profile never composes a client
bundle at all. Ported fromjhfnetboy/dsh-devloop-ui, the standalone
package that verified this was feasible before folding it in. - Writing the planning documents is the goal's first reviewed task (#150, #152).
The readiness panel used to point atpilot planfor missing planning
documents — a skill this loop's headless CLI-spawn architecture cannot
invoke. Whendocs/agent/(or.pilot.yml's configured directory) is
empty, the host now prepends a real task — "write the planning documents",
reviewed and merged through the normal worktree pipeline like any other —
before the planner's own tasks. Nothing writes docs unreviewed.
New in 0.6.8
A one-click fix for the readiness panel's most common block, and a worked
install example for people who aren't building from source.
- Create and switch to a work branch from the page (#146).
When the readiness panel blocks ontrunk.onTrunkorbranch.detached, it
now shows a name field and a button next to the failing check. It runs the
samegit switch -cthe check already names, refuses once the project is
armed (pausing the loop is what that's for), and refuses an unusable name,
the trunk itself, or a name already taken. New route:
POST /devloop/api/projects/<id>/branch. - npm install and a worked example in the README (#147).
A one-linedsh plugin --profile web add @jhfnetboy/dsh-devloop@0.6.8
install, and a fullcordis.patch.ymlfor the common setup this project
runs in production: Codex plans, DeepSeek Flash implements, Claude Opus
reviews locally, forge opens a PR per task.
New in 0.6.7
DeepSeek work defaults to DeepSeek V4.1 Flash, by the API id DeepSeek
published for it (notice of 2026-09-10) and DeepSeek Harness 0.1.5's own
default agent model: deepseek-flash.
- Default routes (#144).
routing.T1androuting.T2default todeepseek-flashinstead of
deepseek-v4-flash(deprecated, routed to V4.1 Flash for now) and
deepseek-v4-pro(served by V4.1 Flash from 2026-09-14 12:00 Beijing
time). A profile that names its routes is unchanged. - Prices (#143).
deepseek-flashis priced from the V4.1 Flash card;deepseek-v4-flash
anddeepseek-v4-proat the same card, each with a note saying why; all
are billed asdeepseek-flash. docs/Pricing.md lists the ids.
The model id passes through to DeepSeek's API, so dsh builds before 0.1.5
use deepseek-flash too (as a text-only route); dsh 0.1.5 adds its image
input and in-history system prompt updates.
New in 0.6.6
One repository, worked on goal after goal, every change reviewed. Found by
running 0.6.5 end to end on a live dashboard and a sandbox forge repository,
and shaped after LoopX, where a goal is long-lived and
finished work stays with it.
- The next goal on the same repository (#128–#131).
A finished project's page shows a "Next goal" box. The finished goal is
archived under.devloop/archive/NNNN/(GOAL, STATE, PLAN, REVIEW,
PROGRESS) under the state lock, and the next is planned on the same work
branch; spend carries over, per-task counters restart. Where the forge
merges, the next goal waits for the finished one's release to merge, its
task ids get ag<N>-prefix so its branches never meet an earlier goal's,
and its release is matched by number, never by an earlier goal's merge. - Each project pushes to its own forge repository (#132, #135, #136).
Before a registered project first starts on the forge route, the page shows
its checkout's origin (read withoutinsteadOf) for the operator to
confirm; it is kept in the project registry, never re-read from the
checkout, and the project's loop runs with it. Also fixes the forge route
failing to start when a profile never namedforge.localReview. - Mechanical checks fix before review (#133).
A commit the pre-PR checker blocks on a rule, or whose acceptance command
fails, goes back to the worker with what the check said, bounded by the
task's attempts; only size alone (split the task) or no verdict still asks
the operator. The PR record shows how many tasks passed their first review
(#139). - Safer with a repository that is already in use (#127, #137, #140).
A branch named for a task that holds other work is never reset: the task
holds and asks (task_branch_taken). A forge merge removes the task's
worktree..devloop/is added to the localinfo/exclude. Ahead/behind
is counted against the remote's trunk. - Say what the task is (#134, #138).
Task commits are<task id>: <title>; the task pull request lists the
contract's acceptance and allowed paths; the release links each task's
pull request.
New: .devloop/archive/, STATE goal and Task.pullRequest, registry
pushUrl, hold reason task_branch_taken, POST /api/projects/<id>/next.
Checked before release by a forge E2E in the sandbox: two goals in a row on
one work branch, four pull requests reviewed and merged by DevLoop.
New in 0.6.5
Hardening and polish of 0.6.4's per-task pull requests, from PR-daemon's
reviews of it. No new mode; local mode gains the git and credential fixes too.
- Models run without the host's credentials (#111).
Every worker, reviewer and planner (dsh, claude, codex) starts without any
inheritedGIT_*,GH_*,GITHUB_*orSSH_*variable — git's numbered
GIT_CONFIG_KEY_n/VALUE_nincluded — withghpointed at an empty config
and git at no global or system config. dsh is pinned toworkspace-write.
A model's own sandbox is still what stops it reading credential files on disk. - Every host git through one hardened helper (#113, #114).
InheritedGIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_COMMON_DIRno
longer redirect it, fsmonitor and hooks are off; project registration and
the pre-PR checker included. - Checks you can require (#112, #123).
forge.requireChecks: truemakes a commit with no checks wait instead of
counting as green. Checks are read in the same call as the pull request's
head, so a later push cannot lend the reviewed commit its checks. - A forge refusal is its own question (#119, #124, #125).
Branch protection, an expiredghlogin or empty forge settings hold as
forge_merge_refused: fix it outside DevLoop and resume; the worker is not
run again. The checkout failing to follow the merge staysmerge_wedged;
a pull request pushed to or retargeted since revie...
0.6.9
Release 0.6.9
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.9 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.9. This document is the release note, not a second semver.
New in 0.6.9
A native sidebar entry for DSH Desktop and the browser, and the loop writing
its own planning documents instead of pointing at a skill it cannot invoke.
- A sidebar button, composed from this one package (#149).
On a profile with a Harness chrome (a browser tab or DSH Desktop), an icon
in the sidebar footer opens/devloop/in a new window — no second package
to install, no decision to make. A headless profile never composes a client
bundle at all. Ported fromjhfnetboy/dsh-devloop-ui, the standalone
package that verified this was feasible before folding it in. - Writing the planning documents is the goal's first reviewed task (#150, #152).
The readiness panel used to point atpilot planfor missing planning
documents — a skill this loop's headless CLI-spawn architecture cannot
invoke. Whendocs/agent/(or.pilot.yml's configured directory) is
empty, the host now prepends a real task — "write the planning documents",
reviewed and merged through the normal worktree pipeline like any other —
before the planner's own tasks. Nothing writes docs unreviewed.
New in 0.6.8
A one-click fix for the readiness panel's most common block, and a worked
install example for people who aren't building from source.
- Create and switch to a work branch from the page (#146).
When the readiness panel blocks ontrunk.onTrunkorbranch.detached, it
now shows a name field and a button next to the failing check. It runs the
samegit switch -cthe check already names, refuses once the project is
armed (pausing the loop is what that's for), and refuses an unusable name,
the trunk itself, or a name already taken. New route:
POST /devloop/api/projects/<id>/branch. - npm install and a worked example in the README (#147).
A one-linedsh plugin --profile web add @jhfnetboy/dsh-devloop@0.6.8
install, and a fullcordis.patch.ymlfor the common setup this project
runs in production: Codex plans, DeepSeek Flash implements, Claude Opus
reviews locally, forge opens a PR per task.
New in 0.6.7
DeepSeek work defaults to DeepSeek V4.1 Flash, by the API id DeepSeek
published for it (notice of 2026-09-10) and DeepSeek Harness 0.1.5's own
default agent model: deepseek-flash.
- Default routes (#144).
routing.T1androuting.T2default todeepseek-flashinstead of
deepseek-v4-flash(deprecated, routed to V4.1 Flash for now) and
deepseek-v4-pro(served by V4.1 Flash from 2026-09-14 12:00 Beijing
time). A profile that names its routes is unchanged. - Prices (#143).
deepseek-flashis priced from the V4.1 Flash card;deepseek-v4-flash
anddeepseek-v4-proat the same card, each with a note saying why; all
are billed asdeepseek-flash. docs/Pricing.md lists the ids.
The model id passes through to DeepSeek's API, so dsh builds before 0.1.5
use deepseek-flash too (as a text-only route); dsh 0.1.5 adds its image
input and in-history system prompt updates.
New in 0.6.6
One repository, worked on goal after goal, every change reviewed. Found by
running 0.6.5 end to end on a live dashboard and a sandbox forge repository,
and shaped after LoopX, where a goal is long-lived and
finished work stays with it.
- The next goal on the same repository (#128–#131).
A finished project's page shows a "Next goal" box. The finished goal is
archived under.devloop/archive/NNNN/(GOAL, STATE, PLAN, REVIEW,
PROGRESS) under the state lock, and the next is planned on the same work
branch; spend carries over, per-task counters restart. Where the forge
merges, the next goal waits for the finished one's release to merge, its
task ids get ag<N>-prefix so its branches never meet an earlier goal's,
and its release is matched by number, never by an earlier goal's merge. - Each project pushes to its own forge repository (#132, #135, #136).
Before a registered project first starts on the forge route, the page shows
its checkout's origin (read withoutinsteadOf) for the operator to
confirm; it is kept in the project registry, never re-read from the
checkout, and the project's loop runs with it. Also fixes the forge route
failing to start when a profile never namedforge.localReview. - Mechanical checks fix before review (#133).
A commit the pre-PR checker blocks on a rule, or whose acceptance command
fails, goes back to the worker with what the check said, bounded by the
task's attempts; only size alone (split the task) or no verdict still asks
the operator. The PR record shows how many tasks passed their first review
(#139). - Safer with a repository that is already in use (#127, #137, #140).
A branch named for a task that holds other work is never reset: the task
holds and asks (task_branch_taken). A forge merge removes the task's
worktree..devloop/is added to the localinfo/exclude. Ahead/behind
is counted against the remote's trunk. - Say what the task is (#134, #138).
Task commits are<task id>: <title>; the task pull request lists the
contract's acceptance and allowed paths; the release links each task's
pull request.
New: .devloop/archive/, STATE goal and Task.pullRequest, registry
pushUrl, hold reason task_branch_taken, POST /api/projects/<id>/next.
Checked before release by a forge E2E in the sandbox: two goals in a row on
one work branch, four pull requests reviewed and merged by DevLoop.
New in 0.6.5
Hardening and polish of 0.6.4's per-task pull requests, from PR-daemon's
reviews of it. No new mode; local mode gains the git and credential fixes too.
- Models run without the host's credentials (#111).
Every worker, reviewer and planner (dsh, claude, codex) starts without any
inheritedGIT_*,GH_*,GITHUB_*orSSH_*variable — git's numbered
GIT_CONFIG_KEY_n/VALUE_nincluded — withghpointed at an empty config
and git at no global or system config. dsh is pinned toworkspace-write.
A model's own sandbox is still what stops it reading credential files on disk. - Every host git through one hardened helper (#113, #114).
InheritedGIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_COMMON_DIRno
longer redirect it, fsmonitor and hooks are off; project registration and
the pre-PR checker included. - Checks you can require (#112, #123).
forge.requireChecks: truemakes a commit with no checks wait instead of
counting as green. Checks are read in the same call as the pull request's
head, so a later push cannot lend the reviewed commit its checks. - A forge refusal is its own question (#119, #124, #125).
Branch protection, an expiredghlogin or empty forge settings hold as
forge_merge_refused: fix it outside DevLoop and resume; the worker is not
run again. The checkout failing to follow the merge staysmerge_wedged;
a pull request pushed to or retargeted since review holds as
no_review_pass, to be reviewed again. - Gates and bodies that say what happens (#114, #117, #120, #121, #122).
The release body says how it is decided (a GitHub review, always) and marks
tasks accepted without a change; a trunk or detached checkout held before
review no longer says the task "passed review"; a superseded trunk pull
request is closed; a task merged by someone else is logged as a warning. - Review notes (#115, #116, #118).
A local reviewer's long notes are cut at 8192 characters instead of stopping
the loop; the PR log names the local reviewer.
New config: forge.requireChecks (default false). New hold reason:
forge_merge_refused (the only new value STATE can hold). New PR-LOG field:
localReviewer.
Not in 0.6.5: automatic retry of transient forge merge errors (gh gives no
signal to tell them from refusals).
New in 0.6.4
One GitHub pull request per task,...
0.6.8
Release 0.6.8
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.8 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.8. This document is the release note, not a second semver.
New in 0.6.8
A one-click fix for the readiness panel's most common block, and a worked
install example for people who aren't building from source.
- Create and switch to a work branch from the page (#146).
When the readiness panel blocks ontrunk.onTrunkorbranch.detached, it
now shows a name field and a button next to the failing check. It runs the
samegit switch -cthe check already names, refuses once the project is
armed (pausing the loop is what that's for), and refuses an unusable name,
the trunk itself, or a name already taken. New route:
POST /devloop/api/projects/<id>/branch. - npm install and a worked example in the README (#147).
A one-linedsh plugin --profile web add @jhfnetboy/dsh-devloop@0.6.8
install, and a fullcordis.patch.ymlfor the common setup this project
runs in production: Codex plans, DeepSeek Flash implements, Claude Opus
reviews locally, forge opens a PR per task.
New in 0.6.7
DeepSeek work defaults to DeepSeek V4.1 Flash, by the API id DeepSeek
published for it (notice of 2026-09-10) and DeepSeek Harness 0.1.5's own
default agent model: deepseek-flash.
- Default routes (#144).
routing.T1androuting.T2default todeepseek-flashinstead of
deepseek-v4-flash(deprecated, routed to V4.1 Flash for now) and
deepseek-v4-pro(served by V4.1 Flash from 2026-09-14 12:00 Beijing
time). A profile that names its routes is unchanged. - Prices (#143).
deepseek-flashis priced from the V4.1 Flash card;deepseek-v4-flash
anddeepseek-v4-proat the same card, each with a note saying why; all
are billed asdeepseek-flash. docs/Pricing.md lists the ids.
The model id passes through to DeepSeek's API, so dsh builds before 0.1.5
use deepseek-flash too (as a text-only route); dsh 0.1.5 adds its image
input and in-history system prompt updates.
New in 0.6.6
One repository, worked on goal after goal, every change reviewed. Found by
running 0.6.5 end to end on a live dashboard and a sandbox forge repository,
and shaped after LoopX, where a goal is long-lived and
finished work stays with it.
- The next goal on the same repository (#128–#131).
A finished project's page shows a "Next goal" box. The finished goal is
archived under.devloop/archive/NNNN/(GOAL, STATE, PLAN, REVIEW,
PROGRESS) under the state lock, and the next is planned on the same work
branch; spend carries over, per-task counters restart. Where the forge
merges, the next goal waits for the finished one's release to merge, its
task ids get ag<N>-prefix so its branches never meet an earlier goal's,
and its release is matched by number, never by an earlier goal's merge. - Each project pushes to its own forge repository (#132, #135, #136).
Before a registered project first starts on the forge route, the page shows
its checkout's origin (read withoutinsteadOf) for the operator to
confirm; it is kept in the project registry, never re-read from the
checkout, and the project's loop runs with it. Also fixes the forge route
failing to start when a profile never namedforge.localReview. - Mechanical checks fix before review (#133).
A commit the pre-PR checker blocks on a rule, or whose acceptance command
fails, goes back to the worker with what the check said, bounded by the
task's attempts; only size alone (split the task) or no verdict still asks
the operator. The PR record shows how many tasks passed their first review
(#139). - Safer with a repository that is already in use (#127, #137, #140).
A branch named for a task that holds other work is never reset: the task
holds and asks (task_branch_taken). A forge merge removes the task's
worktree..devloop/is added to the localinfo/exclude. Ahead/behind
is counted against the remote's trunk. - Say what the task is (#134, #138).
Task commits are<task id>: <title>; the task pull request lists the
contract's acceptance and allowed paths; the release links each task's
pull request.
New: .devloop/archive/, STATE goal and Task.pullRequest, registry
pushUrl, hold reason task_branch_taken, POST /api/projects/<id>/next.
Checked before release by a forge E2E in the sandbox: two goals in a row on
one work branch, four pull requests reviewed and merged by DevLoop.
New in 0.6.5
Hardening and polish of 0.6.4's per-task pull requests, from PR-daemon's
reviews of it. No new mode; local mode gains the git and credential fixes too.
- Models run without the host's credentials (#111).
Every worker, reviewer and planner (dsh, claude, codex) starts without any
inheritedGIT_*,GH_*,GITHUB_*orSSH_*variable — git's numbered
GIT_CONFIG_KEY_n/VALUE_nincluded — withghpointed at an empty config
and git at no global or system config. dsh is pinned toworkspace-write.
A model's own sandbox is still what stops it reading credential files on disk. - Every host git through one hardened helper (#113, #114).
InheritedGIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_COMMON_DIRno
longer redirect it, fsmonitor and hooks are off; project registration and
the pre-PR checker included. - Checks you can require (#112, #123).
forge.requireChecks: truemakes a commit with no checks wait instead of
counting as green. Checks are read in the same call as the pull request's
head, so a later push cannot lend the reviewed commit its checks. - A forge refusal is its own question (#119, #124, #125).
Branch protection, an expiredghlogin or empty forge settings hold as
forge_merge_refused: fix it outside DevLoop and resume; the worker is not
run again. The checkout failing to follow the merge staysmerge_wedged;
a pull request pushed to or retargeted since review holds as
no_review_pass, to be reviewed again. - Gates and bodies that say what happens (#114, #117, #120, #121, #122).
The release body says how it is decided (a GitHub review, always) and marks
tasks accepted without a change; a trunk or detached checkout held before
review no longer says the task "passed review"; a superseded trunk pull
request is closed; a task merged by someone else is logged as a warning. - Review notes (#115, #116, #118).
A local reviewer's long notes are cut at 8192 characters instead of stopping
the loop; the PR log names the local reviewer.
New config: forge.requireChecks (default false). New hold reason:
forge_merge_refused (the only new value STATE can hold). New PR-LOG field:
localReviewer.
Not in 0.6.5: automatic retry of transient forge merge errors (gh gives no
signal to tell them from refusals).
New in 0.6.4
One GitHub pull request per task, reviewed there and merged by DevLoop, then
one release pull request to trunk: the per-task review the 0.6 design set
out, run end to end in a sandbox repository before release. Off unless
reviewerRoute names the forge backend; without it tasks merge locally as
before. How to turn it on: README, "One pull request per task".
- Verdicts from GitHub reviews (#93, #98).
Only allowlisted reviewers who are not this host, only reviews of exactly the
reviewed commit, each reviewer's latest word; any request for changes
outranks every approval and is rework. An approval passes only once the
commit's checks are green.forge.verdictSource: commentskeeps the old
envelope path; exactly one source is read. - Rework carries the review (#95, #96, #105, #106).
A request for changes' body — PR-daemon's, or the local reviewer's — reaches
the worker's next attempt, as one quoted string, and survives a failed or
blocked attempt; it is dropped once an attempt ...
0.6.7
Release 0.6.7
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.7 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.7. This document is the release note, not a second semver.
New in 0.6.7
DeepSeek work defaults to DeepSeek V4.1 Flash, by the API id DeepSeek
published for it (notice of 2026-09-10) and DeepSeek Harness 0.1.5's own
default agent model: deepseek-flash.
- Default routes (#144).
routing.T1androuting.T2default todeepseek-flashinstead of
deepseek-v4-flash(deprecated, routed to V4.1 Flash for now) and
deepseek-v4-pro(served by V4.1 Flash from 2026-09-14 12:00 Beijing
time). A profile that names its routes is unchanged. - Prices (#143).
deepseek-flashis priced from the V4.1 Flash card;deepseek-v4-flash
anddeepseek-v4-proat the same card, each with a note saying why; all
are billed asdeepseek-flash. docs/Pricing.md lists the ids.
The model id passes through to DeepSeek's API, so dsh builds before 0.1.5
use deepseek-flash too (as a text-only route); dsh 0.1.5 adds its image
input and in-history system prompt updates.
New in 0.6.6
One repository, worked on goal after goal, every change reviewed. Found by
running 0.6.5 end to end on a live dashboard and a sandbox forge repository,
and shaped after LoopX, where a goal is long-lived and
finished work stays with it.
- The next goal on the same repository (#128–#131).
A finished project's page shows a "Next goal" box. The finished goal is
archived under.devloop/archive/NNNN/(GOAL, STATE, PLAN, REVIEW,
PROGRESS) under the state lock, and the next is planned on the same work
branch; spend carries over, per-task counters restart. Where the forge
merges, the next goal waits for the finished one's release to merge, its
task ids get ag<N>-prefix so its branches never meet an earlier goal's,
and its release is matched by number, never by an earlier goal's merge. - Each project pushes to its own forge repository (#132, #135, #136).
Before a registered project first starts on the forge route, the page shows
its checkout's origin (read withoutinsteadOf) for the operator to
confirm; it is kept in the project registry, never re-read from the
checkout, and the project's loop runs with it. Also fixes the forge route
failing to start when a profile never namedforge.localReview. - Mechanical checks fix before review (#133).
A commit the pre-PR checker blocks on a rule, or whose acceptance command
fails, goes back to the worker with what the check said, bounded by the
task's attempts; only size alone (split the task) or no verdict still asks
the operator. The PR record shows how many tasks passed their first review
(#139). - Safer with a repository that is already in use (#127, #137, #140).
A branch named for a task that holds other work is never reset: the task
holds and asks (task_branch_taken). A forge merge removes the task's
worktree..devloop/is added to the localinfo/exclude. Ahead/behind
is counted against the remote's trunk. - Say what the task is (#134, #138).
Task commits are<task id>: <title>; the task pull request lists the
contract's acceptance and allowed paths; the release links each task's
pull request.
New: .devloop/archive/, STATE goal and Task.pullRequest, registry
pushUrl, hold reason task_branch_taken, POST /api/projects/<id>/next.
Checked before release by a forge E2E in the sandbox: two goals in a row on
one work branch, four pull requests reviewed and merged by DevLoop.
New in 0.6.5
Hardening and polish of 0.6.4's per-task pull requests, from PR-daemon's
reviews of it. No new mode; local mode gains the git and credential fixes too.
- Models run without the host's credentials (#111).
Every worker, reviewer and planner (dsh, claude, codex) starts without any
inheritedGIT_*,GH_*,GITHUB_*orSSH_*variable — git's numbered
GIT_CONFIG_KEY_n/VALUE_nincluded — withghpointed at an empty config
and git at no global or system config. dsh is pinned toworkspace-write.
A model's own sandbox is still what stops it reading credential files on disk. - Every host git through one hardened helper (#113, #114).
InheritedGIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_COMMON_DIRno
longer redirect it, fsmonitor and hooks are off; project registration and
the pre-PR checker included. - Checks you can require (#112, #123).
forge.requireChecks: truemakes a commit with no checks wait instead of
counting as green. Checks are read in the same call as the pull request's
head, so a later push cannot lend the reviewed commit its checks. - A forge refusal is its own question (#119, #124, #125).
Branch protection, an expiredghlogin or empty forge settings hold as
forge_merge_refused: fix it outside DevLoop and resume; the worker is not
run again. The checkout failing to follow the merge staysmerge_wedged;
a pull request pushed to or retargeted since review holds as
no_review_pass, to be reviewed again. - Gates and bodies that say what happens (#114, #117, #120, #121, #122).
The release body says how it is decided (a GitHub review, always) and marks
tasks accepted without a change; a trunk or detached checkout held before
review no longer says the task "passed review"; a superseded trunk pull
request is closed; a task merged by someone else is logged as a warning. - Review notes (#115, #116, #118).
A local reviewer's long notes are cut at 8192 characters instead of stopping
the loop; the PR log names the local reviewer.
New config: forge.requireChecks (default false). New hold reason:
forge_merge_refused (the only new value STATE can hold). New PR-LOG field:
localReviewer.
Not in 0.6.5: automatic retry of transient forge merge errors (gh gives no
signal to tell them from refusals).
New in 0.6.4
One GitHub pull request per task, reviewed there and merged by DevLoop, then
one release pull request to trunk: the per-task review the 0.6 design set
out, run end to end in a sandbox repository before release. Off unless
reviewerRoute names the forge backend; without it tasks merge locally as
before. How to turn it on: README, "One pull request per task".
- Verdicts from GitHub reviews (#93, #98).
Only allowlisted reviewers who are not this host, only reviews of exactly the
reviewed commit, each reviewer's latest word; any request for changes
outranks every approval and is rework. An approval passes only once the
commit's checks are green.forge.verdictSource: commentskeeps the old
envelope path; exactly one source is read. - Rework carries the review (#95, #96, #105, #106).
A request for changes' body — PR-daemon's, or the local reviewer's — reaches
the worker's next attempt, as one quoted string, and survives a failed or
blocked attempt; it is dropped once an attempt is handed in or the task is
accepted. - The work branch (#94, #97, #107).
Recorded at the first delegate; task pull requests target it, labelled
devloop, never trunk. It is created on the forge at the task's base,
fast-forwarded when behind, left alone when ahead, refused when moved away;
a review with no work branch holds on trunk or detached instead of opening a
pull request. - A local review first (#99).
forge.localReviewruns a local reviewer before the pull request opens, and
its usage counts toward the caps. - DevLoop merges (#100–#102).
The verdict and checks are read again, thengh pr merge --match-head-commit
from an empty directory; the checkout fetches the merge commit by id and
fast-forwards to it b...
0.6.6
Release 0.6.6
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.6 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.6. This document is the release note, not a second semver.
New in 0.6.6
One repository, worked on goal after goal, every change reviewed. Found by
running 0.6.5 end to end on a live dashboard and a sandbox forge repository,
and shaped after LoopX, where a goal is long-lived and
finished work stays with it.
- The next goal on the same repository (#128–#131).
A finished project's page shows a "Next goal" box. The finished goal is
archived under.devloop/archive/NNNN/(GOAL, STATE, PLAN, REVIEW,
PROGRESS) under the state lock, and the next is planned on the same work
branch; spend carries over, per-task counters restart. Where the forge
merges, the next goal waits for the finished one's release to merge, its
task ids get ag<N>-prefix so its branches never meet an earlier goal's,
and its release is matched by number, never by an earlier goal's merge. - Each project pushes to its own forge repository (#132, #135, #136).
Before a registered project first starts on the forge route, the page shows
its checkout's origin (read withoutinsteadOf) for the operator to
confirm; it is kept in the project registry, never re-read from the
checkout, and the project's loop runs with it. Also fixes the forge route
failing to start when a profile never namedforge.localReview. - Mechanical checks fix before review (#133).
A commit the pre-PR checker blocks on a rule, or whose acceptance command
fails, goes back to the worker with what the check said, bounded by the
task's attempts; only size alone (split the task) or no verdict still asks
the operator. The PR record shows how many tasks passed their first review
(#139). - Safer with a repository that is already in use (#127, #137, #140).
A branch named for a task that holds other work is never reset: the task
holds and asks (task_branch_taken). A forge merge removes the task's
worktree..devloop/is added to the localinfo/exclude. Ahead/behind
is counted against the remote's trunk. - Say what the task is (#134, #138).
Task commits are<task id>: <title>; the task pull request lists the
contract's acceptance and allowed paths; the release links each task's
pull request.
New: .devloop/archive/, STATE goal and Task.pullRequest, registry
pushUrl, hold reason task_branch_taken, POST /api/projects/<id>/next.
Checked before release by a forge E2E in the sandbox: two goals in a row on
one work branch, four pull requests reviewed and merged by DevLoop.
New in 0.6.5
Hardening and polish of 0.6.4's per-task pull requests, from PR-daemon's
reviews of it. No new mode; local mode gains the git and credential fixes too.
- Models run without the host's credentials (#111).
Every worker, reviewer and planner (dsh, claude, codex) starts without any
inheritedGIT_*,GH_*,GITHUB_*orSSH_*variable — git's numbered
GIT_CONFIG_KEY_n/VALUE_nincluded — withghpointed at an empty config
and git at no global or system config. dsh is pinned toworkspace-write.
A model's own sandbox is still what stops it reading credential files on disk. - Every host git through one hardened helper (#113, #114).
InheritedGIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_COMMON_DIRno
longer redirect it, fsmonitor and hooks are off; project registration and
the pre-PR checker included. - Checks you can require (#112, #123).
forge.requireChecks: truemakes a commit with no checks wait instead of
counting as green. Checks are read in the same call as the pull request's
head, so a later push cannot lend the reviewed commit its checks. - A forge refusal is its own question (#119, #124, #125).
Branch protection, an expiredghlogin or empty forge settings hold as
forge_merge_refused: fix it outside DevLoop and resume; the worker is not
run again. The checkout failing to follow the merge staysmerge_wedged;
a pull request pushed to or retargeted since review holds as
no_review_pass, to be reviewed again. - Gates and bodies that say what happens (#114, #117, #120, #121, #122).
The release body says how it is decided (a GitHub review, always) and marks
tasks accepted without a change; a trunk or detached checkout held before
review no longer says the task "passed review"; a superseded trunk pull
request is closed; a task merged by someone else is logged as a warning. - Review notes (#115, #116, #118).
A local reviewer's long notes are cut at 8192 characters instead of stopping
the loop; the PR log names the local reviewer.
New config: forge.requireChecks (default false). New hold reason:
forge_merge_refused (the only new value STATE can hold). New PR-LOG field:
localReviewer.
Not in 0.6.5: automatic retry of transient forge merge errors (gh gives no
signal to tell them from refusals).
New in 0.6.4
One GitHub pull request per task, reviewed there and merged by DevLoop, then
one release pull request to trunk: the per-task review the 0.6 design set
out, run end to end in a sandbox repository before release. Off unless
reviewerRoute names the forge backend; without it tasks merge locally as
before. How to turn it on: README, "One pull request per task".
- Verdicts from GitHub reviews (#93, #98).
Only allowlisted reviewers who are not this host, only reviews of exactly the
reviewed commit, each reviewer's latest word; any request for changes
outranks every approval and is rework. An approval passes only once the
commit's checks are green.forge.verdictSource: commentskeeps the old
envelope path; exactly one source is read. - Rework carries the review (#95, #96, #105, #106).
A request for changes' body — PR-daemon's, or the local reviewer's — reaches
the worker's next attempt, as one quoted string, and survives a failed or
blocked attempt; it is dropped once an attempt is handed in or the task is
accepted. - The work branch (#94, #97, #107).
Recorded at the first delegate; task pull requests target it, labelled
devloop, never trunk. It is created on the forge at the task's base,
fast-forwarded when behind, left alone when ahead, refused when moved away;
a review with no work branch holds on trunk or detached instead of opening a
pull request. - A local review first (#99).
forge.localReviewruns a local reviewer before the pull request opens, and
its usage counts toward the caps. - DevLoop merges (#100–#102).
The verdict and checks are read again, thengh pr merge --match-head-commit
from an empty directory; the checkout fetches the merge commit by id and
fast-forwards to it before the task is done. Already merged is not merged
twice; anything that cannot be completed holds. - The release pull request (#103, #104).
Opened once every task is done, looked at each tick outside the state lock,
merged once approved with green checks, on the forge only. - Security fix: a worker could run a program as the host through git
(#108). Found by PR-daemon's
review. The Codex delegate was granted its worktree's gitdir, and any worker
could rewrite its worktree's.gitpointer; either could point the host's
next git call — committing the task, the pre-PR checker, the repository
status scan — at a repository whose config runs a program. Codex no longer
gets the gitdir, and every host git call in a task worktree pins its git
directories to the host's own paths with fsmonitor and hooks off. This
predates 0.6.4 and affects local ...
0.6.5
Release 0.6.5
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.5 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.5. This document is the release note, not a second semver.
New in 0.6.5
Hardening and polish of 0.6.4's per-task pull requests, from PR-daemon's
reviews of it. No new mode; local mode gains the git and credential fixes too.
- Models run without the host's credentials (#111).
Every worker, reviewer and planner (dsh, claude, codex) starts without any
inheritedGIT_*,GH_*,GITHUB_*orSSH_*variable — git's numbered
GIT_CONFIG_KEY_n/VALUE_nincluded — withghpointed at an empty config
and git at no global or system config. dsh is pinned toworkspace-write.
A model's own sandbox is still what stops it reading credential files on disk. - Every host git through one hardened helper (#113, #114).
InheritedGIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_COMMON_DIRno
longer redirect it, fsmonitor and hooks are off; project registration and
the pre-PR checker included. - Checks you can require (#112, #123).
forge.requireChecks: truemakes a commit with no checks wait instead of
counting as green. Checks are read in the same call as the pull request's
head, so a later push cannot lend the reviewed commit its checks. - A forge refusal is its own question (#119, #124, #125).
Branch protection, an expiredghlogin or empty forge settings hold as
forge_merge_refused: fix it outside DevLoop and resume; the worker is not
run again. The checkout failing to follow the merge staysmerge_wedged;
a pull request pushed to or retargeted since review holds as
no_review_pass, to be reviewed again. - Gates and bodies that say what happens (#114, #117, #120, #121, #122).
The release body says how it is decided (a GitHub review, always) and marks
tasks accepted without a change; a trunk or detached checkout held before
review no longer says the task "passed review"; a superseded trunk pull
request is closed; a task merged by someone else is logged as a warning. - Review notes (#115, #116, #118).
A local reviewer's long notes are cut at 8192 characters instead of stopping
the loop; the PR log names the local reviewer.
New config: forge.requireChecks (default false). New hold reason:
forge_merge_refused (the only new value STATE can hold). New PR-LOG field:
localReviewer.
Not in 0.6.5: automatic retry of transient forge merge errors (gh gives no
signal to tell them from refusals).
New in 0.6.4
One GitHub pull request per task, reviewed there and merged by DevLoop, then
one release pull request to trunk: the per-task review the 0.6 design set
out, run end to end in a sandbox repository before release. Off unless
reviewerRoute names the forge backend; without it tasks merge locally as
before. How to turn it on: README, "One pull request per task".
- Verdicts from GitHub reviews (#93, #98).
Only allowlisted reviewers who are not this host, only reviews of exactly the
reviewed commit, each reviewer's latest word; any request for changes
outranks every approval and is rework. An approval passes only once the
commit's checks are green.forge.verdictSource: commentskeeps the old
envelope path; exactly one source is read. - Rework carries the review (#95, #96, #105, #106).
A request for changes' body — PR-daemon's, or the local reviewer's — reaches
the worker's next attempt, as one quoted string, and survives a failed or
blocked attempt; it is dropped once an attempt is handed in or the task is
accepted. - The work branch (#94, #97, #107).
Recorded at the first delegate; task pull requests target it, labelled
devloop, never trunk. It is created on the forge at the task's base,
fast-forwarded when behind, left alone when ahead, refused when moved away;
a review with no work branch holds on trunk or detached instead of opening a
pull request. - A local review first (#99).
forge.localReviewruns a local reviewer before the pull request opens, and
its usage counts toward the caps. - DevLoop merges (#100–#102).
The verdict and checks are read again, thengh pr merge --match-head-commit
from an empty directory; the checkout fetches the merge commit by id and
fast-forwards to it before the task is done. Already merged is not merged
twice; anything that cannot be completed holds. - The release pull request (#103, #104).
Opened once every task is done, looked at each tick outside the state lock,
merged once approved with green checks, on the forge only. - Security fix: a worker could run a program as the host through git
(#108). Found by PR-daemon's
review. The Codex delegate was granted its worktree's gitdir, and any worker
could rewrite its worktree's.gitpointer; either could point the host's
next git call — committing the task, the pre-PR checker, the repository
status scan — at a repository whose config runs a program. Codex no longer
gets the gitdir, and every host git call in a task worktree pins its git
directories to the host's own paths with fsmonitor and hooks off. This
predates 0.6.4 and affects local mode too.
Carried to 0.6.5 (from the reviews), and closed there: workers inherited this
host's gh login; an empty set of checks counted as green; a few messages and
gate texts to tighten. 0.6.x numbers follow the release plan rather than strict semver.
New in 0.6.3
The page speaks English, Chinese and Thai. A switch at the top right
(EN · 中 · ไทย) changes every word the page draws, in place, and is
remembered on that browser; English is the default.
- The page's own words (#77–#82).
dashboard/i18n.jsholds each string as[English, 中文, ไทย], served at
/devloop/i18n.jsbehind the page's authentication. Headers, the home
lanes, cards, the start panel, the gate and halt panels, tasks, budget,
events, documents, the guide, repository status and the PR record all go
through it; times use the reader's locale (Thai dates show the Buddhist
year). A missing translation falls back to English and an unknown key
shows as itself. - What the server says, by code (#83–#90).
Readiness checks, cleanup reasons, protect_patterns warnings, every gate's
question, evidence and steps, and the halt reasons now carry a stable code
and the values their sentence uses; the page says them in the reader's
language and falls back to the server's own words for a code it does not
know. The CLI and the server's messages are unchanged. - Tests keep it whole. Every key the page asks for, every code the server
can send and every gate family ingate.tsmust have all three languages;
a key defined twice fails the suite. - Fix: a saved language is taken only when it is one of the three by own
property (a storedconstructorused to break every date on the page).
Not translated, on purpose: what models and people wrote (task titles,
GOAL.md, planning documents) and raw identifiers (reason codes, commands,
branch names).
New fields: readiness code/params, cleanup code, ProtectDrop.code,
gate key/vars, halt details (haltDetails on a project). No config or
STATE change. 0.6.x numbers follow the release plan rather than strict
semver.
New in 0.6.2
The page answers "what needs me?" first, and says what an answer costs before
it is given. Both ideas are borrowed from LoopX's control plane.
- The home page is grouped by attention (#71, #72, #74).
Four columns, in this order: 等你处理 (a halt asking a question, a project
the page cannot read, an armed loop whose process has stopped), 进行中, 闲置
(not started, paused, or a halt answered "leave it" while it is still that
halt), 已完成. Once there are projects they come before the guide and the
picker. Each card says in one sentence what happens next or what it waits
for, and h...
0.6.4
Release 0.6.4
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.4 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.4. This document is the release note, not a second semver.
New in 0.6.4
One GitHub pull request per task, reviewed there and merged by DevLoop, then
one release pull request to trunk: the per-task review the 0.6 design set
out, run end to end in a sandbox repository before release. Off unless
reviewerRoute names the forge backend; without it tasks merge locally as
before. How to turn it on: README, "One pull request per task".
- Verdicts from GitHub reviews (#93, #98).
Only allowlisted reviewers who are not this host, only reviews of exactly the
reviewed commit, each reviewer's latest word; any request for changes
outranks every approval and is rework. An approval passes only once the
commit's checks are green.forge.verdictSource: commentskeeps the old
envelope path; exactly one source is read. - Rework carries the review (#95, #96, #105, #106).
A request for changes' body — PR-daemon's, or the local reviewer's — reaches
the worker's next attempt, as one quoted string, and survives a failed or
blocked attempt; it is dropped once an attempt is handed in or the task is
accepted. - The work branch (#94, #97, #107).
Recorded at the first delegate; task pull requests target it, labelled
devloop, never trunk. It is created on the forge at the task's base,
fast-forwarded when behind, left alone when ahead, refused when moved away;
a review with no work branch holds on trunk or detached instead of opening a
pull request. - A local review first (#99).
forge.localReviewruns a local reviewer before the pull request opens, and
its usage counts toward the caps. - DevLoop merges (#100–#102).
The verdict and checks are read again, thengh pr merge --match-head-commit
from an empty directory; the checkout fetches the merge commit by id and
fast-forwards to it before the task is done. Already merged is not merged
twice; anything that cannot be completed holds. - The release pull request (#103, #104).
Opened once every task is done, looked at each tick outside the state lock,
merged once approved with green checks, on the forge only. - Security fix: a worker could run a program as the host through git
(#108). Found by PR-daemon's
review. The Codex delegate was granted its worktree's gitdir, and any worker
could rewrite its worktree's.gitpointer; either could point the host's
next git call — committing the task, the pre-PR checker, the repository
status scan — at a repository whose config runs a program. Codex no longer
gets the gitdir, and every host git call in a task worktree pins its git
directories to the host's own paths with fsmonitor and hooks off. This
predates 0.6.4 and affects local mode too.
Carried to 0.6.5 (from the reviews): workers still inherit this host's gh
login; an empty set of checks counts as green; a few messages and gate texts
to tighten. 0.6.x numbers follow the release plan rather than strict semver.
New in 0.6.3
The page speaks English, Chinese and Thai. A switch at the top right
(EN · 中 · ไทย) changes every word the page draws, in place, and is
remembered on that browser; English is the default.
- The page's own words (#77–#82).
dashboard/i18n.jsholds each string as[English, 中文, ไทย], served at
/devloop/i18n.jsbehind the page's authentication. Headers, the home
lanes, cards, the start panel, the gate and halt panels, tasks, budget,
events, documents, the guide, repository status and the PR record all go
through it; times use the reader's locale (Thai dates show the Buddhist
year). A missing translation falls back to English and an unknown key
shows as itself. - What the server says, by code (#83–#90).
Readiness checks, cleanup reasons, protect_patterns warnings, every gate's
question, evidence and steps, and the halt reasons now carry a stable code
and the values their sentence uses; the page says them in the reader's
language and falls back to the server's own words for a code it does not
know. The CLI and the server's messages are unchanged. - Tests keep it whole. Every key the page asks for, every code the server
can send and every gate family ingate.tsmust have all three languages;
a key defined twice fails the suite. - Fix: a saved language is taken only when it is one of the three by own
property (a storedconstructorused to break every date on the page).
Not translated, on purpose: what models and people wrote (task titles,
GOAL.md, planning documents) and raw identifiers (reason codes, commands,
branch names).
New fields: readiness code/params, cleanup code, ProtectDrop.code,
gate key/vars, halt details (haltDetails on a project). No config or
STATE change. 0.6.x numbers follow the release plan rather than strict
semver.
New in 0.6.2
The page answers "what needs me?" first, and says what an answer costs before
it is given. Both ideas are borrowed from LoopX's control plane.
- The home page is grouped by attention (#71, #72, #74).
Four columns, in this order: 等你处理 (a halt asking a question, a project
the page cannot read, an armed loop whose process has stopped), 进行中, 闲置
(not started, paused, or a halt answered "leave it" while it is still that
halt), 已完成. Once there are projects they come before the guide and the
picker. Each card says in one sentence what happens next or what it waits
for, and how long it has waited. Each project's summary carries itslane
andsince. - A halt offers one answer, with its cost (#73, #75).
Every answer now says whether a model is paid again and whether existing work
is thrown away. The gate names a recommended answer, which is the page's one
primary button; the others are folded under 其他选项. A gate whose only
answer is to leave it leads with 要你做的事, the steps for the person. - Fix:
retrysaid "from a clean worktree"; it is not. A retry runs the
worker again in the task's existing worktree and base. The summary, the docs
and the new impact say so. A redo from a clean base is still the manual
command in the over-budget and replan gates.
A patch: new summary fields (lane, since) and gate fields (recommended,
impact), no config change and no STATE change.
New in 0.6.1
The per-PR budget, enforced by PR-daemon's own rules and recorded so it can
be judged on data. Each task's change goes through PR-daemon's mechanical
pre-PR checker before any reviewer is paid; the rules live in the PR-daemon
repository and are only called from here, so a rule change there reaches the
loop with a git pull, without a DevLoop release.
- The checker gates the review (#55–#57, #65).
Off by default; setprePrCheckto the checker's argv
(['bash', '~/Dev/tools/PR-daemon/scripts/pre-pr-check.sh']), with
prePrProfile(devloop) andprePrTimeoutMinutes(5). DevLoop knows only
the checker's contract — argv, exit codes, JSON — and never a rule. Exit 0
passes; exit 1 with a blocking finding holds the task, as
task_over_budgetwhen only size rules blocked (redo it smaller) or
prepr_blockedotherwise (SZ-4, high-risk content mixed in, is not a size); anything else, a timeout, or a result that
disagrees with itself holds asprepr_unavailable, never a pass. - The budget has an elastic band (#64–#69). Up to 200 lines, 5 files and
2 counted top-level directories is normal; up to 260 / 6 / 3 is elastic —
reviewed, with the size put in front of the reviewer, who is asked to judge
whether it should have been split (REWORK or REPLAN); beyond that the task
is refused as over budget. The thresholds are PR-daemon's (size.band,
size.limits, rules 1.2.0); an older checker's result is read as normal or
over from its blocks. - The planner is told the budget and estimates each task's size
(#59, #66, #67). The estimate is
never enforced — a malformed one is dropped, not the plan — and is logged
beside the checker's count, the data the estimate rules will be tuned on. .devloop/PR-LOG.jsonland the PR 记录 panel
([#58...
0.6.3
Release 0.6.3
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.3 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.3. This document is the release note, not a second semver.
New in 0.6.3
The page speaks English, Chinese and Thai. A switch at the top right
(EN · 中 · ไทย) changes every word the page draws, in place, and is
remembered on that browser; English is the default.
- The page's own words (#77–#82).
dashboard/i18n.jsholds each string as[English, 中文, ไทย], served at
/devloop/i18n.jsbehind the page's authentication. Headers, the home
lanes, cards, the start panel, the gate and halt panels, tasks, budget,
events, documents, the guide, repository status and the PR record all go
through it; times use the reader's locale (Thai dates show the Buddhist
year). A missing translation falls back to English and an unknown key
shows as itself. - What the server says, by code (#83–#90).
Readiness checks, cleanup reasons, protect_patterns warnings, every gate's
question, evidence and steps, and the halt reasons now carry a stable code
and the values their sentence uses; the page says them in the reader's
language and falls back to the server's own words for a code it does not
know. The CLI and the server's messages are unchanged. - Tests keep it whole. Every key the page asks for, every code the server
can send and every gate family ingate.tsmust have all three languages;
a key defined twice fails the suite. - Fix: a saved language is taken only when it is one of the three by own
property (a storedconstructorused to break every date on the page).
Not translated, on purpose: what models and people wrote (task titles,
GOAL.md, planning documents) and raw identifiers (reason codes, commands,
branch names).
New fields: readiness code/params, cleanup code, ProtectDrop.code,
gate key/vars, halt details (haltDetails on a project). No config or
STATE change. 0.6.x numbers follow the release plan rather than strict
semver.
New in 0.6.2
The page answers "what needs me?" first, and says what an answer costs before
it is given. Both ideas are borrowed from LoopX's control plane.
- The home page is grouped by attention (#71, #72, #74).
Four columns, in this order: 等你处理 (a halt asking a question, a project
the page cannot read, an armed loop whose process has stopped), 进行中, 闲置
(not started, paused, or a halt answered "leave it" while it is still that
halt), 已完成. Once there are projects they come before the guide and the
picker. Each card says in one sentence what happens next or what it waits
for, and how long it has waited. Each project's summary carries itslane
andsince. - A halt offers one answer, with its cost (#73, #75).
Every answer now says whether a model is paid again and whether existing work
is thrown away. The gate names a recommended answer, which is the page's one
primary button; the others are folded under 其他选项. A gate whose only
answer is to leave it leads with 要你做的事, the steps for the person. - Fix:
retrysaid "from a clean worktree"; it is not. A retry runs the
worker again in the task's existing worktree and base. The summary, the docs
and the new impact say so. A redo from a clean base is still the manual
command in the over-budget and replan gates.
A patch: new summary fields (lane, since) and gate fields (recommended,
impact), no config change and no STATE change.
New in 0.6.1
The per-PR budget, enforced by PR-daemon's own rules and recorded so it can
be judged on data. Each task's change goes through PR-daemon's mechanical
pre-PR checker before any reviewer is paid; the rules live in the PR-daemon
repository and are only called from here, so a rule change there reaches the
loop with a git pull, without a DevLoop release.
- The checker gates the review (#55–#57, #65).
Off by default; setprePrCheckto the checker's argv
(['bash', '~/Dev/tools/PR-daemon/scripts/pre-pr-check.sh']), with
prePrProfile(devloop) andprePrTimeoutMinutes(5). DevLoop knows only
the checker's contract — argv, exit codes, JSON — and never a rule. Exit 0
passes; exit 1 with a blocking finding holds the task, as
task_over_budgetwhen only size rules blocked (redo it smaller) or
prepr_blockedotherwise (SZ-4, high-risk content mixed in, is not a size); anything else, a timeout, or a result that
disagrees with itself holds asprepr_unavailable, never a pass. - The budget has an elastic band (#64–#69). Up to 200 lines, 5 files and
2 counted top-level directories is normal; up to 260 / 6 / 3 is elastic —
reviewed, with the size put in front of the reviewer, who is asked to judge
whether it should have been split (REWORK or REPLAN); beyond that the task
is refused as over budget. The thresholds are PR-daemon's (size.band,
size.limits, rules 1.2.0); an older checker's result is read as normal or
over from its blocks. - The planner is told the budget and estimates each task's size
(#59, #66, #67). The estimate is
never enforced — a malformed one is dropped, not the plan — and is logged
beside the checker's count, the data the estimate rules will be tuned on. .devloop/PR-LOG.jsonland the PR 记录 panel
(#58, #61–#63, #65).
One line per check — size, band, estimate, rules hit, rules version — and
per review verdict. Best-effort (a lost line costs only that line), never
through a symlink, and a malformed line is dropped rather than taking the
page down. The project page shows the latest 50, marking 弹性 and 超限.- Redoing a task smaller is real (#60).
The over-budget and replan gates used to suggest editing PLAN.md, which the
loop never reads back; they now give the commands that redo the task from
its base, and the worker's prompt states the budget. - A pending hold that cannot be read says so on every tick
(#59). One kept through a
read error (EACCES and the like) used to wait in silence until it read.
A minor: three new optional config keys, new optional task fields
(overBudget, estimate), a new file under .devloop/, no change to
existing behaviour while prePrCheck is unset.
New in 0.6.0
The first step of the 0.6 plan (design: draft PR #42): DevLoop does
the status half of pilot's work itself — see a repository's branches and
worktrees, and clean up merged branches — from the page, without a skill.
Shipped as eleven reviewed PRs, each inside the per-PR budget and each through
PR-daemon's mechanical pre-PR rules, a local review and PR-daemon's review.
- 仓库状态 panel (#43–#47, #49, #50).
On every project page, before and after a start: current branch, trunk,
ahead/behind, uncommitted changes; the merged branches that can go, as ticked
checkboxes; every kept branch with its reason; the steps left to a person
with their commands. 删除选中的分支 runsgit branch -dfor the ticked
branches the plan still offers at that moment, and says which were deleted
and why any were not. The rules it keeps are in
Dashboard.md ("Branch cleanup deletes only what git itself calls safe"). .pilot.ymlprotect_patterns are honoured, read as a superset of pilot's
own ref hook (both list forms, CRLF, blank and comment lines, non-ASCII
names) and never below release/hotfix/deploy; entries that protect nothing,
such as globs, are shown as a warning.- A finished dispatch waits for the state lock to save its result
(#51) instead of dropping it
after one try, and a hold that cannot get the lock is kept in
.devloop/PENDING_HOLDfor the next tick. - Fix: a tag named like the trunk no longer hides it
(#48). With a tagmain, git
shortened the branch toheads/mainand the start check let a loop start on
main; branches are now read by full ref.
A minor: new operator surface and a new endpoint pair
(GET …/projects/<id>/status, POST …/projects/<id>/cleanup), no config
change and no new STATE field.
New in 0.5.6
The last loose ends before 0.6, and the first release made the new way: split
into PRs inside the per-PR budget (≤200 lines, ≤5 files, ≤2 counted top-level
directories), each passing PR-daemon's mechanical pre-PR rules and a local
review before PR-daemon reviewed it.
- **Each task reco...
0.6.2
Release 0.6.2
Bounded autonomous engineering loop: structured model results, deterministic state transitions, host-enforced write scope, SHA-bound independent review, durable recovery, and role/tier routing. Tag v0.6.2 and the GitHub Release are created after this commit is on main; steps: Deploy.md.
Package version: 0.6.2. This document is the release note, not a second semver.
New in 0.6.2
The page answers "what needs me?" first, and says what an answer costs before
it is given. Both ideas are borrowed from LoopX's control plane.
- The home page is grouped by attention (#71, #72, #74).
Four columns, in this order: 等你处理 (a halt asking a question, a project
the page cannot read, an armed loop whose process has stopped), 进行中, 闲置
(not started, paused, or a halt answered "leave it" while it is still that
halt), 已完成. Once there are projects they come before the guide and the
picker. Each card says in one sentence what happens next or what it waits
for, and how long it has waited. Each project's summary carries itslane
andsince. - A halt offers one answer, with its cost (#73, #75).
Every answer now says whether a model is paid again and whether existing work
is thrown away. The gate names a recommended answer, which is the page's one
primary button; the others are folded under 其他选项. A gate whose only
answer is to leave it leads with 要你做的事, the steps for the person. - Fix:
retrysaid "from a clean worktree"; it is not. A retry runs the
worker again in the task's existing worktree and base. The summary, the docs
and the new impact say so. A redo from a clean base is still the manual
command in the over-budget and replan gates.
A patch: new summary fields (lane, since) and gate fields (recommended,
impact), no config change and no STATE change.
New in 0.6.1
The per-PR budget, enforced by PR-daemon's own rules and recorded so it can
be judged on data. Each task's change goes through PR-daemon's mechanical
pre-PR checker before any reviewer is paid; the rules live in the PR-daemon
repository and are only called from here, so a rule change there reaches the
loop with a git pull, without a DevLoop release.
- The checker gates the review (#55–#57, #65).
Off by default; setprePrCheckto the checker's argv
(['bash', '~/Dev/tools/PR-daemon/scripts/pre-pr-check.sh']), with
prePrProfile(devloop) andprePrTimeoutMinutes(5). DevLoop knows only
the checker's contract — argv, exit codes, JSON — and never a rule. Exit 0
passes; exit 1 with a blocking finding holds the task, as
task_over_budgetwhen only size rules blocked (redo it smaller) or
prepr_blockedotherwise (SZ-4, high-risk content mixed in, is not a size); anything else, a timeout, or a result that
disagrees with itself holds asprepr_unavailable, never a pass. - The budget has an elastic band (#64–#69). Up to 200 lines, 5 files and
2 counted top-level directories is normal; up to 260 / 6 / 3 is elastic —
reviewed, with the size put in front of the reviewer, who is asked to judge
whether it should have been split (REWORK or REPLAN); beyond that the task
is refused as over budget. The thresholds are PR-daemon's (size.band,
size.limits, rules 1.2.0); an older checker's result is read as normal or
over from its blocks. - The planner is told the budget and estimates each task's size
(#59, #66, #67). The estimate is
never enforced — a malformed one is dropped, not the plan — and is logged
beside the checker's count, the data the estimate rules will be tuned on. .devloop/PR-LOG.jsonland the PR 记录 panel
(#58, #61–#63, #65).
One line per check — size, band, estimate, rules hit, rules version — and
per review verdict. Best-effort (a lost line costs only that line), never
through a symlink, and a malformed line is dropped rather than taking the
page down. The project page shows the latest 50, marking 弹性 and 超限.- Redoing a task smaller is real (#60).
The over-budget and replan gates used to suggest editing PLAN.md, which the
loop never reads back; they now give the commands that redo the task from
its base, and the worker's prompt states the budget. - A pending hold that cannot be read says so on every tick
(#59). One kept through a
read error (EACCES and the like) used to wait in silence until it read.
A minor: three new optional config keys, new optional task fields
(overBudget, estimate), a new file under .devloop/, no change to
existing behaviour while prePrCheck is unset.
New in 0.6.0
The first step of the 0.6 plan (design: draft PR #42): DevLoop does
the status half of pilot's work itself — see a repository's branches and
worktrees, and clean up merged branches — from the page, without a skill.
Shipped as eleven reviewed PRs, each inside the per-PR budget and each through
PR-daemon's mechanical pre-PR rules, a local review and PR-daemon's review.
- 仓库状态 panel (#43–#47, #49, #50).
On every project page, before and after a start: current branch, trunk,
ahead/behind, uncommitted changes; the merged branches that can go, as ticked
checkboxes; every kept branch with its reason; the steps left to a person
with their commands. 删除选中的分支 runsgit branch -dfor the ticked
branches the plan still offers at that moment, and says which were deleted
and why any were not. The rules it keeps are in
Dashboard.md ("Branch cleanup deletes only what git itself calls safe"). .pilot.ymlprotect_patterns are honoured, read as a superset of pilot's
own ref hook (both list forms, CRLF, blank and comment lines, non-ASCII
names) and never below release/hotfix/deploy; entries that protect nothing,
such as globs, are shown as a warning.- A finished dispatch waits for the state lock to save its result
(#51) instead of dropping it
after one try, and a hold that cannot get the lock is kept in
.devloop/PENDING_HOLDfor the next tick. - Fix: a tag named like the trunk no longer hides it
(#48). With a tagmain, git
shortened the branch toheads/mainand the start check let a loop start on
main; branches are now read by full ref.
A minor: new operator surface and a new endpoint pair
(GET …/projects/<id>/status, POST …/projects/<id>/cleanup), no config
change and no new STATE field.
New in 0.5.6
The last loose ends before 0.6, and the first release made the new way: split
into PRs inside the per-PR budget (≤200 lines, ≤5 files, ≤2 counted top-level
directories), each passing PR-daemon's mechanical pre-PR rules and a local
review before PR-daemon reviewed it.
- Each task records who planned it (#38).
STATE named the implementer and reviewer but not the planner, so after the
switch to three-way routing only Codex's own logs showed who planned. Every
task a plan creates now carriesplanner(the route identity), validated on
load like the other two; STATE files without it load unchanged. - The page shows all three roles, and a selection no longer freezes it
(#40). Each task row reads
规划 … · 实现 … · 评审 …. The refresh used to pause for any text selection
until the reader clicked elsewhere, so a task id selected to copy froze the
gate and budget; it now pauses only for a selection inside a document, and
for at most 60 seconds.
A patch: a new optional task field, no config change.
New in 0.5.5
The loop can be watched and understood from the page, and the trunk rule now
holds for the whole run, not only at start.
- Every merge refuses the trunk. 0.5.4 checked the branch when a loop
started. Now the merge asks the same question each time, so a checkout
switched back tomain/master/the configured base mid-loop, or a project
armed by writing GOAL.md by hand, halts with a newmerge_onto_trunkhold
(and a detached HEAD withmerge_detached_head, which used to retry silently).
The reviewed task staysmerge_ready; the page says to move the checkout back
and resume, and it merges on the next tick without being redone or paid for
again. - A root that is not its own git toplevel is refused. A plain directory
inside another repository used to pass the start check with the outer
repository's branch. - The planning documents are on the page. The project page has a 文档 panel,
before and after a start. It previews pilot's roadmap, tasks, progress,
acceptance, architecture, spec and research fromdocs_dir, and DevLoop's own
GOAL, PLAN, REVIEW and PROGRESS, rendered as markdown built from text nodes.
Each task in the table now l...