Skip to main content

ADR-0024: Tool state root, write contract, and version migration

  • Status: Accepted
  • Date: 2026-07-25
  • Deciders: Michel Gillet

Context

ADR-0013 introduced .a2c/adoption.yaml, drift warnings, and method delivery via copy / submodule / clone at tools/ai-rules/. Related ADRs hard-coded the same .a2c/ prefix for config.yaml, cli-journal.yaml, and migration.yaml (ADR-0014, ADR-0016, ADR-0017, ADR-0018).

That approach has three problems:

  1. No abstract folder concept — changing the on-disk root requires amending every file ADR instead of one path-binding ADR.
  2. Write contract vs session pin — in superbuilds, many product repos share one checkout while each repo’s adopted A2C version is the write contract. Mounting a single tools/ai-rules (or using the workspace superbuild tools/ai-rules) does not match per-repo authorship rules. Additive minors must not cause agents to emit newer-only artifacts while the repo’s adopted version is older.
  3. Delivery — method assets for several write-contract versions must be installable side by side (package / Conan / pip) under a local tree, without committing full method trees into the superbuild or colliding with superbuild-workflow at $WORKSPACE/tools/ai-rules/.

Legacy repos still have .a2c/* and often $R/tools/ai-rules/ as the A2C method mount. New repos should use .tools/esys/a2c/ for committed tool state and .tools_local/esys/a2c/<version>/ for installed method assets.

Decision

1. Abstract locations (single binding ADR)

ConceptMeaning
Tool state rootCommitted A2C tool-internal state for one git repository
Method asset rootOn-disk tree of method assets (rules/, prompts/, templates/, …) for a specific write-contract version

Concrete bindings (this ADR):

ConceptLegacy (read if new absent)Canonical for new repos / new layout versions
Tool state root.a2c/.tools/esys/a2c/
Method asset root (installed)$R/tools/ai-rules/ when that tree is an A2C method checkout.tools_local/esys/a2c/<version>/ (gitignored install prefix)

Future path changes amend or supersede this ADR only. Other ADRs refer to {tool_state_root}/… and “resolved method asset root for version V”, not to a hard-coded folder string (except historical text in Superseded ADRs).

Files under tool state root include at least:

  • adoption.yaml
  • config.yaml
  • cli-journal.yaml
  • migration.yaml (when brownfield migration is in use)

2. Write contract

The repository’s adopted A2C version (consumer ADR-0000 + adoption record tool_version / method_ref) is the write contract: durable A2C artifacts (ADRs, ASRs, tool state, method-governed scaffolding) must be authored under that version’s method rules.

  • A workspace / session pin (e.g. newer CLI or superbuild-installed tools) may mount a newer method tree for reading; it must not silently apply newer-only write rules while the write contract is older.
  • The repository has one write contract (its adopted version). Whether a parent workspace pins a newer A2C for its own session is outside that contract.

3. Method asset resolution (agents and CLI)

For A2C work in git repo R with write contract version V:

  1. $WORKSPACE/.tools_local/esys/a2c/V/ if present (superbuild shared install)
  2. Else $R/.tools_local/esys/a2c/V/ if present (single-repo install)
  3. Else $R/tools/ai-rules/ if present and recognized as an A2C method tree (legacy delivery)
  4. Else fail / warn: install method assets for V — do not invent rules

Never use $WORKSPACE/tools/ai-rules/ as the A2C method asset root. In a superbuild that path is superbuild-workflow, not A2C.

4. Adoption record and delivery modes

Keep the machine-readable adoption record and drift-warning intent of ADR-0013.

  • Path: {tool_state_root}/adoption.yaml (legacy .a2c/adoption.yaml still read when the new path is absent).
  • New repos after this ADR’s layout is required: write only under .tools/esys/a2c/.
  • Extend delivery to include at least: none, copy, submodule, clone, and package (or equivalent) meaning method assets installed under .tools_local/esys/a2c/<version>/ (PyPI, Conan, or other install).
  • Drift checks compare running CLI / recorded adoption / resolved method asset root for V, not only a git checkout at tools/ai-rules/.

Schema version may bump when fields are added; readers must accept legacy .a2c/adoption.yaml shape.

5. Version migration (primary); layout migration (conditional)

Operators upgrade adoption with an explicit version migration command, e.g. a2c migrate version --to X.Y.Z (name may vary; must not be folded into a2c bootstrap).

Bootstrap remains adopt/scaffold for new or additive setup — not the upgrade path across layout eras.

Version migration:

  1. Update write contract / adoption record to target V.
  2. If V (or the first version that mandates the new layout) requires .tools/esys/a2c/ and .a2c/ still exists:
    • git mv tool-state files into .tools/esys/a2c/ (adoption.yaml, config.yaml, cli-journal.yaml, migration.yaml, …)
    • Remove the empty .a2c/ directory
    • Prefer a single git commit for the move
  3. If both roots exist before migrate completes: prefer .tools/esys/a2c/ if present; otherwise fail or warn until migration finishes (no silent dual-write).
  4. Ensure method assets for V are installable under .tools_local/esys/a2c/V/ when delivery is package-oriented.

Layout change is a consequence of version migration when the target version’s contract requires it — not a standalone “migrate layout” product story.

6. Superbuild and multi-repo

  • Superbuild may install the union of write-contract versions used by member repos under $WORKSPACE/.tools_local/esys/a2c/<ver>/.
  • Each member repo keeps its own tool state root and write contract.
  • Superbuild-workflow remains at $WORKSPACE/tools/ai-rules/ (committed submodule or pin). A2C method installs do not replace that path.

6.1 Workspace root ($WORKSPACE / W)

$WORKSPACE / W is not an ambient environment variable. Discovering W is the responsibility of the a2c CLI (shared library / commands such as a2c workspace path). Agents and other tools call that API; they do not re-implement discovery in prompts.

Path roles (committed marker at W vs local pointer under R), first-class signals, parent-walk algorithm, and materializing $R/.tools_local/esys/a2c/workspace.yaml are defined in ADR-0025 — kept separate so discovery can evolve (e.g. nested superbuilds) without reopening this ADR’s write-contract and path bindings.

Once W is known, method resolution (§3) uses $W/.tools_local/esys/a2c/V/ first. Agents must still never treat $W/tools/ai-rules/ as the A2C method asset root.

7. Relationship to ADR-0013

This ADR supersedes ADR-0013. Adoption records, drift warnings, and bootstrap pinning intent remain; paths, delivery modes, write-contract semantics, and version migration are redefined here.

Consequences

Positive

  • One ADR binds abstract roots to concrete paths — future moves do not fan out.
  • Write contract matches existing “adopted version” without fake ranges.
  • Superbuild and single-repo flows share the same resolution rules.
  • Workspace discovery is owned by a2c; algorithm details live in ADR-0025 so they can evolve separately.
  • Legacy .a2c/ and $R/tools/ai-rules/ remain readable until version migration.

Negative

  • Implementation must dual-read paths until consumers migrate.
  • Agents and docs must stop treating every tools/ai-rules as A2C.
  • Agents must call a2c for W rather than guess paths.
  • Package publishing of method assets and a2c migrate version are required follow-through (out of scope to fully implement in this ADR text alone).

Migration (operators)

  1. When ready to adopt a version that requires .tools/esys/a2c/, run a2c migrate version --to X.Y.Z (or documented equivalent).
  2. Review the git mv of .a2c/.tools/esys/a2c/.
  3. Install method assets for X.Y.Z into .tools_local/esys/a2c/X.Y.Z/ as directed by delivery mode / doctor.

References

Amends

  • ADR-0005 — consumer tool state / method install layout
  • ADR-0014 — journal path relative to tool state root
  • ADR-0016 — config path relative to tool state root
  • ADR-0017 — config path relative to tool state root
  • ADR-0018 — migration.yaml path relative to tool state root

Amended by

  • (none)

Supersedes

Superseded by

  • (none)