# Frozen legacy trees The root `claude/` tree in this repository is **frozen**, not live. It exists only to serve pre-1.6.0 Claude clients whose download path hardcodes `claude` at the repo root and cannot be retargeted without shipping a new binary. All new skill, agent, and hook work happens in `assets/claude/` and `assets/codex/`. The root tree is never edited again. ## Freeze point ``` 3253eacedc83659790f00f40dec74f84e49beb56 2026-08-20T16:33:10-05:00 Add named subagents for plan/build/ship stages (#31) ``` This is `origin/master` HEAD at the time of the freeze (2026-08-23), **not** this branch's HEAD. This branch had already added declarative skill content (`hyprlayer orchestrate check`/`compile` invocations, which pre-1.6.0 binaries do not have) and deleted eight skills (`ci_commit`, `ci_describe_pr`, `create_plan_nt`, `create_plan_generic`, `describe_pr_nt`, `iterate_plan_nt`, `research_codebase_nt`, and `research_codebase_generic`) relative to `origin/master`. Freezing at this branch's state would have pushed both changes onto every pre-1.6.0 client within 24h via the existing auto-refresh (`src/version.rs:377-407`): the declarative skills reference a command group (`orchestrate`) those binaries lack, and `sync_tree` never deletes, so the removed skills would linger on disk forever rather than actually going away. Freezing at `origin/master` instead means pre-1.6.0 clients keep receiving exactly what they receive today — including the nine named subagents added in this same commit, which a stale local `master` ref would have silently dropped (`git rev-parse master` resolved to `4c5cf37` in at least one worktree at freeze time; `origin/master` is authoritative here). ## Verifying the freeze `tests/frozen_legacy_trees.rs` asserts the root tree remains byte-identical to the SHA above via `git diff --quiet -- claude/`. It is pinned to this recorded SHA, not to `origin/master`, so it keeps holding as `master` advances past the freeze point. `agents::tests::frozen_manifests_match_the_frozen_trees` covers the second half: that the digests embedded in the binary still describe these trees. ## The trees are also data `src/agents/frozen/claude.json` records every file in this tree with its SHA256, generated by `scripts/build-frozen-manifests.sh`. The binary embeds those lists (`AgentTool::frozen_manifest`) and uses them for one thing: on a machine with no install record — or one whose record only goes back to 1.6.0 — they are the proof that a file was ours to delete. That is what finally retires the eight workflows dropped at the freeze (`ci_commit`, `ci_describe_pr`, `create_plan_generic`, `create_plan_nt`, `describe_pr_nt`, `iterate_plan_nt`, `research_codebase_generic`, `research_codebase_nt`). Pre-1.6.0 installs wrote no manifest, so nothing else records that we put them in `~/.claude/skills`, and until 1.6.1 they simply stayed there — live `SKILL.md` files sitting next to the skills that replaced them. Removal is digest-guarded: a file whose bytes no longer match the frozen tree has been edited since, so it is the user's and stays. The lists are deliberately *not* consulted for the overwrite decision. A machine that last refreshed before the freeze holds older bytes for files we still ship, and treating those as "not ours" would freeze it on them forever. See `sync_tree` in `src/agents.rs`. ## Retired Copilot and OpenCode trees The paired Claude + Codex setup also retired the repository's old `copilot/` and `opencode/` trees. Their roots no longer need to remain available to old clients, but their known file digests are embedded in `src/agents/frozen/*-retired.json` so an upgrade can remove the copies those clients left in the shared harness directories without touching user files. Those manifests cover every distinct blob in each tree's history through `d705a48094606e267f817226f553a5c5a9764072`, the last commit before their removal. The OpenCode manifest additionally covers all three model-resolved variants produced by the legacy installer. Regenerate both with `scripts/build-retired-agent-manifests.sh`. ## Making a deliberate change to a frozen tree Don't, except to fix something actively broken for pre-1.6.0 clients. If you must, update the SHA recorded here in the same commit as the tree change, so the freeze guard reflects the new baseline rather than failing forever, and rerun `scripts/build-frozen-manifests.sh` so the embedded digests still describe the trees — `agents::tests::frozen_manifests_match_the_frozen_trees` fails until you do. ## Removal See "Sunsetting the legacy trees" in `thoughts/shared/plans/2026-08-23-versioned-release-asset-bundles.md`.