Skip to content

Latest commit

 

History

History
504 lines (410 loc) · 64.1 KB

roadmap.md

File metadata and controls

504 lines (410 loc) · 64.1 KB

Roadmap

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.

The path to the first release

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
Loading

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

Build 1: Foundation

#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
Loading

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

Build 2: Identity, settings and keys

#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).

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
Loading

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

Build 3: Hosts

#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.

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
Loading

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

Build 4: Planning

#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).

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
Loading

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

Build 5: Doing the work

#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).

Build 6: Milestones, landing, undo and pause

#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.

Build 7: Next action and progress

#28 · milestone Evidence · planned

Baley answers what to do next and shows progress from keyed ledger views. A status read never writes.

Build 8: Search, why and support work

#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.

Build 9: Removal

#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.

Release

R1. Release design

#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.

R2. Live acceptance run on Claude Code

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.

R3. Publish and install

Planned. Publish Baley and install it on a machine for Claude Code. Milestone Traders. It has no issue of its own.

Other open issues

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.

Upkeep and docs

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

Bugs

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

Build 3 issues

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

Milestones

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

Not yet decided

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.sh and the updater now check SHA-256 against an unsigned manifest in verify_download before 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 by baley serve, the development install.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 in user, 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 is CLAUDE_CONFIG_DIR when 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.json with the pre-tool hook, the permissions.deny rules 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 through claude mcp add-json and never writes itself. It replaces an artifact only when this binary's own render or install.recorded shows Baley wrote it. Otherwise it refuses install-ownership-conflict or install-settings-conflict before any write. Then it seeds the catalog and records install.recorded in user. The install view holds those records, so the view set rises from 7 to 8, and a binary built before T15 is read-only on user once 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 missing bwrap or socat on 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 to config.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, deepseek or none, and a blank answer keeps the stored choice. It shows design 0003's provider warning for each provider named and needs a typed yes to each, and it refuses owner-identity-missing, before the summary, when git has no user.name. The summary lists every file the confirmed writes can change or create. After the final yes four writes run in order, and a step with nothing to change is skipped. First, providers.acknowledged is recorded in the per-user project user, with the providers, the warning version and its SHA-256, git user.name and 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 write user once it holds the event. Second, each provider's API host, api.openai.com or api.deepseek.com, is added to sandbox.network.allowedDomains in Claude Code's settings file through the digest-checked replacement, with no install lock, no install.recorded and no claude command. Third, the global review.reviewers is written, and fourth, the settings answers go through the apply function config set uses. review.reviewers is now in the settings schema, default ["host"], with the interview as its setup reader and writer, and config set refuses it list-not-settable. A failure stops the run, prints its code and the writes already completed, and a rerun finishes only what is missing. baley install is unchanged: it records no acknowledgement and keeps every host the interview added. T16 hands Build 4 the recorded acknowledgement and review.reviewers for 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>, default claude-code, which refuses an unknown host unknown-host with exit 2 before the ledger opens, and the delivery checks over what baley install and baley config interview wrote. 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 effective updates.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 the cat and 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 once user was 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 (commit d95f482a, 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.