This file is the order of work from now to Baley's first public release: nine builds, then the release design, a live acceptance run on Claude Code, and publishing. Status is Build 2 complete, Build 3 T1 to T17 merged (T17 is #262) with #24 open for what T17 left open, Build 4 T1 merged (#268), Build 4 T2 merged (#271), and Build 4 T3 in progress on this branch, based on main 0f023936, dated 2026-10-14, taken from the GitHub issues, milestones and pull requests of crenshawdev/baley and from the design documents and decision records. No issue, milestone or design document gives a date, so this file shows order only. The plan re-check design #134 is recorded as landed on 2026-10-06 in ADR 0037; its implementation belongs to Builds 4 and 5. The integration check design #229 is recorded as landed on 2026-10-08 in ADR 0042; its implementation belongs to Builds 4 and 5. The repository upkeep design #47 is recorded as landed on 2026-10-06 in 0015; its remaining implementation belongs to #54, while UPK-R2 is implemented by Build 3 delivery tasks T14 to T17 (#24). The delivery and credential designs are recorded as landed on 2026-10-06 in ADR 0038 and ADR 0039. Build 3 T17 is merged. Its installed run is recorded in spikes/host-matrix (install-live-2026-10-11-run1.md and a repeat of the install rerun, install-live-2026-10-11-run2.md), and what the run left open is listed in the Build 3 table and notes below, so Build 3 is not complete. Build 4 (#25) T2 removed the built key reader, baley exec --key and the HTTPS model lister (#271). Each build pull request updates this roadmap.
Builds 1 to 9 run in order, and on GitHub each build issue is blocked by the one before it. All nine are in the milestone Evidence. The release design (#14) waits on all nine builds and on every other open issue except the Build 3 issues #190, #203, #214, #219, #220, #221, #227, #235, #238 to #249, #251, #252 and #254 to #256, which GitHub does not link to it.
flowchart TB
B1["Build 1: Foundation<br/>#22"]
B2["Build 2: Identity, settings and keys<br/>#23"]
B3["Build 3: Hosts<br/>#24"]
B4["Build 4: Planning<br/>#25"]
B5["Build 5: Doing the work<br/>#26"]
B6["Build 6: Milestones, landing, undo and pause<br/>#27"]
B7["Build 7: Next action and progress<br/>#28"]
B8["Build 8: Search, why and support work<br/>#29"]
B9["Build 9: Removal<br/>#30"]
OTHER["8 other open issues:<br/>upkeep, docs, bugs"]
R1["Release design<br/>#14"]
R2["Live acceptance run on Claude Code"]
R3["Publish and install"]
B1 --> B2 --> B3 --> B4 --> B5 --> B6 --> B7 --> B8 --> B9 --> R1 --> R2 --> R3
OTHER --> R1
classDef done fill:#1a7f37,stroke:#116329,color:#ffffff
classDef progress fill:#9a6700,stroke:#7d4e00,color:#ffffff
classDef next fill:#fff8c5,stroke:#9a6700,stroke-width:3px,color:#3b2300
classDef blocked fill:#cf222e,stroke:#a40e26,color:#ffffff
classDef planned fill:#eaeef2,stroke:#6e7781,color:#24292f
class B1,B2 done
class B3,B4 progress
class R1 blocked
class B5,B6,B7,B8,B9,OTHER,R2,R3 planned
Figure 1. The path from Build 1 to publishing. Arrows point from a piece of work to what waits on it. Eight other open issues block the release design; the twenty-five open Build 3 issues are listed below but have no GitHub dependency link to it.
| Status | Meaning |
|---|---|
| Done | Merged |
| In progress | Pull requests are merging |
| Next | The next build to start |
| Blocked | Waits on an open issue outside the build chain as well as on the item before it |
| Planned | Not started |
#22 · milestone Evidence · design 0001 evidence ledger · done
The evidence ledger store: a storage port with a SQLite adapter behind it, one conformance suite every adapter must pass, the hash chain, and forge anchors pushed with git. The owner's command line runs verify, doctor, export, purge, scrub, rebuild, anchor and acknowledge-restore, and baley-bench measures the real adapter. Nothing in the lifecycle uses the ledger yet.
ADRs: 0001 event ledger, 0002 SQLite, 0003 per-user database, 0005 storage port, 0007 forge anchors, 0010 projector traits in the port, 0012 optimistic concurrency, 0021 claim rules in the port, 0022 acknowledged restore, 0023 no backups in Baley, 0024 conformance suite and adapter tests, 0025 anchor tag objects, 0026 anchors read by Baley.
flowchart LR
T1["T1 to T14<br/>merged"]
classDef done fill:#1a7f37,stroke:#116329,color:#ffffff
class T1 done
Figure 2. Build 1's tasks. One pull request per task.
| Task | What | Pull requests | Status |
|---|---|---|---|
| T1 | Workspace split: four crates, baley-core fenced from the engine |
#31 | Merged |
| T2 | Events, canonical JSON, the hash chain and the pure verifier | #32 | Merged |
| T3 | The storage port; the event and chain move into baley-store |
#33 | Merged |
| T4 | Opening the store, the schema, the writer queue and the epoch | #34 | Merged |
| T5 | Payloads and references | #35 | Merged |
| T6 | Views: tables, indexes, get and find |
#36 | Merged |
| T7 | transact and the request view |
#39 | Merged |
| T8 | Retention, reduction and purge | #41 | Merged |
| T9 | Generations, rebuild and verify --views |
#42, #43 | Merged |
| T10 | Claims, leases and reconciliation | #132 | Merged |
| T11 | Anchors and the adapter's verify |
#135 | Merged |
| T12 | Export, doctor and the owner-only acknowledge-restore command; backups removed | #138 | Merged |
| T13 | The conformance suite, run against every store adapter | #140 | Merged |
| T14 | CLI commands verify, doctor, export, purge, scrub, rebuild, anchor and acknowledge-restore; the git forge and ticker, and baley-bench with seed |
#142 | Merged |
#23 · milestone Evidence · done
Baley finds its per-user ledger safely, and baley init ties a repository to a project through a committed baley.toml. Baley keeps its files in its own folder under a crenshawdev vendor folder: the global settings file config.toml and the keys file keys.env in $XDG_CONFIG_HOME/crenshawdev/baley and the ledger in $XDG_DATA_HOME/crenshawdev/baley on Linux (an empty or relative XDG variable counts as unset), all three in ~/Library/Application Support/crenshawdev/baley on macOS, and all three in BALEY_HOME when it is set (ADR 0027). The ledger's home is not supported on a network share, and Baley does not check for one. Baley reads the two TOML settings files (ADR 0015) and resolves routes against a model catalog it refreshes by calling each provider's model-list endpoint with reqwest (ADR 0028). Provider keys are plain NAME=value lines in keys.env, which the owner edits by hand and Baley only reads, refusing it with keys-file-exposed when group or others can read it or another user owns it, and with keys-file-invalid when a line is invalid, a value is empty or a name appears twice, and with keys-file-unreadable when it is not a regular file or cannot be read. There is no encryption, no master key and no OS secret store. Keys reach a command only through baley exec --key; detection also reads them for provider model-list requests. Key values never enter events, views or exports. All of it runs from the command line, on Linux and macOS. This describes the completed build. ADR 0039 replaces its credential and fetching design: Build 4 T2 removed the built reader, baley exec --key and the HTTPS lister (#271).
- Designs: 0001 evidence ledger, 0002 system design, 0003 configuration and routing, 0012 host interface
- ADRs: 0003 per-user database, 0004 project identity, 0013 host session calls outside models, 0015 settings in TOML, 0027 vendor folders and plain keys, 0028 one HTTP stack
- Carries: no bugs
- Blocked by: Build 1 (#22)
flowchart LR
T1["T1: Folders, the home and the open checks"]
T2["T2: The keys file reader"]
T3["T3: baley exec --key"]
T4["T4: Settings: the schema, the two files, the merge and route resolution"]
T5["T5: The project file and discovery"]
T6["T6: baley init"]
T7["T7: The model catalog"]
T8["T8: Detection"]
T9["T9: The recorded policy"]
T10["T10: baley config show and baley config set"]
T11["T11: baley config interview"]
T12["T12: The anchor remote from the project's settings"]
T13["T13: Checkouts and forks"]
T1 --> T2
T1 --> T4
T1 --> T6
T1 --> T7
T2 --> T3
T2 --> T8
T4 --> T5
T4 --> T7
T5 --> T6
T5 --> T9
T6 --> T8
T6 --> T9
T6 --> T13
T7 --> T8
T7 --> T9
T9 --> T10
T9 --> T12
T10 --> T11
T12 --> T13
classDef done fill:#1a7f37,stroke:#116329,color:#ffffff
classDef planned fill:#eaeef2,stroke:#6e7781,color:#24292f
class T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13 done
Figure 3. Build 2's tasks. Arrows point from a task to what waits on it. One pull request per task.
| Task | What | Pull requests | Status |
|---|---|---|---|
| T1 | Folders, the home and the open checks | #149 | Merged |
| T2 | The keys file reader | #152 | Merged |
| T3 | baley exec --key |
#154 | Merged |
| T4 | Settings: the schema, the two files, the merge and route resolution | #156 | Merged |
| T5 | The project file and discovery | #158 | Merged |
| T6 | baley init |
#164 | Merged |
| T7 | The model catalog | #165 | Merged |
| T8 | Detection | #166 | Merged |
| T9 | The recorded policy | #167 | Merged |
| T10 | baley config show and baley config set |
#170 | Merged |
| T11 | baley config interview |
#171 | Merged |
| T12 | The anchor remote from the project's settings | #172 | Merged |
| T13 | Checkouts and forks | #173 | Merged |
#24 · milestone Evidence · in progress
Claude Code is the only host Baley supports in this release, and Build 3 removes Codex support. Each Claude Code session starts its own Baley MCP server over stdio, and the session's subagents reach it through the session's connection. There is no launcher, no HTTP listener and no background service, and every worker in this release is a subagent of its session. The server takes its project from CLAUDE_PROJECT_DIR, records its working directory beside it, and creates a session id that every call carries, with the host's own session id beside it when one is set. Ledger events record which caller wrote them. Each project call is prepared from the session's CLAUDE_PROJECT_DIR in the order the command line uses: a read appends nothing, and a write runs checkout admission and the host's policy step before its command. T8's capture and document are the first operations to use it. Another host can connect and list the tools, but every tool call it makes is refused with Claude Code named as the supported host. Sessions share the ledger through the store: every write takes the writer queue and decides inside its transaction (ADR 0012), and the build's acceptance includes two live Claude Code sessions writing one project at once, with the record checked afterwards. Agents can neither read nor write Baley's home or its config folder (config.toml). Claude Code's sandbox, its file permission rules and Baley's guard hook carry that together, and baley doctor reports what an agent can reach. The designed credential boundary keeps keys in the owner's environment (ADR 0039), which those folder denials do not protect. The compiled instructions are served (ADR 0009): T7 serves help, the operation schemas and the compiled instructions by identity in parts, and T8, which builds document, attaches the instruction identity a session sends on capture to the caller it records, with the version and hash taken from the registry. The build renders the stub content that baley install writes, and it opens with warnings that say what a restore cannot undo. ADR 0038 specifies one installer command into ~/.local/bin, with baley install writing every artifact at the stable path, no npm or plugin, and default setup with the interview available later. T14's development install.sh places the binary behind ~/.local/bin/baley and ends by running baley install through that path. T15's baley install writes Claude Code's wiring: the user-scope MCP registration, made through claude mcp add-json, the pre-tool hook, the sandbox and file-tool denials merged into the user settings file, and the skill stubs. Updates are off by default and opt-in. At startup, baley serve reads updates.auto once and starts the detached check without waiting when it is on. The check claims at most one check per UTC day per installation, uses SHA-256 verification against an unsigned manifest, and stages a newer version beside the old ones. The guard never checks for updates. Running servers keep their version; the next hook call follows the stable path to the new binary. T14 keeps the newer hook compatible with an older server and ledger state, and T17 qualified that combination and the live install and update paths on Linux, with the results and open items in the Build 3 notes. Manual baley update is built and can run even on a day already claimed. T14 and T17 use unsigned development artifacts only. Both delivery paths have verify_download between download and staging. The release design #14 owns the signature format, trust root and both verifiers and must fill and qualify that seam before any release. Captures are recorded.
- Designs: 0001 evidence ledger, 0002 system design, 0003 configuration and routing, 0010 guard, 0012 host interface, 0014 support families, 0015 repository upkeep and the build gate
- ADRs: 0008 host sandbox isolation, 0009 served instructions, 0011 one shared server, 0012 optimistic concurrency, 0020 sandbox is a write barrier, 0028 one HTTP stack, 0029 a host may offer more, 0033 host security bar, 0034 one server per session, 0035 restore purge uncertainty, 0036 per-user guard records, 0038 installer and opt-in updates, 0039 session-owned provider credentials
- Carries: #71, #146, #194
- Blocked by: Build 2 (#23)
flowchart LR
T1["T1: Restore warnings"]
T2["T2: Claude seam and removal"]
T3["T3: Caller provenance"]
T4["T4: Session stdio server"]
T5["T5: Request preparation"]
T6["T6: Guard decisions"]
T7["T7: Instructions and parts"]
T8["T8: Captures"]
T9["T9: Bounded guard access"]
T10["T10: Guard records and answers"]
T11["T11: Claude artifact content"]
T12["T12: Live Claude qualification"]
T13["T13: Runtime doctor"]
Delivery["Delivery design: ADR 0038 and 0039"]
T14["T14: Binary delivery with unsigned development artifacts"]
T15["T15: Artifact application"]
T16["T16: Setup entry"]
T17["T17: Installed doctor and unsigned development qualification"]
Release14["#14: Format, trust root and both verifiers after Builds 1 to 9"]
Verified["Verified delivery for release"]
T1 --> T2
T2 --> T3
T2 --> T6
T3 --> T4
T4 --> T5
T4 --> T9
T4 --> T14
T5 --> T7
T5 --> T10
T6 --> T9
T7 --> T8
T8 --> T11
T9 --> T10
T10 --> T11
T11 --> T12
T11 --> T13
T11 --> T15
T12 --> T14
T12 -. evidence .-> T13
Delivery --> T14
T13 --> T17
T14 --> T15
T15 --> T16
T16 --> T17
T14 --> Release14
T17 --> Release14
Release14 --> Verified
classDef done fill:#1a7f37,stroke:#116329,color:#ffffff
classDef progress fill:#9a6700,stroke:#7d4e00,color:#ffffff
classDef planned fill:#eaeef2,stroke:#6e7781,color:#24292f
class T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12 done
class Delivery done
class T13 done
class T14,T15,T16,T17 done
class Release14,Verified planned
Figure 4. Build 3's tasks. Arrows point from a task to what waits on it. The dotted arrow is an evidence link. T14 to T17 are merged (#250, #253, #257, #262). T14 and T17 use unsigned development artifacts only. #14 fills and qualifies T14's verify_download seam before delivery can release verified artifacts; its other build dependencies are listed under R1. One pull request per Build 3 task.
| Task | What | Pull requests | Status |
|---|---|---|---|
| T1 | Explain purge uncertainty after a restore | #176 | Merged |
| T2 | Claude host seam and Codex removal | #182 | Merged |
| T3 | Caller provenance in the ledger | #183 | Merged |
| T4 | Per-session stdio server and store maintenance | #189 | Merged |
| T5 | Per-request discovery, admission and policy | #191 | Merged |
| T6 | Guard decisions and protected paths | #196 | Merged |
| T7 | Compiled instructions, help, schemas and parts | #199 | Merged |
| T8 | Ledger captures and project identity reads | #202 | Merged |
| T9 | Bounded guard process and storage access | #204 | Merged |
| T10 | Per-user guard records and Claude hook answers | #207 | Merged |
| T11 | Claude artifact content, logical stubs and supplied executable-path protection | #228 | Merged |
| T12 | Live Claude qualification and concurrent sessions. Run on 2026-10-08 against Claude Code 2.1.294 in three runs kept in spikes/host-matrix: the first sheet is claude-live-2026-10-08-run1.md, the rerun after the fixes for issues #231 and #232 is claude-live-2026-10-08-run2.md, and the final run, against commit 7c8ca4c3 after changes to the procedure, is claude-live-2026-10-08-run3.md. The two defects the first run showed are claude-live-2026-10-08-run1.md#exit.session-a and claude-live-2026-10-08-run1.md#hand.parts.document-main, and the rerun passes both (claude-live-2026-10-08-run2.md#exit.session-a, claude-live-2026-10-08-run2.md#hand.parts.document-main). No barrier failed: the Bash, Read, Write and Edit rows for the home and the config folder pass (claude-live-2026-10-08-run1.md#bar.home.bash-read, claude-live-2026-10-08-run1.md#bar.home.bash-write, claude-live-2026-10-08-run1.md#bar.home.read-tool, claude-live-2026-10-08-run1.md#bar.home.write-tool, claude-live-2026-10-08-run1.md#bar.home.edit-tool, claude-live-2026-10-08-run1.md#bar.config.bash-read, claude-live-2026-10-08-run1.md#bar.config.bash-write, claude-live-2026-10-08-run1.md#bar.config.read-tool, claude-live-2026-10-08-run1.md#bar.config.write-tool, claude-live-2026-10-08-run1.md#bar.config.edit-tool). The final run found no defect. It passes Grep and Glob over each folder and over its parent, in a session launched with --allowedTools Grep,Glob because Claude Code 2.1.294 leaves both tools out of its default tool list, and the guard refused every call (claude-live-2026-10-08-run3.md#bar.home.grep-folder, claude-live-2026-10-08-run3.md#bar.home.grep-parent, claude-live-2026-10-08-run3.md#bar.home.glob-folder, claude-live-2026-10-08-run3.md#bar.home.glob-parent, claude-live-2026-10-08-run3.md#bar.config.grep-folder, claude-live-2026-10-08-run3.md#bar.config.grep-parent, claude-live-2026-10-08-run3.md#bar.config.glob-folder, claude-live-2026-10-08-run3.md#bar.config.glob-parent, claude-live-2026-10-08-run3.md#ctl.grep-parent-guard, claude-live-2026-10-08-run3.md#ctl.glob-parent-guard). It also passes the hook on Grep, Glob, Write, Edit and NotebookEdit (claude-live-2026-10-08-run3.md#ctl.hook.grep, claude-live-2026-10-08-run3.md#ctl.hook.glob, claude-live-2026-10-08-run3.md#ctl.hook.write, claude-live-2026-10-08-run3.md#ctl.hook.edit, claude-live-2026-10-08-run3.md#ctl.hook.notebookedit), the user-scope registration in an isolated configuration, whose three tools were callable without a tool search in the main session and a subagent (claude-live-2026-10-08-run3.md#id.user-scope.startup, claude-live-2026-10-08-run3.md#hand.tools.user-main, claude-live-2026-10-08-run3.md#hand.tools.user-subagent), and the skill from both placements (claude-live-2026-10-08-run3.md#hand.skill-listed, claude-live-2026-10-08-run3.md#hand.skill-run, claude-live-2026-10-08-run3.md#hand.skill-project-listed, claude-live-2026-10-08-run3.md#hand.skill-project-run). Acceptance left open or unverified: keys and detection, because Build 4 T2 removed the key reader, the credential wrapper and the model lister the row would exercise (#271) (claude-live-2026-10-08-run3.md#hand.keys-detection); the restore report, which failed on one step, since a repeated acknowledge-restore is a new request that exits 1 with "already acknowledged" and prints no purge warning, so whether a replayed acknowledgement carrying the warning is reachable from the command line is open (claude-live-2026-10-08-run3.md#hand.restore-report); the PowerShell reads, writes, hook and recorded ask, because pwsh was absent in every run (claude-live-2026-10-08-run3.md#bar.home.ps-read, claude-live-2026-10-08-run3.md#ctl.hook.powershell, claude-live-2026-10-08-run3.md#ctl.powershell-ask); the .git/HEAD fallback, since with git off PATH the guard asked about unreadable settings and never reached the fallback path (claude-live-2026-10-08-run1.md#ctl.fallback-head); a hook timeout, since no guard call reached 10,000 ms and the highest took 49 ms (claude-live-2026-10-08-run3.md#ctl.timeout-not-denial, claude-live-2026-10-08-run3.md#ctl.latency); a live redelivery, since no tool_use_id arrived twice (claude-live-2026-10-08-run3.md#ctl.redelivery); the burst of calls in flight at exit, since Claude Code held /exit until the turn ended and no call was inside the server (claude-live-2026-10-08-run2.md#exit.burst); the guard's own deny of a Write to a protected file, since the Edit deny rule refused that Write before the hook ran (claude-live-2026-10-08-run1.md#ctl.write-baleytoml-denied); the Edit rule's reach over NotebookEdit, which the read-first check refused first (claude-live-2026-10-08-run1.md#bar.home.notebook-edit); host-specific settings, since neither config file had a host section to list (claude-live-2026-10-08-run1.md#hand.config-show); and the arrival of served-answer parts after part 1, since only part 1 was read (claude-live-2026-10-08-run2.md#hand.parts.document-main) |
#236 | Merged |
| T13 | Runtime doctor host observations | #237 | Merged |
| T14 | Binary delivery, ledger update claims and events, version-folder protection and update compatibility using unsigned development artifacts only; leave verify_download between download and staging for #14's verifiers |
#250 | Merged; released delivery depends on #14 |
| T15 | Claude artifact ownership and application | #253 | Merged |
| T16 | Owner setup: final summary lists every file, then yes records provider acknowledgement, writes API-host allowances through the installation writer, writes global review.reviewers, and runs settings config set in order. Stop on failure, report completed writes and permit safe rerun |
#257 | Merged |
| T17 | Delivery doctor and installed qualification with unsigned development artifacts only, including newer-hook/older-server compatibility. The doctor takes --host and reports the install outcome, the hook and settings against what install writes, stale and older stubs, the stable path's version, writable locations, provider hosts, acknowledgements and the effective updates.auto, with a fix on every finding. The installed run of 2026-10-11 against Claude Code 2.1.296 is spikes/host-matrix/install-live-2026-10-11-run1.md, and a shell-only repeat of the install rerun after three fixes is install-live-2026-10-11-run2.md. The run left open the live repeat of the older-server fix (#258), which passed at Build 4 T3's raise of the view set to 9 (older-server-live-2026-10-15.md), Grep and Glob on Baley's home and config folder and the installed hook in bypass-permissions mode in a live session, whether a running session finds a newly written stub and the Bash read of Baley's home folder (both rest on the session's answer), and #190 |
#262 | Merged; released-artifact verification and its qualification belong to #14 |
#25 · milestone Evidence · in progress
The owner starts a project, shapes the story backlog, and commits stories to phases under a task capacity. Each story carries versioned truths, and each truth has one check. The analyzer and the planner ask the owner only the decisions left to the owner, each with a recommended answer, in rounds ordered by what each question depends on, and every answer and deferral is recorded (ADR 0030). Each phase's plan is written, checked, reviewed and risk-scanned, and approval binds the plan's exact digest. Every configured reviewer runs, and a provider that cannot be called is replaced by the host's own subagent reviewer unless that reviewer already runs. The host session makes the outside calls from Baley's work order and checks each finding, and the owner rules on each one that survives (ADR 0013, ADR 0019). The first workers are dispatched here, so routing is finished here. The first dispatch task supplies Claude Code's identity rung map and a dated per-model table of supported effort levels. Claude Code runs an unsupported level as the highest supported level at or below it, and a model without effort is not applicable. The route records the requested rung and the effective level apart. RungMap is unchanged, and the owner reviews the initial table in that task's pull request.
Build 4 owns baley models import, the provider-list fetch work order and models-return, and checks the current provider acknowledgement before issuing review or fetch work. These depend on Build 3 T16's provider choice and typed acknowledgement in the ledger. T16 added the setup reader and writer of review.reviewers; Build 4 adds the review consumer. Build 4 also implements tier selection: an explicit setting, then the owner's entry for the tier, otherwise the newest accepted catalog id tagged for it by created date, then hint order, with the catalog record extension in 0003. Build 4 T2 removed the built keys.env reader, the baley exec --key credential wrapper, the HTTPS model lister and the credential lookup, and switched baley init from detection to seeding (#271). The pure catalog parsing, classification, tagging, diff and event code stays.
Build 4 implements PLN-R16's full and diff plan re-check inputs, the setting's first reader and validation, immutable material for each round, and the scope recorded in plan-check and plan-review events and views. Design 0005 leaves the way the checker's revision and a plan review's revision combine for one plan as an open question owned by Build 4.
Build 4 adds the check level, unit or integration, to the evidence map grammar and serves the planner the integration rules of 0005 section 10: an integration check where a truth's outcome depends on two or more of the project's own units working together, with only outside boundaries mocked, each behind an interface the project owns (ADR 0042).
- Designs: 0001 evidence ledger, 0002 system design, 0003 configuration and routing, 0004 starting a project and changing scope, 0005 context, plans and acceptance, 0008 review, 0009 risk, 0012 host interface, 0014 support families
- ADRs: 0013 host session calls outside models, 0017 stories and sprints, 0019 reviews adjudicated and ruled, 0030 question rounds, 0031 one term per concept, 0037 plan re-check scope, 0039 session-owned provider credentials, 0042 mocked-boundary integration checks, 0043 submissions recorded as drafts, 0044 owner acts on the command line
- Carries: #40, #68, #69, #72
- Blocked by: Build 3 (#24)
flowchart TD
T1["T1: Git error redaction"]
T2["T2: Key removal and seeding"]
T3["T3: Scope records and approval"]
T4["T4: Scope and description changes"]
T5["T5: Routing and first dispatch"]
T6["T6: Question rounds"]
T7["T7: Refinement and reads"]
T8["T8: Plan grammar"]
T9["T9: Phase commitment and plan approval"]
T10["T10: Checker and re-check"]
T11["T11: Lease risk and git facts"]
T12["T12: Tiers and model lists"]
T13["T13: Review admission and returns"]
T14["T14: Rulings and approval gate"]
T15["T15: Live planning run"]
B3T15["Build 3 T15: Installation"]
B3T16["Build 3 T16: Owner setup"]
B3T17["Build 3 T17: Installed qualification"]
T1 --> T2
T1 --> T3
T3 --> T4
T3 --> T5
T3 --> T6
T4 --> T7
T5 --> T7
T6 --> T7
T6 --> T8
T4 --> T9
T5 --> T9
T7 --> T9
T8 --> T9
T9 --> T10
T9 --> T11
T10 --> T11
T2 --> T12
T5 --> T12
T10 --> T13
T11 --> T13
T12 --> T13
T11 --> T14
T13 --> T14
T14 --> T15
B3T15 -.-> T5
B3T16 -.-> T2
B3T16 -.-> T11
B3T16 -.-> T12
B3T16 -.-> T13
B3T17 -.-> T15
classDef done fill:#1a7f37,stroke:#116329,color:#ffffff
classDef progress fill:#9a6700,stroke:#7d4e00,color:#ffffff
classDef planned fill:#eaeef2,stroke:#6e7781,color:#24292f
class B3T15,B3T16,B3T17 done
class T1,T2 done
class T3 progress
class T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15 planned
Figure 5. Build 4's tasks. Arrows point from a task to what waits on it, and a dotted arrow is a wait on a Build 3 task. Build 3 T14 to T17 are merged (#250, #253, #257, #262). One pull request per Build 4 task.
| Task | What | Pull requests | Status |
|---|---|---|---|
| T1 | Redact git error text | #268 | Merged |
| T2 | Remove the key paths and seed the catalog at init | #271 | Merged |
| T3 | Scope records and approval | In progress | |
| T4 | Scope changes | Planned | |
| T5 | Routing, work orders and the first dispatch | Planned | |
| T6 | Question sets and rounds | Planned | |
| T7 | Refinement and versioned truths | Planned | |
| T8 | Plan grammar, evidence map and the planner's rules | Planned | |
| T9 | Phase planning, drafts and plan approval | Planned | |
| T10 | The plan checker and re-check scope | Planned | |
| T11 | Risk at plan submit and git facts in the transaction | Planned | |
| T12 | Tier selection and session model lists | Planned | |
| T13 | Review admission, work orders and returns | Planned | |
| T14 | Adjudication, rulings and the plan review's second round | Planned | |
| T15 | Live planning run on Claude Code | Planned |
#26 · milestone Evidence · planned
Baley runs a phase's tasks and runs every test and check itself, judging by exit code (ADR 0014). A task close is refused for any path outside the lease until the owner rules on it (ADR 0018). Build 5 also supplies the active dispatch's lease to the guard's write decision, whose only lease input until then is "no active dispatch", and adds the out-of-lease deny (GRD-R11, EXE-R8). The verifier gets specs and run ids, never the executor's summary. Diff review and the completion risk scan gate each plan. A fix ruling opens a gap plan, and a finding is filed on GitHub only on the owner's command. A returning finding the owner dismissed before is brought back beside that dismissal, and the owner confirms or reverses it.
Build 5 constructs the full revised targets for diff and completion risk review re-checks, including the original reviewed changes and completed gap-plan fixes.
Build 5 serves the verifier the VER-R6 rule that rejects an integration check mocking one of the project's own units it claims to run together. Integration checks need no other execution change: they run red then green like any check, and the plan-close suite runs them as part of the project's test command (ADR 0042).
- Designs: 0002 system design, 0006 execution, 0007 verification, 0008 review, 0009 risk, 0012 host interface
- ADRs: 0014 Baley runs tests, 0018 lease enforced at close, 0019 reviews adjudicated and ruled, 0037 plan re-check scope, 0042 mocked-boundary integration checks
- Carries: no bugs
- Blocked by: Build 4 (#25)
#27 · milestone Evidence · planned
Milestones close and archive. A finished phase lands on GitHub one step at a time, and each push, pull request, merge, tag and cleanup needs its own owner authorization. Landing waits while a deferred review is unruled. The managed project's releases are proposed and confirmed. Undo and pause work. Anchors are pushed at every occasion the design names.
- Designs: 0001 evidence ledger, 0003 configuration and routing, 0004 starting a project and changing scope, 0008 review, 0011 milestones, landing, undo and pause
- ADRs: 0007 forge anchors, 0031 one term per concept
- Carries: #68, its landing part: git's error text in
landing/effects.rsand the remote URLs landing shows go throughcheckout::redact_git_text - Blocked by: Build 5 (#26)
#28 · milestone Evidence · planned
Baley answers what to do next and shows progress from keyed ledger views. A status read never writes.
- Designs: 0013 next action and progress, 0014 support families
- ADRs: 0031 one term per concept
- Carries: no bugs
- Blocked by: Build 6 (#27)
#29 · milestone Evidence · planned
Ranked recall and exact "why" queries, then task, debug and spike on the ledger. Purge also removes search rows. Baley runs each debug reproduction itself: red before any hypothesis, and green at resolve over reproduction files byte-identical to the red run's. The owner can close an episode that never reproduced, with a reason. Debug gets the diagnosis review. A spike works outside the project and commits nothing.
- Designs: 0001 evidence ledger, 0008 review, 0013 next action and progress, 0014 support families
- ADRs: none
- Carries: no bugs
- Blocked by: Build 7 (#28)
#30 · milestone Evidence · planned
Removes the old JSON record, the intent journal, participants, root binding, the Markdown renderers and parsers, and every .planning path. Builds baley show and record export to Markdown (EVD-R25), with the record-export spelling settled beside the standalone project export. Every owner command and every served instruction then reads the ledger. It also deletes the parked review engine (crates/baley/src/inherited.rs and the review code only it reaches), including its credentials reader (crates/baley/src/review/provider/credentials.rs), which still reads environment keys and providers.env. The real server's memory, start time and main operations are measured against design 0001's budgets. The timings are recorded as measurements, not test assertions.
- Designs: 0001 evidence ledger, 0012 host interface, 0014 support families
- ADRs: 0006 no Markdown records, 0009 served instructions
- Carries: #93
- Blocked by: Build 8 (#29)
#14 · milestone Traders · not written · blocked
The tag gate (on main, CI green, version matches the crate). Static, reproducible Linux and macOS archives, refused if a checksum differs from the committed pin. Signed artifacts and provenance attestations. Release notes and whether a CHANGELOG starts. How releases relate to forge anchors and tag rules. This work owns the signed checksum manifest's signature format and trust root, both verifier implementations (the installer's available before Baley exists and the updater's), and their qualification. It fills T14's named verify_download seam between download and staging in both delivery paths. T14 and T17 will have built and qualified delivery with unsigned development artifacts only; no release exists before #14 completes verification. Installation follows ADR 0038: one installer command, binary-written wiring at the stable path, and opt-in verified updates for new server sessions, with the hook taking the new stable-path version at its next call. Provider access follows ADR 0039, with no Baley key file or provider call. #14 must name any new signature-verification dependency; none is selected yet. It also picks the first version number.
Blocked by Builds 1 to 9 and by every issue in Other open issues except the Build 3 issues #190, #203, #214, #219, #220, #221, #227, #235, #238 to #249, #251, #252 and #254 to #256.
Planned. One throwaway Rust project on Claude Code, with its own private GitHub repository, taken through the whole loop from starting the project to a landed change. Anything that breaks is fixed as a bug with its own unit test. No end-to-end tests are added to the suite. A written list records what is knowingly left untested. The host matrix (EVD-R24) and the server measurements are re-run. The run is defined in #14, which leaves open whether it gates every release or only the first.
Planned. Publish Baley and install it on a machine for Claude Code. Milestone Traders. It has no issue of its own.
Every issue here except the Build 3 issues blocks the release design #14. GitHub links none of the twenty-five Build 3 issues to #14. "Carried by" means that build does the fix.
| Issue | What | Milestone | Depends on / blocks |
|---|---|---|---|
| #44 | Start the architecture overview | Evidence | None |
| #54 | List the slow tests; read what the suite's count is made of | Encyclopedists | None |
| Issue | What | Milestone | Depends on / blocks |
|---|---|---|---|
| #40 | Read a command's cheap git facts inside the write transaction | Evidence | Carried by Build 4 |
| #68 | Git error text is stored and shown unredacted (URL credentials) | Evidence | Carried by Build 4 (built paths) and Build 6 (landing) |
| #69 | model.escalate_on_failure never applies to automatic retries |
Evidence | Carried by Build 4 |
| #72 | The provider schema accepts whitespace-only text the validator refuses | Evidence | Carried by Build 4 |
| #93 | The audit admits any bold span as a requirement id and skips unreadable rows | Evidence | Carried by Build 9 |
| #70 | Forgejo tracker calls pass the host as tea's --login name |
None | No build carries it |
| Issue | What | Milestone | Depends on / blocks |
|---|---|---|---|
| #190 | baley serve drops calls it already read when input closes in the same burst |
Evidence | T17 owns it: it runs the installed server live and fixes a confirmed defect in its own bug pull request. The 2026-10-11 installed run ended Claude Code's process with SIGTERM on its first baley_apply call: the one call sent was recorded exactly once (install-live-2026-10-11-run1.md#exit.r1.answered) and Claude Code saw the connection close before the answer arrived (install-live-2026-10-11-run1.md#exit.condition). That capture was recorded 1.4 ms before the signal, so under the rule corrected after the run no call is shown open inside the server, and the server's standard error did not reach the debug log, so no drain line could be seen (install-live-2026-10-11-run1.md#exit.r1.stderr). No dropped call was confirmed and no bug pull request was filed, so the in-flight check stays unverified. T12 merged in #236 without reproducing it. The 2026-10-08 runs confirmed no dropped call: every call the server read was answered and no drain line appeared, but no call was in flight inside the server at exit, so the check is unverified (claude-live-2026-10-08-run2.md#exit.burst). They found a different shutdown defect, #231, fixed in bug pull request #233 |
| #203 | An export through a store opened for the guard waits without limit for the new copy's writer queue | Evidence | Its text names no build |
| #214 | A half-written transport error line can be interleaved by another reply | Evidence | Its text names no build |
| #219 | Bug: the guard never judges a commit that has anything in front of git |
Evidence | Its text names no build |
| #220 | Design: decide what the guard does with a commit or push it declines to read | Evidence | Its text names no build |
| #221 | Enhancement: judge a commit after a plain cd at the directory it names instead of asking |
Evidence | Its text says to build it with #219 |
| #227 | A case-variant spelling lets a stub take the executable's or another artifact's file on a case-insensitive filesystem | Evidence | Its text names no build |
| #235 | The live restore script does not refuse a symlinked results folder or ledger, so it can delete a database outside the disposable root | Evidence | Its text names no build |
| #238 | A downloaded manifest's version text is split into every dot-separated part before the part count is checked, so a huge malformed version can exhaust memory instead of being refused | None | Its text names no build |
| #239 | Joining a relative link target to the link's folder keeps bin/../ in the path, so a stable link the kernel resolves can fail with a name-too-long error under a very long HOME |
None | Its text names no build |
| #240 | Rollback exchanges with the stable entry without confirming it is still this attempt's link, then deletes what it displaced, which can destroy an owner's newer replacement | None | Its text names no build |
| #241 | The lease check before activation is a point-in-time check, so an attempt that loses its claim after it can still activate | None | Its text names no build |
| #242 | The new link is published and its folder synced before the displaced entry is checked, so a conflicting activation can become durable if the updater dies before rollback | None | Its text names no build |
| #243 | The staged-binary check reads the file owner's execute bit, not whether the installing user can run the file | None | Its text names no build |
| #244 | A stale claim holder can still activate after another check takes over its lease | None | Its text names no build |
| #245 | The activation rollback can delete a replacement the owner put at the stable path during the rollback | None | Its text names no build |
| #246 | A retry that finds an already published staged binary skips the folder syncs a failed earlier attempt did not finish | None | Its text names no build |
| #247 | install.sh's final staging move can overwrite a different binary another installer placed after the existence check |
None | Its text names no build |
| #248 | install.sh checks only the staged file, so a version folder that is a symbolic link can place the binary outside the versions folder |
None | Its text names no build |
| #249 | install.sh's temporary-link check strips trailing newlines from readlink, so a crafted directory link can pass it |
None | Its text names no build |
| #251 | Between install's recheck of mcpServers.baley and claude mcp remove, another writer can change the entry, so the removal can delete an entry install did not judge |
None | Its text names no build |
| #252 | With nothing runnable at the stable path, install withholds the new guard hook but still removes a recorded older hook | None | Its text names no build |
| #254 | The interview's test for no write and no store open before the owner confirms calls only the conversation step, not the command, so it cannot catch either | None | Its text names no build |
| #255 | A rerun of the interview cannot finish a reviewer-list step that failed after the global file was replaced | None | Its text names no build |
| #256 | A failed sync of the settings file's folder after the provider-host write is reported as success, so the later writes go ahead | None | Its text names no build |
Counts from GitHub on 2026-10-12. #238 to #249, #251, #252 and #254 to #256 have no milestone. Evidence shows 45 closed and 21 open issues, and Encyclopedists six closed and one open.
| Milestone | Theme | Closed | Open | Open issues | State |
|---|---|---|---|---|---|
| Evidence | Replace the JSON store with one designed from how records are read and written, and move it out of the repository's .planning directory. | 45 | 21 | Builds 3 to 9, bug #40, #44, #68, #69, #72, #93 and Build 3 issues #190, #203, #214, #219, #220, #221, #227 and #235 | Open |
| Encyclopedists | Keep the repository's names, public face and build gate accurate: Baley names throughout, formatting, labels, description and topics, the README, and what the test suite costs. | 6 | 1 | #54 | Open |
| Traders | Publish Baley and install it on a machine for Claude Code, after a live run of the whole loop. | 0 | 1 | #14 | Open |
| Seldon | Bring a new or existing repository under Baley and write its first requirements and roadmap. | 1 | 0 | None | Closed |
| Mule | Change what was approved: edit or withdraw a phase, move its requirements, revise a truth or a requirement, keeping every earlier version on record. | 1 | 0 | None | Closed |
| Little Lost Robot | What an agent may touch: how a task's file lease is enforced, and whether Baley edits source itself. | 2 | 0 | None | Closed |
| Terminus | Open the repository to the public: a README for visitors, a security policy, issue templates, and branch protection with no bypass. | 2 | 0 | None | Closed |
What the records leave open or do not say.
- Builds 5 to 9 have no task breakdown. Each lists the design requirements it delivers, and all but Build 7 add a short list of settled points.
- There is no first version number. The release design #14 picks it.
- #44 was meant to land before Build 1 T10, which has merged. No order is given for bug #70.
- The board's Status field is set only on the build issues, #40 and #14.
- The release design #14 owns the signed checksum manifest's signature format, trust root and both verifiers, including qualification and any new dependency. Both
install.shand the updater now check SHA-256 against an unsigned manifest inverify_downloadbefore staging. T14 and T17 use unsigned development artifacts only, and nothing is released before #14 supplies and qualifies signature verification. Removing old versions also belongs to #14. - Build 3 T14 now provides
baley update, the opt-in detached check started bybaley serve, the developmentinstall.sh, ledger update claims and events, and staged binaries at~/.local/lib/crenshawdev/baley/versions/<version>/baley. The placement map projects the versions folder for write-only protection, and the security proposal renders its denials. T14 leaves the view set at 7 and records update events only inuser, adding no event type to the session's project. T17 qualified the live install script, the update path and a newer stable-path hook beside an older running server and its ledger state; its bullet below holds the results. T11 supplies the installed executable path to the protected-path projection. - Build 3 T15 provides
baley install [--host claude-code], which writes Claude Code's wiring at the stable path. The Claude folder isCLAUDE_CONFIG_DIRwhen it is set, else~/.claude, and one derivation of the stable path and the Claude folder serves install, the live guard and the doctor. Install writes the user settings file<Claude folder>/settings.jsonwith the pre-tool hook, thepermissions.denyrules and the sandbox block merged into the owner's settings, the skill stubs under<Claude folder>/skills/, and the user-scope MCP registration, which it has Claude Code write throughclaude mcp add-jsonand never writes itself. It replaces an artifact only when this binary's own render orinstall.recordedshows Baley wrote it. Otherwise it refusesinstall-ownership-conflictorinstall-settings-conflictbefore any write. Then it seeds the catalog and recordsinstall.recordedinuser. Theinstallview holds those records, so the view set rises from 7 to 8, and a binary built before T15 is read-only onuseronce a newer binary has brought its views to 8. The live guard now protects the placed stubs, the settings file, the registration file and the executable, and the versions folder as write-only. The doctor judges only what the install record shows, so a machine that never ran install still reports every artifact as not installed. An owner setting that weakens protection, a missingbwraporsocaton Linux, or nothing runnable at the stable path makes the install partial: the receipt names each gap with its fix and the command exits 1. Install writes nothing toconfig.toml. T16 builds on the settings file and the install record, as the next bullet says. T17's doctor reads the derived placements and the record in its installed-result checks, and the live install and Claude Code sessions on the written wiring ran in T17's qualification. Two cases are filed and not closed: a registration changed between install's check and its removal of the old entry (#251), and an older recorded hook removed while nothing runnable is at the stable path (#252). - Build 3 T16 provides the owner's setup entry in
baley config interview. After the thirteen settings questions the interview asks which outside review providers to use,openai,deepseekornone, and a blank answer keeps the stored choice. It shows design 0003's provider warning for each provider named and needs a typedyesto each, and it refusesowner-identity-missing, before the summary, when git has nouser.name. The summary lists every file the confirmed writes can change or create. After the finalyesfour writes run in order, and a step with nothing to change is skipped. First,providers.acknowledgedis recorded in the per-user projectuser, with the providers, the warning version and its SHA-256, gituser.nameand the time; a current acknowledgement is reused, and no view is added, so the view set stays at 8 and a binary built before T16 cannot writeuseronce it holds the event. Second, each provider's API host,api.openai.comorapi.deepseek.com, is added tosandbox.network.allowedDomainsin Claude Code's settings file through the digest-checked replacement, with no install lock, noinstall.recordedand noclaudecommand. Third, the globalreview.reviewersis written, and fourth, the settings answers go through the apply functionconfig setuses.review.reviewersis now in the settings schema, default["host"], with the interview as its setup reader and writer, andconfig setrefuses itlist-not-settable. A failure stops the run, prints its code and the writes already completed, and a rerun finishes only what is missing.baley installis unchanged: it records no acknowledgement and keeps every host the interview added. T16 hands Build 4 the recorded acknowledgement andreview.reviewersfor its review and fetch checks, and hands T17 the written settings and the install record, whose settings digest predates the file once the host step has run and is not drift. Enforcing the acknowledgement at issuance stays with Build 4. - Build 3 T17 provides
baley doctor --host <name>, defaultclaude-code, which refuses an unknown hostunknown-hostwith exit 2 before the ledger opens, and the delivery checks over whatbaley installandbaley config interviewwrote. The doctor reports a partial install and a held-back sandbox block as gaps, a hook install withheld, the placed hook and settings against the whole entries install renders and the record holds, each stub the record lists that the binary no longer ships as stale, an older stub Baley placed, the version the stable path links to, the writability of each folder install writes into, the provider hosts the settings allow, each provider's acknowledgement and the effectiveupdates.auto, with a fix on every finding. It never compares the settings digest, so the interview's provider hosts are not drift, and it reads no running session's version. The installed run of 2026-10-11 used Claude Code 2.1.296 on Linux with unsigned development artifacts served from a throwaway branch of this repository. It showed a new session loading the server, the hook and the stubs, a running session reporting that it found a newly written stub at its next turn (that report and the new session's list of stubs rest on the session's answer, not on a file, the ledger or a receipt, and are unverified), protection of Baley's folders (the Bash read of the home folder rests on the session's quote of thecatand is unverified), the versions folder and the stable path, the manual and opt-in updates, the install rerun and a newer hook beside an older server (spikes/host-matrix/install-live-2026-10-11-run1.md). It found three defects: the older server could not write its own project onceuserwas at a newer view set (#258, fixed by #260), install left a retired stub's file on disk (#259, fixed by #261), and the doctor called Baley's own older stub foreign (commitd95f482a, in this task's code). A repeat of the install rerun after those fixes passes (spikes/host-matrix/install-live-2026-10-11-run2.md). Open after the run: the live repeat of #258's fix, owed at the next raise of the view set and run at Build 4 T3's raise to 9, where it passed (spikes/host-matrix/older-server-live-2026-10-15.md); Grep and Glob on Baley's home and config folder and the installed hook in bypass-permissions mode are unverified in a live session, as are whether a running session finds a newly written stub and the Bash read of the home folder, which rest on the session's answer; #190 is unverified; macOS was not run; signatures and release belong to #14. Build 3 stays open until T17 lands.