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
7 changes: 5 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ Read these files before editing:
but are not product behavior.
- Keep the builder unable to push, merge, deploy, or rewrite its own acceptance
oracle. The shipper may push only an already committed, verified candidate.
- Keep forge credentials behind the attended shipper boundary. Persist external
intent before a call, treat provider readback as authoritative, and block
mutation while an effect outcome is unknown.
- Do not claim hostile-code containment for attended host execution.
- No ambient credentials, implicit network, auto-merge, deployment, parallel
writers, daemon, hosted control plane, or self-modification in v1.
Expand Down Expand Up @@ -67,8 +70,8 @@ iteration, but skipped required checks block promotion.

- Default branch: `main`.
- Work branches use `codex/` unless a task says otherwise.
- Required checks and exact-head local review must settle before David marks a
draft ready and merges it.
- Required checks and exact-head local review must settle before a human marks a
draft ready and David, the configured merger, merges it.
- Use conventional commits and DCO sign-off.
- Releases come only from immutable tags through trusted npm publishing with
provenance. The first release follows the genesis qualification protocol.
Expand Down
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ All notable changes follow Keep a Changelog and Semantic Versioning.
and exact-candidate read-only Codex review.
- Repository-namespaced SQLite state with append-only events, exclusive writer
leases, cancellation, interruption recovery, backup/validated restore,
terminal-only purge, and redacted support export.
reviewed-or-terminal purge, and redacted support export.
- Executable task-packet, context-manifest, validation-evidence, and
review-result contracts with aligned runtime and JSON Schema validation.
- Exact-candidate draft-PR planning, attended push/open, unknown-effect
reconciliation, paginated GitHub policy observation, human merge gating, and
exact post-merge closure with an executable delivery-record contract.
- Coordinator-enforced remote attendance, one readback-authorized effect retry,
changing-blocker replacement, and database-swap state-restore recovery.

### Changed

Expand Down Expand Up @@ -67,6 +72,9 @@ All notable changes follow Keep a Changelog and Semantic Versioning.
active attempts only through compare-and-swap.
- Named OCI verifier containers are force-removed under an independent cleanup
deadline after success, failure, timeout, output exhaustion, or cancellation.
- OCI verification safely aliases comma-bearing bind paths, and restoring an
older state backup quarantines newer unreferenced worktrees with durable
recovery evidence rather than deleting them.

### Security

Expand All @@ -86,3 +94,10 @@ All notable changes follow Keep a Changelog and Semantic Versioning.
- Codex invocations ignore ambient execution rules, and OCI verification uses a
clean read-only candidate workspace so uncommitted ignored artifacts cannot
affect promotion evidence.
- GitHub credentials stay behind the operator-owned `gh` and Git credential
helper boundary. Exact actor/repository/remote binding, expiring approval,
expected-head push leases, immutable PR markers, effect journaling, and
authoritative readback prevent builder access and blind duplicate mutation.
Durable cancellation is polled before and during mutations; top-level and
inline review findings, exact merger identity, provable merge shape, and
non-false-green post-merge results remain fail-closed.
70 changes: 64 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ approved product outcome into a tested, reviewed draft pull request.
The project is pre-alpha. Wave 1 provides the installable source package,
compact schemas, static PRD/repository inspection, and readiness diagnostics.
Wave 2 adds an attended local path from one explicit task approval to an exact
committed, OCI-validated, independently reviewed candidate. The CLI is
`millctl`, published eventually as `@davidahmann/mill` to avoid collision with
the existing `mill` command and npm package.
committed, OCI-validated, independently reviewed candidate. Wave 3 adds an
attended, exact-candidate path to one draft GitHub pull request, bounded
CI/review observation, human merge, and truthful closure. The CLI is `millctl`,
published eventually as `@davidahmann/mill` to avoid collision with the existing
`mill` command and npm package.

Mill's v1 boundary is deliberately narrow:

Expand Down Expand Up @@ -80,6 +82,61 @@ transient or invalid provider review; the durable per-candidate attempt budget
prevents an unbounded token loop while still allowing the one reviewed repair
generation.

## Open one attended draft pull request

The downstream repository must explicitly raise `trustCeiling` to `propose` and
bind its immutable GitHub repository node ID, target branch, accepted operators,
required checks, review policy, and allowed human merge methods. Mill reads the
live actor, repository, remote, and default branch before it returns an approval
digest. That plan performs no remote mutation. The separate `pr open` command
requires the exact unexpired digest and an attended operator:

```yaml
trustCeiling: propose
propose:
forge: github
host: github.com
owner: example
repository: app
repositoryNodeId: R_kgDOExample
remoteName: origin
baseBranch: main
branchPrefix: mill/
allowedActors: [founder]
allowedMergerLogins: [founder]
requiredChecks: [validate, CodeQL]
reviewPolicy:
mode: local_only
requiredReviewerLogins: []
allowedMergeMethods: [linear_tree_preserving]
```

```sh
node dist/cli.js --json pr plan --task product/tasks/TASK.yaml --run <run-id>
node dist/cli.js --json pr open --task product/tasks/TASK.yaml --run <run-id> \
--approve sha256:<digest-from-pr-plan> --attended
node dist/cli.js --json pr observe --task product/tasks/TASK.yaml --run <run-id>
# A human may mark ready; a configured merger merges in GitHub.
node dist/cli.js --json pr finalize --task product/tasks/TASK.yaml --run <run-id>
```

Only the shipper reads the operator-owned `gh` session. Builder and reviewer
processes receive neither GitHub credentials nor mutation tools. Mill journals
intent before push and PR creation, uses an expected-old-head lease, and reads
GitHub back before claiming an effect. An uncertain outcome becomes
`effect_unknown`; `pr reconcile` is read-only and must classify it before any
retry. Exact readback proving absence authorizes one retry; a second absent
outcome blocks. Required checks pass only when every latest exact-head result is
successful. A configured `github_required` reviewer may complete a current-head
`APPROVED` or `COMMENTED` review, but any current-head actionable finding still
blocks, including a severity-tagged top-level review body. Mill stops at
`awaiting_human`; draft readiness is not closure authority and Mill never
changes it or merges. Finalization verifies the recorded merger against
`allowedMergerLogins`. Because GitHub does not expose an authoritative
distinction between a one-commit squash and rebase, the provable policy is
`linear_tree_preserving`; Mill never guesses a specific linear method from its
allowlist.

Use `--json` before the command for the stable machine-readable envelope.
`--json --version` is machine-readable; help is human-only and combining it with
`--json` returns a typed usage error. `doctor` and static adoption never execute
Expand Down Expand Up @@ -124,9 +181,10 @@ the repository.

## Status

Not published. Local attended delivery is implemented, but no GitHub mutation,
hostile-host containment, release, or generalized stack-compatibility claim
exists until its corresponding later-wave canary passes.
Not published. Local attended delivery and the bounded draft-PR lifecycle are
implemented and covered by fake-provider and packed-package canaries. The first
attended disposable real-GitHub canary, hostile-host containment, release, and
generalized stack-compatibility claims remain pending their explicit gates.

## License

Expand Down
3 changes: 2 additions & 1 deletion WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ For each wave:
6. Run a complete exact-candidate local review and one systemic repair wave if
necessary.
7. Push the unchanged candidate, open/update one PR, and observe required CI.
8. David marks ready and merges. Observe the resulting main commit and checks.
8. A human may mark the draft ready; David, the configured merger, merges it.
Observe the resulting main commit and checks.

Current Factory skills are optional maintainer-side bootstrap tools. Their
prompts, profiles, artifacts, or state are not Mill runtime or product
Expand Down
75 changes: 59 additions & 16 deletions architecture/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Mill architecture

Status: approved foundation decision Last updated: 2026-08-31
Status: approved v1 decision Last updated: 2026-09-01

## Form

Expand All @@ -11,7 +11,7 @@ and exits to resumable state for long waits—there is no daemon.

## Boundaries

The implemented Wave 2 boundary is:
The implemented Wave 3 boundary is:

```text
exact human-authored task + product/scenario/policy digests
Expand All @@ -22,6 +22,11 @@ exact human-authored task + product/scenario/policy digests
-> selected digest-pinned OCI commands without network
-> fresh read-only Codex review of the exact verified commit
-> reviewed local candidate or one repair-and-revalidate cycle
-> exact actor/repository/remote proposal digest
-> expected-head push + immutable-marker draft PR
-> exact-head CI and optional GitHub-review observation
-> human readiness and merge
-> exact merge/tree/default-branch check readback and closure
```

The complete planned v1 boundary extends that path:
Expand All @@ -45,6 +50,36 @@ The builder never receives forge/deployment authority. The shipper cannot create
or amend the candidate commit. Product/oracle changes invalidate the candidate.
Provider state is authoritative for external effects.

The GitHub adapter is isolated behind the delivery coordinator. Planning reads
the live delegated actor, repository node identity, clone URL, fork status and
default branch, then binds them with the candidate commit/tree, task/config,
branch, required checks, review policy, allowed merge methods, approval expiry,
and intended effects. Only `pr open` mutates. Its effect journal records intent
and call start before each push or PR request, caps each effect at two attempts,
and makes ambiguous results enter `effect_unknown`. Reconciliation performs
authoritative branch/marker/PR readback without mutation. Exact absence permits
one retry; a second absent outcome blocks for human disposition. The same
recorded PR number, node identity, marker, branch, base, open-draft state, and
observed head are invariant whether an ambiguous repair push is absent or
landed. A retry performs that check again from a fresh readback immediately
before recording call start and invoking Git. GitHub API collections are
paginated under one deadline and output budget. Tokens remain behind the
operator-owned `gh` and Git credential-helper boundary and are not passed to
Codex or stored in state.

One stable delivery key and branch identify the PR across the single allowed
repair. A new candidate gets new validation, review, approval, and push-effect
identity while updating that same PR. Required checks are evaluated on the exact
current head; missing, pending, conflicting, cancelled, neutral, skipped,
timed-out, or failed results do not pass. Mill never changes draft readiness or
merge state, and readiness is not treated as closure authority. Finalization
requires GitHub to prove the PR head, merge commit, tree, authorized merger
identity, containment in the configured default branch, allowed merge shape, and
successful required checks on the exact merge commit. One-parent tree-preserving
history is classified only as `linear_tree_preserving`, never guessed to be
squash or rebase from policy. A tree-changing merge requires separate
revalidation rather than inferred closure.

In Wave 2, the qualification approval digest binds a passing baseline's exact
base commit, canonical task and repository configuration, selected command
definitions, and normalized evidence identity. The context manifest, candidate
Expand Down Expand Up @@ -80,15 +115,20 @@ deadline and output cap. 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; no command
signals a stored PID. If the lease is free but a recorded process may still
exist, resume and terminal cancellation fail closed for attended reconciliation.
State events are append-only, backup restore validates SQLite integrity, schema,
and required objects before atomic replacement, and purge requires every run to
be terminal. A failed pre-build context setup removes its provisional worktree
and branch. Review attempt budgets are scoped to an exact candidate generation,
and repair reasserts the reviewed commit/tree before allowing writes. There is
no background daemon or implicit retry.
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 append-only, backup restore validates SQLite
integrity, schema, and required objects before atomic replacement. Restoring
older state moves newer unreferenced Mill worktrees into a mode-restricted
quarantine. Its immutable recovery manifest records the database-swap commit
point and exact moved paths; restore never silently deletes them. Purge requires
every run to be reviewed or terminal. A failed pre-build context setup removes
its provisional worktree and branch. Review attempt budgets are scoped to an
exact candidate generation, and repair reasserts the reviewed commit/tree before
allowing writes. There is no background daemon or implicit retry.

## Core modules

Expand Down Expand Up @@ -118,11 +158,14 @@ digest-pinned OCI environment with no network, a read-only root and workspace,
dropped capabilities, no-new-privileges, resource bounds, and no implicit image
pull. Every command receives an opaque Mill-owned container name and evidence is
withheld until an unconditional, separately bounded `docker rm --force`
succeeds. Codex runs in attended trusted-host mode using workspace-write
sandboxing and promotion-time Git scope and identity checks. Mill does not claim
this prevents all host access. Stronger containment requires a separately
qualified container/VM worker with controlled model authentication and no
host-home, Docker-socket, keychain, or forge credential access.
succeeds. If a canonical workspace path contains a comma, Mill mounts it through
a mode-restricted, exact-realpath temporary alias so Docker's comma-delimited
long syntax does not truncate the source. Codex runs in attended trusted-host
mode using workspace-write sandboxing and promotion-time Git scope and identity
checks. Mill does not claim this prevents all host access. Stronger containment
requires a separately qualified container/VM worker with controlled model
authentication and no host-home, Docker-socket, keychain, or forge credential
access.

## Release trust

Expand Down
31 changes: 24 additions & 7 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ Only applicable tiers are active. A skipped required lane blocks promotion.
| Scenario | active | normal, exception, degradation, recovery, adversarial |
| Cross-system | Wave 3+ | Codex, OCI and GitHub canaries |

Wave 2 keeps a deterministic fake-adapter suite in CI and requires an attended
real Codex/OCI canary before the wave is accepted. The realistic scenario set
covers:
Wave 3 keeps deterministic fake Codex, OCI, GitHub, and Git adapters in CI and
runs the packed CLI through the human-merge gate in a disposable repository. A
real Codex/OCI or GitHub canary remains attended maintainer evidence, never a CI
job with personal credentials. The realistic scenario set covers:

- normal approval, build, lifecycle commit, verification, and clean review;
- negative controls for failed, stale, inspect-only, or interrupted baseline
Expand All @@ -58,15 +59,31 @@ covers:
- recovery through crash-released writer leases, PID-reuse-safe orphan
reconciliation, explicit OCI container cleanup, provisional workspace cleanup,
exact-candidate repair revalidation, per-candidate review budgets, validated
state backup/restore, and terminal-only purge;
state backup/restore, quarantine of worktrees newer than a restored backup,
external-effect readback, one readback-authorized retry, retry exhaustion,
coordinator-level attendance enforcement, changing blocker identity, and purge
only after a locally reviewed or terminal state;
- provenance through exact base, context, candidate commit/tree, validation, and
review identity checks;
- remote delivery through wrong-actor/fork/remote denial, stale approvals,
expected-head pushes, effect-before-receipt recovery, unknown-effect blocking,
cancellation before and during mutations, paginated exact-head inline and
top-level review feedback, one aggregated repair, stable PR identity and
open-draft preflight before retry whether an ambiguous push is absent or
landed, unauthorized merger and disallowed merge-shape rejection, merge-tree
binding, and non-false-green post-merge checks;
- hostile filesystem coverage for Docker bind paths containing commas without
weakening read-only/no-network verification;
- restore recovery through an immutable pre-commit quarantine manifest and a
database swap as the final fallible commit point;
- packaging through installation of the generated tarball and execution of its
public CLI and schema exports.

The real provider canary is maintainer evidence, not a deterministic CI job: it
uses the maintainer's personal Codex account and a pre-pulled digest-pinned
image, and it must never push or create a pull request in Wave 2.
The real-provider canaries use the maintainer's personal Codex and GitHub
accounts, a pre-pulled digest-pinned image, and an explicitly named disposable
repository. They may exercise only the wave's approved effects and must preserve
authoritative readback evidence. No test may provision a repository, mark a PR
ready, merge, deploy, or rerun remote checks.

## Architecture questions

Expand Down
4 changes: 3 additions & 1 deletion docs/repository-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ After the Wave 1 checks have run at least once, configure:
- conversation resolution required;
- no force pushes or default-branch deletion;
- merge queue disabled initially;
- squash merge as the only merge method;
- squash merge as the only GitHub UI method; Mill records the independently
provable result as `linear_tree_preserving` because one-commit squash and
rebase are not distinguishable from post-merge topology alone;
- automatic branch deletion after merge;
- zero required approving human reviews, because David is the sole maintainer;
- maintainer bypass allowed only for emergencies and recorded as repair/audit
Expand Down
7 changes: 4 additions & 3 deletions product/PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Each item is one vertical delivery wave, not a bucket of microtasks. Later-wave
choices close only before their wave. The current detailed task is in
`product/tasks/`.

Wave 1 is landed. Wave 2 is implemented and remains active until its packed CLI
and attended real-provider canaries, exact-candidate review, PR CI, human merge,
and resulting-main checks are complete.
Waves 1 and 2 are landed. Wave 3 is active: its implementation, fake-provider
fault matrix, and packed draft-PR canary live in the same candidate change.
Exact-candidate review, PR CI, human merge, resulting-main checks, and the
explicitly authorized disposable real-GitHub canary remain its promotion gates.
3 changes: 1 addition & 2 deletions product/PRD.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Mill product requirements

Status: approved foundation contract Owner: David Ahmann Last updated:
2026-08-31
Status: approved v1 contract Owner: David Ahmann Last updated: 2026-09-01

## Problem

Expand Down
Loading