Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# AGENTS.md: operating Mill safely

Version: 2.6
Version: 2.7

Status: normative

Expand All @@ -21,6 +21,10 @@ and checks are in `product/review-delivery-follow-through.md`. Use the native
maintainer path for these Mill control changes; it does not grant a builder
permission to modify its own frozen controls.

The owner approved the bounded verifier recovery repair on 2026-09-21. Its
authority and acceptance are in `product/verifier-recovery.md`. Use the native
maintainer route; preserve downstream task and candidate identities.

## Operating Mill

Mill turns approved repository-native product intent into a bounded, tested,
Expand Down Expand Up @@ -259,6 +263,10 @@ millctl --json state backup
millctl --json support-bundle --run <run-id>
```

- Eligible verifier infrastructure failures may use the exact attended
[candidate recovery](docs/verifier-recovery.md) plan. Its single-use allowance
retains the original deadline and grants only unchanged-candidate verification
and review. It cannot authorize another builder or repair.
- `resume` is permitted only when Mill can prove no prior worker still owns the
effect or when it is performing the approved bounded review-repair pass.
- `cancel` records intent; only the live foreground controller may signal its
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ All notable changes follow Keep a Changelog and Semantic Versioning.

## [Unreleased]

## [0.8.1] - 2026-09-21

### Fixed

- Recover unchanged candidates after eligible verifier infrastructure failures
through an exact attended plan, without another builder attempt.
- Preserve the original blocker when a follow-up command is rejected.

### Added

- A single bounded verification/review recovery allowance, with its own expiry
and controller identity while retaining the original run history.

## [0.8.0] - 2026-09-21

### Added
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ existing repository.

```sh
npm view @davidahmann/mill dist-tags --json
npm install --save-dev --save-exact --ignore-scripts @davidahmann/mill@0.8.0
npm install --save-dev --save-exact --ignore-scripts @davidahmann/mill@0.8.1
npx --no-install millctl --version
```

The example selects this source candidate's version, `0.8.0`. Use it after the
The example selects this source candidate's version, `0.8.1`. Use it after the
linked release's final evidence confirms publication; an unpublished source
candidate is not an installable release. See the
[v0.8.0 scope](docs/releases/v0.8.0.md) and
[v0.8.1 scope](docs/releases/v0.8.1.md) and
[planning evidence rules](docs/planning.md#what-passing-evidence-means).

To develop Mill itself from a clean source checkout:
Expand Down Expand Up @@ -550,6 +550,12 @@ Cancellation records intent without discarding the receipt. Use
`pr finalize` and green main checks before cleanup. See
[approval recovery](docs/approvals.md#interruptions).

For an eligible pre-command verifier infrastructure failure, inspect the
[candidate recovery procedure](docs/verifier-recovery.md). It preserves the
original run and can grant one separately approved verification/review window
after its original deadline expires. The unchanged candidate must have a
committed version pin. Tests and independent review remain required.

Before any remote attempt, stale review scope can use
`review --task product/tasks/TASK.yaml --run <run-id> --refresh --base <exact-provider-commit> --attended`.
This preserves the candidate and remaining review budget, invalidates the
Expand Down
16 changes: 11 additions & 5 deletions architecture/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,17 @@ private labels and binds removal readback to the observed container and daemon.
Unresolved ownership blocks retry and destructive cleanup. There is no
host-independent deadline watchdog; see [OCI recovery](../docs/oci-recovery.md).
The persisted absolute run deadline is reused for verification, review, retry,
repair, and resume; no checkpoint grants a fresh budget. An attempt ID plus PID,
PGID, and process-start digest is diagnostic state, not signalling authority.
Cancellation is durable state polled by the foreground lease owner, which
terminates its own in-memory child, including a GitHub mutation process; no
command signals a stored PID. Cancellation is rechecked before each external
repair, and resume; ordinary checkpoints grant no fresh budget. The explicit
[candidate recovery](../docs/verifier-recovery.md) boundary may grant one
separately approved verification/review window after eligible infrastructure
failure and expiry of the original deadline. A committed candidate pin is
required. Its immutable receipt retains the original deadline, failure history,
controller identity and exact candidate. It grants no builder or repair and
requires settled worker/container ownership before application. An attempt ID
plus PID, PGID, and process-start digest is diagnostic state, not signalling
authority. Cancellation is durable state polled by the foreground lease owner,
which terminates its own in-memory child, including a GitHub mutation process;
no command signals a stored PID. Cancellation is rechecked before each external
effect, and an interrupted effect remains unknown until authoritative readback.
If the lease is free but a recorded process may still exist, resume and terminal
cancellation fail closed for attended reconciliation. State events are
Expand Down
8 changes: 8 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,11 @@ Native maintainer changes use the
[standalone review route](maintainer-review.md). Dependabot grouping is checked
by `npm run check:dependabot`; the checker covers Mill's bounded update policy
and the shipped starter, not GitHub's full schema.

## Verifier infrastructure recovery

See [candidate recovery](verifier-recovery.md) for the exact plan/apply flow.
Keep preflight failures separate from failed command evidence. Recovery tests
must cover unchanged-candidate success, historical blocker provenance, pin
compatibility, stale approval, cancellation, uncertain ownership, authority
drift, original-deadline retention and denial of another builder or allowance.
14 changes: 14 additions & 0 deletions docs/releases/v0.8.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Mill 0.8.1

This source candidate adds explicit recovery for unchanged candidates blocked by
eligible verifier infrastructure failures. The operator approves one fixed
verification/review window; Mill preserves the original run, deadline, attempts,
candidate and failure history. Recovery grants no builder or repair.

Rejected follow-up commands preserve the original blocker. Recovery checks
candidate and authority identity, previous evidence, worker and container
ownership, and its single-use approval before continuing. Tests remain required.

Publication and npm/GitHub channel pointers are established by the protected
workflow's final release evidence. This source record grants no new stack,
customer-compatibility or unattended-operation claim.
57 changes: 57 additions & 0 deletions docs/verifier-recovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Recover verification of an unchanged candidate

A missing approved image can stop verification before any test runs. Pull that
exact digest explicitly and inspect the run's status and timeline. Mill never
pulls it during verification, and restoring it does not establish passing tests.

Recovery is available only for a committed candidate with an eligible
infrastructure failure and a valid `mill.lock` committed in that candidate.
Unpinned candidates cannot use this recovery route. The task, configuration,
frozen context, base, candidate commit and tree must still match. Failed tests,
changed files, cancellation, uncertain workers or containers, and delivery
effects require their existing reconciliation or disposition.

## One attended recovery window

The recovery plan retains the original deadline and grants one separate window
for verification and read-only review of the same candidate. Select an explicit
future ISO timestamp no more than the smaller of the task's original duration
and 1,200 seconds away. Use the same timestamp in both commands:

```sh
millctl --json verification-recovery plan --task product/tasks/TASK.yaml \
--run <run-id> --expires-at <ISO-timestamp>
millctl --json verification-recovery apply --task product/tasks/TASK.yaml \
--run <run-id> --expires-at <same-ISO-timestamp> \
--approve sha256:<recovery-plan> --attended
millctl --json verify --task product/tasks/TASK.yaml --run <run-id>
millctl --json review --task product/tasks/TASK.yaml --run <run-id>
```

Planning reads existing state without creating or upgrading it. An incompatible
controller must validate the recovery receipt before writable state access or
resource cleanup. Apply checks attendance and approval before writable access,
then rechecks the plan under the writer lease.

Inspect the exact plan before applying it. Every fresh recovery window requires
the original run deadline to have expired. This prevents an older controller
from using remaining worker authority. The approval binds the recorded failure,
immutable candidate pin, invoking checkout, authority and recovery controller. A
changed checkout pin blocks recovery. A newer controller can service only the
bound recovery operations; it does not silently upgrade the repository's tool.
Preserve its installed artifact and release evidence. Repin the downstream
repository through a reviewed change after the old run closes.

The recovery grants no builder, repair, new candidate or delivery approval.
P0/P1 findings stop a candidate-only allowance. Required test failures remain
failures. Another expired recovery window requires a new owner decision outside
this single-use mechanism; repeating the command cannot extend it.

## Historical failures

Older Mill versions could replace an infrastructure blocker with
`RUN_NOT_COMMITTED` after an invalid retry. Recovery examines the retained event
chain instead of trusting that latest code alone. It must prove the eligible
failure belongs to the current candidate and excludes intervening validation,
review, cancellation and external effects. Retain both original and rejected
command evidence. Never edit the database to manufacture eligibility.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@davidahmann/mill",
"version": "0.8.0",
"version": "0.8.1",
"description": "Local-first software factory for new and existing codebases. Turns approved product intent into tested, reviewed PRs with repo-native evidence and explicit human approval for delivery and merge.",
"license": "Apache-2.0",
"author": "David Ahmann",
Expand Down
50 changes: 50 additions & 0 deletions product/verifier-recovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Recover an unchanged candidate after verifier preflight failure

Status: approved by David Ahmann on 2026-09-21 in the maintainer work session.
Route: native maintainer implementation, independent architecture review and
exact-candidate local review before push.

Telryn's admitted T-019 builder committed its candidate, but verification
stopped before command execution because the approved image was unavailable.
Restoring the image did not make the blocked candidate retryable. A rejected
second verify also replaced the original blocker with `RUN_NOT_COMMITTED`.
Preserved events and CLI evidence retain the original cause.

Implement a bounded recovery for that failure family. A passing image check must
not count as passing a product test. Preserve the run, original deadline,
candidate, task, configuration, context, attempts and prior evidence.

Acceptance:

- A rejected follow-up command preserves the existing failure reason.
- Safe pre-command infrastructure failure can retry only with unchanged
authority and candidate identity, no active or uncertain worker, and settled
container ownership. Actual failed commands require their existing
disposition.
- An attended, exact plan may grant one new candidate-only verification/review
window. Its expiry is fixed before approval and no later than the smaller of
the original task duration and 1,200 seconds from planning/application.
- Original deadlines and counters remain intact. Recovery never grants a
builder, repair, new candidate, weaker tests, automatic image pull, or
delivery approval. Cancellation, failed tests, drift and unresolved effects
block it.
- Historical overwritten blocker codes qualify only when the retained event
history proves the allowed failure and excludes intervening evidence/effects.
- Recovery requires a valid version pin committed in the candidate.
- A tool upgrade is explicit. Any exception to the frozen package pin binds the
recovery controller version to this run and its verification/review only.
Every new recovery window requires the original deadline to expire, preventing
an old controller from launching a builder or repair. Bind the immutable
candidate pin and reject invoking-checkout pin drift.
- Recovery planning and incompatible-controller admission read existing state
before any writable open, migration or resource reconciliation. Apply
validates attendance and exact approval first, then rechecks under the writer
lease.
- Unit/integration and installed CLI tests cover success and adversarial
boundaries. Full native checks, audit and independent reviews pass before
merge. Release follows the existing tag/artifact/OIDC/readback procedure.

After qualification, use the released fix to recover the existing Telryn
candidate under a fresh explicit receipt. Verify and review it before ordinary
approved delivery. Preserve acceptance and historical records; repin Telryn
through a separate reviewed maintainer change after the product run closes.
Loading