Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,128 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.15.0] — 2026-08-24

### Fixed

- **amplifier-agent no longer shares a module cache with amplifier-app-cli.** Module git
clones were written into `~/.amplifier/cache`, a tree owned by a different application.
Nothing in this repository referenced `.amplifier` to cause it: `amplifier_foundation`
resolves its storage root from `AMPLIFIER_HOME` and falls back to `~/.amplifier`, and this
app never set the variable — so the coupling was created by an *absent* argument at the
`load_bundle()` call, invisible to any search for the path itself. `AMPLIFIER_HOME` is now
bound to `<agent home>/foundation` before `amplifier_foundation` is imported, so
foundation's own resolver writes into a root this application owns. Ordering is
load-bearing: `amplifier_foundation.session.finder` computes a `~/.amplifier`-derived
constant at import time. Override with `$AMPLIFIER_AGENT_FOUNDATION_HOME` (this subtree)
or `$AMPLIFIER_AGENT_HOME` (the whole tree). Design: `docs/spec/foundation-cache-ownership.md`.

- **`amplifier-agent update` now actually picks up upstream module fixes, without
re-downloading everything.** Module sources are declared at a floating `@main`, but
foundation caches each clone at `sha256(git_url@ref)` and returns any directory that already
exists — it never fetches into it. With `@main` the key never changes while the commit it
names does, so one directory served every commit that branch would ever have: in practice the
first one, for the life of the machine. An upstream fix never reached an existing install, and
reinstalling did not help, because the reinstall rebuilt from the same frozen clone.

That is correct reasoning on a false premise. Foundation is told the identity of the content
is `main`; `main` is a pointer, not an identity. Rather than deleting directories to work
around the consequence, amplifier-agent now fixes the premise: before `prepare()`, each
floating ref is resolved to the commit it currently points at (`git ls-remote` — refs only, no
repository data, no authentication) and the source is rewritten to that SHA. Foundation then
keys on something that genuinely identifies the content, and its reuse rule becomes correct:

- branch unmoved → same SHA → same directory → **nothing is downloaded**
- branch moved → new SHA → new directory → cloned fresh, automatically
- offline → ref left floating → existing clone reused, exactly as before

**This is not pinning.** `bundle.md` still says `@main` and is never rewritten in the
repository; resolution happens on the user's machine against the branch as it stands at that
moment. Ship a provider fix and the next resolution picks it up with no amplifier-agent
release involved — preserving the non-goal recorded in `docs/spec/bundle-and-cache.md`.

Applied through `Bundle.prepare(source_resolver=...)`, a documented foundation extension point
that amplifier-agent had simply never used. Foundation already supports the rewritten form
natively via its `_clone_at_commit()` path for full 40-character SHAs.

Supersedes the one-time clone-deleting migration proposed in #141, whose diagnosis this
follows. No deletion remains anywhere in the refresh path.

- **`update` no longer reports "already up to date" without checking modules.** Modules move
independently of engine releases, so the old early exit meant the only route to a module fix
was an engine release that existed solely to move the cache. `update` now re-resolves refs,
compares them against the commit foundation recorded beside each clone, reports which
repositories moved, and re-primes — downloading only what actually changed. When nothing has
moved it costs one refs-only round trip per module and no downloads at all.

- **Superseded clone directories are pruned.** Content-addressed directories mean a moved branch
leaves its predecessor unreferenced. After a successful prepare, directories for repositories
resolved in that pass whose commit is no longer current are removed. Conservative by
construction: only repositories resolved in this pass are considered, the current commit is
always kept, and failures are ignored — this reclaims disk in amplifier-agent's own tree and
is not load-bearing for correctness.

- **The ChatGPT OAuth token no longer lives in amplifier-app-cli's tree.** `provider_sources`
read `~/.amplifier/openai-chatgpt-oauth.json` directly — pre-existing, but it was the *read*
half of the coupling this release claims to remove, and so the one residual the guarantee
could not honestly cover. The provider accepts a `token_file_path` config key
(`provider.py:103`), the same seam already used for provider-anthropic's rate-limit file, so
the token now lives at `<state_root>/openai-chatgpt-oauth.json`. A pre-0.15.0 login is
**copied forward** on first use so it keeps working; the original is never moved or deleted,
because it sits in a directory this application does not own. The legacy path is still read
as a fallback if the copy could not be made. Raised in review by @DavidKoleczek.

- **`$AMPLIFIER_AGENT_HOME` is now honoured by every storage root.** Two `bundle.md` values —
the recipes `session_dir` and context-intelligence's `base_path` — were literal YAML strings
that nothing expanded. With the variable unset they happened to equal `state_root()`, so the
divergence was invisible in normal use and in every test. Set it, and the
context-intelligence writer followed the literal while its reader followed `state_root()` —
the same writer/reader split this release fixes at the foundation level, reappearing one
level down. Both are now injected at runtime from `state_root()`, the same technique the
vendored skills and modes directories already use. Verified by running the full workload with
the variable set to a non-default path: 3831 files under the relocated root, **zero** under
the default one. Raised in review by @DavidKoleczek.

- **Module clones left behind in `~/.amplifier/cache` are left strictly alone.** Clones written
there by earlier versions are no longer read or written by amplifier-agent, but nothing in
this release removes them, reports on them, or offers to remove them. That directory is
foundation's default for *every* Amplifier application, clone directories are keyed by
`sha256(git_url@ref)[:16]` with no per-application namespacing, and on a machine that also
runs amplifier-app-cli they are its **live** clones — indistinguishable from our leftovers
from inside this application. amplifier-agent therefore ships no route to touching them,
because any such route is a way for a user to break amplifier-app-cli without meaning to.
#141 removed them unconditionally, which was correct while that directory was the one
amplifier-agent itself used; it is not correct once it belongs to somebody else. Users who do
not run amplifier-app-cli and want the disk space back can delete the directory themselves.

- **Recipe session state** moved out of `~/.amplifier/projects/{project}/recipe-sessions` —
the only *write* this application made into amplifier-app-cli's tree.

- **Context-intelligence captures are now readable.** The hook writes to this app's
workspaces tree, but its readers resolve the root only from
`AMPLIFIER_CONTEXT_INTELLIGENCE_BASE_PATH`, defaulting to `~/.amplifier/projects` — so
captures were written to one tree and looked for in another. Now set when absent; an
explicit user setting is left alone.

- **Provider rate-limit state** no longer lands in `~/.amplifier`. `provider-anthropic`
builds that path from `os.path.expanduser("~")` joined to a literal `".amplifier"` and
never consults `AMPLIFIER_HOME`, so the bind above cannot reach it; its
`rate_limit_state_path` config is now defaulted at mount time.

### Added

- **`doctor` reports `foundation isolation`**, failing if `AMPLIFIER_HOME` is unset, points
somewhere unexpected, or resolves inside `~/.amplifier`. Checked at runtime because the
regression it guards is silent: if the bind stops running, clones return to app-cli's tree
and nothing else in the system reports a problem.
- **`config show`** surfaces `foundation_home` and `module_cache_root`.

### Known limitation

- Remote **skill** clones still land in `~/.amplifier/cache/skills` until
microsoft/amplifier-bundle-skills#61 merges. That path is hardcoded in `tool-skills` and is
not reachable from bundle config, so it cannot be fixed from this repository.

## [0.14.1] — 2026-08-21

### Fixed
Expand Down
Loading