Artifact 9fa561b89d20b3b1fc102cdad2dfb351ef30e178a291492a2a59b38933f6afa1:
- File
docs/RELEASE-0.1.0-PLAN.md
— part of check-in
[122998a428]
at
2026-07-18 20:12:07
on branch release-0.1
— Add BSD-2-Clause LICENSE, ship it in .paths, drop scratch file, ignore the pattern
A release without a license grants nobody any rights, so this is the legally gating step of the 0.1.0 sequence. zit is an independent reimplementation from the Fossil RFCs rather than a derivation of Fossil source, so the choice was open; BSD-2-Clause matches the Fossil heritage and the systems-Zig ecosystem.
What changed:
- LICENSE at the repo root, BSD 2-Clause, copyright Daniel Mestas 2026. - build.zig.zon .paths now names LICENSE, so the file actually ships inside a fetched package instead of only existing in the checkout. - The leftover commit-description-413190fb92be991f.txt scratch file is gone and .fossil-settings/ignore-glob carries commit-description-* so the class of file cannot drift back in. - src/packaging_test.zig pins the above as executable facts: LICENSE content, LICENSE named inside the manifest's brace-matched .paths block, a line-anchored ignore-glob pin, and a negative-space pin asserting every repo-root path build.zig embeds is also named in .paths. These acceptance criteria are file-structure facts, which rot silently because nothing executes them; the battery alone cannot catch a .paths regression. - build.zig grows build_unit_test_module: the pinned repository files attach as anonymous imports to a test-only compile of root.zig, never to the exported zit module. Attaching them to zit made every consumer's build depend on files outside .paths and a fetched package failed on a missing .fossil-settings/ignore-glob before compiling a line. The negative-space pin exists to catch exactly that recurrence. - docs/RELEASE-0.1.0-PLAN.md, the plan of record for the 0.1.0 release, is committed alongside the first step it describes.
Test evidence: zig build and zig build test green in the working checkout. This commit is additionally gated on a clean-checkout proof — fossil open into a fresh temp directory, then zig build and zig build test there — which is the check that catches a file referenced but never added.
No borrowed techniques in this change, so no attribution is owed. (user: dmestas, size: 25969) [annotate] [blame] [check-ins using]
# zit 0.1.0 — Release Plan **STATUS: FINAL** *(armed — the release workflow may run. The workflow preflight refuses to run against a DRAFT plan. Flipping to FINAL also ratifies the two decisions embedded here: the BSD-2-Clause license choice and the creation of a **private** GitHub mirror named `zit` for CI. (Operator decision, 2026-07-18: BSD-2-Clause **confirmed**; the mirror is **PRIVATE** — publishing the repository publicly is a separate, later, explicitly-operator- gated decision. Nothing in this plan may make the code public.)* Source of truth for findings: `docs/PRE-RELEASE-READINESS.md` (F1–F7, S1–S7, N1–N4). Executor: `/Users/dmestas/zit-plans/release-0.1.0/release.workflow.js`. --- ## 0. Release thesis Ship **0.1.0 as a library-first release with an honest-caveats CLI** in roughly one focused week. Do not hold for fossil parity. The claim we release on: *an independent, conformance-checked implementation of the four Fossil RFCs with an embeddable Zig API* — carried by the smoke step running in CI against the real `fossil` binary. Seven blockers stand between here and that tag; nothing else does. The `main.zig` split is explicitly **not** on the path (post-release, N1) — the architecture is otherwise genuinely deep-module and a pre-release reorg buys users nothing and invites merge churn against concurrent sessions. One framing correction carried into this plan: `zit status` not reporting edited files is a **documented, deliberate deferral** ("honestly deferred to `commit`/`diff` (B-status-16), stated in `--help`", `main.zig:1080-1086`) — not a silent lie. It stays a blocker because users don't read `--help` before running `status`, but it is a UX/completeness gap, and the fix is framed as *completing* the verb, not correcting dishonesty. --- ## 1. What "0.1.0 released" concretely means All of the following, in this order of finality: 1. All seven blockers (F1–F7) closed on the `release-0.1` branch, each with its required tests/fuzz/e2e in tree. 2. Full local battery green on the converged branch: `zig fmt --check .` · `zig build` · `zig build test` · `zig build e2e` · `zig build dst` · `zig build smoke`. 3. `release-0.1` merged to trunk; CI green on the mirror for the merge commit. 4. `build.zig.zon` version `0.0.0` → `0.1.0`; `LICENSE` present and listed in `.paths`. 5. `README.md` carries an **honest caveats table** (see §3, P5b). 6. `docs/RELEASE-NOTES-0.1.0.md`: what it is, what's proven (incl. the exact `fossil` version smoke passed against — S7), what's deliberately NOT done. 7. Tag `v0.1.0` on the trunk merge commit (fossil tag + git tag on the mirror), release notes written to `docs/RELEASE-NOTES-0.1.0.md` and attached to a release on the **private** mirror. NOTE: "released" here means tagged + noted on the private mirror — NOT a public announcement. Going public is a separate operator decision, deliberately out of scope. 8. Cleanup: release worktrees removed, scratch files gone, mirror in sync. The definition-of-done checklist in §8 is the mechanical form of this list. --- ## 2. Phase plan and ordering rationale ``` P1 License & hygiene (hours) └► P2 CI bootstrap (~1 day) ├────────────► P3 CLI cliffs ┐ three parallel worktrees: │ F3 clone→open (1–2d) │ F3 ∥ F4 ∥ F5 │ F4 add/rm rec. (~1d) │ │ F5 status edits (½–1d)┘ └────────────► P4 Fuzz hardening ─ one worktree, F6 → F7 serialized F6 transport/serve (~1d), F7 merge3 (½d) P3 + P4 both complete ─► P5 Release surface (help audit → docs/version) └► P6 Converge & ship ``` **Why this order:** - **P1 first** — LICENSE is minutes of work, legally gating (a release with no license grants nobody any rights), and has zero conflict surface. It also carries the trivial hygiene item S6 and commits this plan document. - **P2 second, before any code fix** — CI is the multiplier: once the mirror pipeline runs `test`+`e2e`+`dst`+`smoke`, every subsequent fix lands with an automated gate, and the smoke conformance claim becomes *continuously enforced* rather than milestone-manual. Bootstrap subtlety: P1 and P2 themselves have no CI to gate on — the local verify battery is the gate for them; from P3 onward every commit additionally gates on mirror CI. (An aggressive schedule could overlap P2 with P3/P4; we deliberately serialize — it costs at most a day and buys the CI gate for every code fix.) - **P3 ∥ P4 fan-out** — the three CLI cliffs and the two fuzz targets are mutually independent. P4 touches only `fuzz_tests.zig` + new `*_fuzz` files + `build.zig` (disjoint from `main.zig`), so it runs fully parallel to P3. Within P3, F3/F4/F5 touch *distinct regions* of `main.zig` (~:2537+, ~:452/:679, ~:1080-1160) plus per-verb spots in `cli.zig` and `e2e.zig` — line-based fossil merges converge cleanly; each track `fossil update`s before committing to absorb siblings. Within P4, F6 and F7 both edit the `fuzz_tests.zig` registration table → serialized. - **P5 after P3+P4** — the help audit (S2) must describe the post-fix verb set (`open` exists only after F3), and the caveats table / release notes must describe final behavior. Writing them earlier documents a moving target. - **P6 strictly last** — trunk re-merge, full battery, single merge to trunk, tag, publish, cleanup. --- ## 3. Per-change specifications ### P1 — License & packaging hygiene (F1 + S6) — *hours, trivial risk* | | | |---|---| | **Scope** | Add `LICENSE` (**BSD-2-Clause**, copyright Daniel Mestas 2026). zit is an independent reimplementation from the RFCs, not derived from fossil source, so any license is legally available; BSD-2-Clause matches the Fossil heritage and the systems-Zig ecosystem. (MIT would be equally defensible — this is the one taste call embedded in the FINAL flip.) Add `LICENSE` to `build.zig.zon` `.paths`. Delete `commit-description-413190fb92be991f.txt` and add an ignore-glob for the pattern (S6). Commit this plan doc. | | **Acceptance** | `LICENSE` at repo root; named in `.paths`; scratch file gone; ignore-glob in `.fossil-settings/ignore-glob`; battery green. | | **Tests** | *Amended from "none new — battery only"* (explicit scope ack, not silent drift). P1 adds `src/packaging_test.zig`: structural pins over the shipped distribution — LICENSE content, LICENSE named inside the manifest's brace-matched `.paths` block, a line-anchored ignore-glob pin, and a negative-space pin asserting every repo-root path `build.zig` embeds is named in `.paths`. Justification: the P1 acceptance criteria are all *file-structure* facts, which rot silently because nothing executes them; the battery alone cannot catch a `.paths` regression. Caveat recorded because this addition was itself the vector for a packaging blocker — the embeds must attach to the test-only module (`build_unit_test_module`), never to the exported `zit` module, or a consumer fetching the package fails on a file outside `.paths`. The negative-space pin exists to catch exactly that recurrence. | | **Risk / size** | Trivial / minutes–hours. | ### P2 — CI bootstrap (F2) — *~1 day, medium risk (infra unknowns)* | | | |---|---| | **Scope** | (a) Establish a **PRIVATE** git mirror of the fossil repo at `github.com/<owner>/zit` via `fossil git export` (create with `gh repo create --private` if absent — the `--private` flag is MANDATORY; a public mirror is out of scope for 0.1.0 and requires a separate operator decision), with a scripted export step so later phases can push deterministically. (b) `.github/workflows/ci.yml`: on push (all branches) + PR — pin **Zig 0.16.0**, install `fossil` (for smoke), run `zig fmt --check .`, `zig build`, `zig build test`, `zig build e2e`, `zig build dst`, `zig build smoke`. Single `ubuntu-latest` gating job for 0.1 (macOS job is 0.2 material). Do **not** change local step semantics — e2e staying compile-only under `zig build test` is a good inner-loop design; CI runs the steps explicitly. | | **Acceptance** | First fully green Actions run on the mirror for `release-0.1`, including smoke against a real installed fossil. Export step is one command, rerunnable. | | **Tests** | The pipeline *is* the test; green run required. | | **Risk / size** | Medium — runner environment (fossil version, Zig install, smoke's spawned-server behavior in CI) is the unknown; budget the day for iteration. ~1 day. | ### P3-F3 — Clone → working tree: `zit open` — *1–2 days, highest risk* | | | |---|---| | **Scope** | Recommended shape (final call belongs to this step's Ousterhout round): implement a **`zit open`** verb — fossil-parity (`fossil clone` + `fossil open` is exactly fossil's own UX) and the deeper module (opens *any* repo file, not just fresh clones). `open` takes a repo path + workdir, writes the checkout record and managed set, and materializes the tip of trunk reusing the existing `checkout.zig`/`update.zig` machinery. `runClone` stays repo-only. Alternative if review prefers it: clone writes the checkout bootstrap itself. Register the verb (`cli.zig` Verb enum + dispatch + help). | | **Acceptance** | e2e proof chain: `clone` (from `zit serve`) → `open` → **files on disk** byte-match the source tree → `update` works in the opened tree → a `commit` in the opened tree round-trips. Smoke scenario: clone from a real `fossil`-served repo → open → file bytes match. `open` appears in help with an e2e pin. | | **Tests** | The e2e chain above (this is the missing proof the assessment called out — the existing clone test asserts digest-set equality only, `e2e.zig:10209`), plus the smoke scenario. | | **Risk / size** | **Highest of the release** — whether `update` works against a fresh clone's absent checkout record is unproven; expect to fix what the new e2e exposes. 1–2 days. | ### P3-F4 — `add`/`rm` directory recursion — *~1 day, low-medium risk* | | | |---|---| | **Scope** | Implement recursion at `main.zig:452` / `:679`, honoring the **existing `extras.sweep` exclusion walk** — the exact pattern `addremove` (f0dc5f4e2a) already established: one scan, mutations only through `ManagedSet.insert/remove/write`. No second walker. Replace the "directory recursion is not yet supported" diagnostics and retire their e2e pins (`e2e.zig:645,1034,1164`). | | **Acceptance** | `zit add .` adds every non-excluded extra under the tree; `zit add <dir>` scoped correctly; `zit rm <dir>` removes tracked files under dir; control files / ignore-glob matches never added; `--dry-run` semantics if present stay consistent with `addremove`. | | **Tests** | e2e: nested dirs, exclusion globs honored, `add .` at root and in subdir, `rm` of a partially-tracked dir; updated diagnostics tests. | | **Risk / size** | Low-medium (proven pattern to copy). ~1 day. | ### P3-F5 — `status` reports edited files — *½–1 day, medium risk* | | | |---|---| | **Scope** | Complete B-status-16: full edited-file detection — hash tracked files against the current check-in, reusing the dirty-scan machinery `commit` already has. Add an `EDITED` row class to the render loop (~`main.zig:1155-1160`). Update `--help` to drop the deferral text. Frame: completing a documented deferral, not fixing a lie. | | **Acceptance** | Edit a tracked file → `status` lists it as edited; unchanged files not listed; `added`/`missing` behavior unchanged; help text updated. No performance *claims* without a benchmark (rule 7) — if the notes want to say anything about status speed, cite a measurement or say nothing. | | **Tests** | e2e: edit→status shows; touch-without-change (mtime bump, same bytes) → not shown; interaction with `missing` and `added` states. | | **Fallback of record** | If the track overruns its budget: ship the minimum honest version — a trailing notice line ("edits not shown; see `zit diff`") — and move full detection to 0.2.0 top-of-list. The workflow treats this as a legitimate DONE_WITH_CONCERNS outcome, recorded in the release notes. | | **Risk / size** | Medium. ½–1 day. | ### P4-F6 — Transport/serve fuzz targets — *~1 day, low risk* | | | |---|---| | **Scope** | `transport_frame_garbage` and `serve_request_garbage` seeded fuzz targets for the only surfaces reachable by an untrusted remote peer (`transport.zig` 469 L, `serve.zig` 593 L). `sync_parsers_adversarial` covers the layer above; these hit the HTTP framing itself. Register in the `fuzz_tests.zig:21-46` table exactly like the existing 24; replayable seeds. | | **Acceptance** | Targets run in the standard fuzz invocation and in CI; N-iteration seeded run clean (no crash/leak/UB); **any bug found is fixed in this step with a regression test pinning the seed**. | | **Risk / size** | Low for the targets; unknown for what they find (that's the point). ~1 day. | ### P4-F7 — `merge3` property fuzz — *½ day, low risk* | | | |---|---| | **Scope** | `merge3_properties` target with the four algebraic oracles: `merge(b,x,b)==x`, `merge(b,b,y)==y`, `merge(b,x,x)==x`, and no-invented-lines (every output line ∈ some input). Silent merge corruption is the worst VCS failure mode; this is the cheapest insurance on the list. Serialized after F6 (shared `fuzz_tests.zig` table). | | **Acceptance** | Same bar as F6: registered, seeded, CI-run, clean at N iterations, findings fixed with pinned-seed regressions. | | **Risk / size** | Low. ½ day. | ### P5a — Help-text audit (S2) — *hours, trivial risk* | | | |---|---| | **Scope** | Every dispatched verb appears in shipped help: name `sync` (currently a live dispatch arm deliberately absent from help, `cli.zig:2355-2357` — fine mid-development, wrong in a release), and audit `clone`/`pull`/`push`/`remote`/`pack`/`open`. | | **Acceptance** | e2e test asserting each dispatched Verb-enum member appears in `zit help` output (a structural pin, so the audit can't rot). | | **Risk / size** | Trivial. Hours. Must run after F3 (open exists). | ### P5b — Version, README caveats, release notes — *½ day, low risk* | | | |---|---| | **Scope** | `build.zig.zon` `0.0.0` → `0.1.0`. README **honest-caveats table**: status/diff limits (rev-vs-rev diff absent — `diff` is working-tree vs current check-in only; status fallback if F5 shipped minimal), placeholder sync identity, deferred R/T/U/W card semantics, verbs missing vs fossil (`stash`, `grep`, `ui`, `settings`, rev-diff). `docs/RELEASE-NOTES-0.1.0.md` in the honest-diagnostic voice the codebase already has (it's a release asset): what's implemented, what the conformance claim rests on (smoke in CI against the real fossil binary — **name the exact fossil version**, S7), what's deliberately deferred and where each deferral is documented. Any performance number quoted (e.g. the pack/re-deltification sizes) must cite its existing measurement (bab9303056) — no unbenchmarked claims. | | **Acceptance** | Version stamped; caveats table complete against the final shipped behavior; notes reviewed at the design tier for voice and honesty; battery green. | | **Risk / size** | Low. ½ day. Strictly after P3+P4+P5a. | ### P6 — Converge & ship — *½ day, medium risk (concurrency)* | | | |---|---| | **Scope** | (1) Re-merge trunk → `release-0.1` (trunk advances from concurrent sessions; expect and absorb their commits). (2) Full local battery incl. smoke on the merged tree. (3) GO/NO-GO judgment against the §8 checklist. (4) Merge `release-0.1` → trunk (SQLITE_BUSY retry; re-merge again if trunk moved). (5) Mirror export; wait for CI green on the merge commit. (6) Tag `v0.1.0` (fossil tag on trunk tip + git tag on the private mirror), publish the release with its notes **on the private mirror only** — no public announcement, no visibility change; going public is a separate operator decision. (7) Cleanup: remove `/Users/dmestas/zit-rel/*` worktrees, verify `fossil extras` clean, mirror in sync. | | **Acceptance** | §8 checklist fully checked. | | **Risk / size** | Medium — merge races with concurrent sessions; the retry+re-merge loop is the mitigation. ½ day. | --- ## 4. Dependency graph & parallelism Serialize: **P1 → P2**. Fan out: **P3 (three worktrees) ∥ P4 (one worktree)**. Join: **P5a → P5b → P6**. Worktree map (house pattern: parallel tracks are **separate worktrees on the SAME branch**, converging on the branch, then one merge to trunk): | Worktree | Track | Files touched (conflict surface) | |---|---|---| | `/Users/dmestas/zit` (trunk checkout) | P1, P2, P5, P6 | root files, `.github/`, docs, `build.zig.zon`, `cli.zig` help | | `/Users/dmestas/zit-rel/open` | F3 | `main.zig` ~:2537+, `cli.zig` Verb/help, `checkout.zig`, `e2e.zig`, `smoke.zig` | | `/Users/dmestas/zit-rel/addrm` | F4 | `main.zig` :452/:679, `extras.zig` (read), `e2e.zig` | | `/Users/dmestas/zit-rel/status` | F5 | `main.zig` ~:1080-1160, `e2e.zig` | | `/Users/dmestas/zit-rel/fuzz` | F6→F7 | `fuzz_tests.zig`, new `*_fuzz` files, `build.zig` | P1/P2/P5/P6 run in the trunk-side checkout but commit to `release-0.1` (sequential phases — no self-conflict). Every track `fossil update`s immediately before committing to absorb sibling commits; if the update pulls nontrivial changes, re-run `zig build test` before committing. Existing `zit-storage` / `zit-nextverbs` worktrees are left alone — they belong to other lines of work. --- ## 5. Branch strategy Single fossil branch **`release-0.1`**, cut from trunk tip at preflight. The phases are interdependent (help audit and notes describe the post-fix verb set), so a coherent branch lets CI validate the set together. **Continuous integration to trunk (operator decision, 2026-07-18).** Every increment lands on trunk as soon as it passes its own gates — *not* one big-bang merge at P6. After a step commits on `release-0.1`, `runStep` immediately runs a **land-on-trunk** gate: 1. Driven from the **trunk worktree** (`/Users/dmestas/zit`), never from the step's worktree — so parallel P3/P4 tracks don't each steer trunk. 2. `fossil update trunk` → require a clean tree (a dirty trunk carrying another session's WIP **blocks**; never revert or stash someone else's work). 3. `fossil merge release-0.1` → **any** conflict or `<<<<<<<` marker blocks for human resolution; no silent semantic merges. 4. **Re-verify the merged tree** (`fmt`/`build`/`test`, plus `smoke` on interop-relevant steps). Green-on-the-branch does **not** imply green-on-the-merge, because trunk advances under us. 5. Commit the merge (guard enforced, SQLITE_BUSY/guard-flake retries, never bypassed). If trunk moved mid-merge, restart the sequence (bounded, 3×). Rationale: smaller, reviewable merges; minimal divergence from a trunk that concurrent sessions keep advancing; each increment independently landed and revertible; conflicts surface at one-increment size instead of accumulating to release-sized. A failed land does **not** lose work — the increment stays committed on `release-0.1` and the step reports `landed: false`. By P6 trunk should already contain every increment; P6's merge becomes a formality (plus the final re-verify, GO/NO-GO, and tag). Tag goes on the trunk tip. Concurrency rules (standing): SQLITE_BUSY on any fossil op → bounded retry with backoff; never inherit rule-violating files from concurrent sessions across a merge (inspect what the re-merge brings in); the `zit-commit-guard` pre-commit hook builds the **main checkout** and runs test/dst — it may flake under concurrent writers; retry, **never bypass, never `--no-verify`**. --- ## 6. Scope decisions — SHOULD-FIX / NICE-TO-HAVE disposition | Item | In 0.1.0? | Rationale | |---|---|---| | S2 help-text audit (`sync` et al.) | **Yes** (P5a) | Cheap; a hidden verb is wrong in a release. | | S6 scratch-file removal | **Yes** (P1) | Minutes. | | S7 fossil version in notes | **Yes** (P5b) | The conformance claim needs it. | | Version stamp + tag + caveats table | **Yes** (P5b/P6) | Is the release. | | S1 working-tree crash-consistency DST sweep | **0.2 — first item** | Biggest post-release safety win (this is where a user's power-loss lands) and the harness (`sim/faulty_file.zig`) already exists — but no user-visible cliff, and the week budget belongs to the seven cliffs. Deliberately top of 0.2. | | Delta/repo-state RFC vectors | **0.2** | Smoke-in-CI (P2) covers the conformance substance with *stronger* evidence (validation against fossil's own code); vectors are defense-in-depth that runs without a fossil binary. | | S3 seam-coverage matrix (~14 "deferred to manifest assembly" promises) | **0.2** | Converts informal promises into one enforced invariant; valuable, not user-facing, not gating. | | S4 parse-garbage fuzz (`managed`/`undo`/`repocache`) | **0.2** | On-disk-state hardening; pairs naturally with S1. | | S5 artifact fuzz alphabet → R/T/U/W/Z | **0.2** | Those card semantics are themselves deferred; fuzz them when they land. | | Extended smoke scenarios (bidirectional sync, delta-heavy) | **0.2** | Marginal conformance dollar goes furthest here — after the tag. | | N1 `main.zig` split | **Post-release, explicitly deferred** | Shallow god-file, real debt — but a reorg buys users nothing pre-tag and invites merge churn. Seam and target shape already documented in the assessment. | | N2 kcov `cov` in CI + floor | **0.2** | The kcov plan already exists (queued post-CLI); wire it once CI is stable. | | N3 separate test-aggregation root · N4 `repostate_crosslink_garbage` | **Backlog** | No release relevance. | --- ## 7. Quality bar (per step — the workflow enforces this; do not thin it) Every P1–P6 step runs the full gauntlet built over the storage lever: 1. **Ousterhout design review** (design tier, bounded ≤3 rounds): shallow module / leaky interface / pass-through check; complexity pushed down, not up to callers; lighter-mechanism check; premise check. 2. **Implement, TDD**: failing test first (shown failing), then to green. 3. **STANDALONE TigerStyle audit** — its own gate with its own agent, never folded into code review (bounded ≤3 audit→fix rounds). 4. **DST/property + seeded fuzz** where the step touches simulated or fuzzed surfaces (F6/F7 are themselves this; F3/F4/F5 must keep `zig build dst` green and extend e2e). 5. **Full local verify battery**: `zig fmt --check .` · `zig build` · `zig build test` · `zig build e2e` · `zig build dst` · `zig build smoke` where interop-relevant (F3, P6 always; others when they touch sync/serve). 6. **Commit discipline** (the pack.zig lesson): check `fossil extras`, `fossil add` **every** new file, commit (SQLITE_BUSY retry), then verify a **clean checkout of the new commit builds** (`fossil open` into a temp dir → `zig build` + `zig build test`). Guard hook: never bypass. 7. **From P3 onward**: mirror export + CI green on the branch is an additional gate per commit. 8. **Attribution**: borrowed techniques cite author + codebase/paper in the code comment AND the commit message. No AI attribution anywhere. 9. **Rule 7**: no performance claim without a benchmark, in code comments, commit messages, or release notes. --- ## 8. Definition-of-done checklist (P6 GO/NO-GO input) - [ ] F1: `LICENSE` (BSD-2-Clause) at root and in `.paths` - [ ] F2: mirror CI green running fmt-check/build/test/e2e/dst/smoke, Zig 0.16.0 pinned, fossil installed - [ ] F3: e2e clone→open→files-on-disk→update→commit chain green; smoke scenario vs real fossil green - [ ] F4: `zit add .` / `zit rm <dir>` recursive, exclusion-sweep-honoring, e2e-covered - [ ] F5: `status` reports edited files (or recorded fallback: notice line + 0.2 deferral in notes) - [ ] F6: transport/serve fuzz targets registered, seeded, CI-run, clean - [ ] F7: merge3 property target (4 oracles) registered, seeded, CI-run, clean - [ ] S2: every dispatched verb in help, structurally pinned by e2e - [ ] S6: scratch file removed, pattern ignored - [ ] Version `0.1.0` in `build.zig.zon` - [ ] README caveats table matches shipped behavior - [ ] `docs/RELEASE-NOTES-0.1.0.md` complete, incl. exact fossil version (S7); no unbenchmarked perf claims - [ ] Trunk re-merged into `release-0.1`; full battery green on converged tree - [ ] `release-0.1` merged to trunk; CI green on merge commit - [ ] `v0.1.0` tagged (fossil + mirror git tag); release published with notes on the PRIVATE mirror (repo visibility unchanged — still private) - [ ] `fossil extras` clean on trunk; release worktrees removed; mirror in sync ## 9. Risks & contingencies | Risk | Mitigation | |---|---| | F3 exposes deeper checkout/update breakage than 1–2 days absorbs | It's the first track dispatched (longest pole). If it balloons: keep `open` minimal (materialize tip + records; defer flags), and let the e2e chain define "enough". If still blocked, the workflow halts that track and surfaces it — 0.1 does **not** ship without F3. | | CI environment fights back (smoke in Actions) | Budgeted into P2's day; smoke's server-spawn is the likely friction. If a runner-specific smoke issue can't be fixed same-day, gate on test/e2e/dst and file the smoke-in-CI gap as a named caveat + 0.2 item — an explicitly surfaced downgrade, not a silent one. | | Concurrent sessions race trunk | Re-merge before finalizing; SQLITE_BUSY retries; inspect merged-in content; guard-hook flakes get retried, never bypassed. | | F6/F7 fuzz finds real bugs | That's success. Fix-with-pinned-seed inside the step; if a finding is structural (e.g. a protocol flaw), the workflow halts the track and surfaces it rather than papering over. | | F5 full detection overruns | Recorded fallback: notice line + 0.2 deferral (see P3-F5). |