From f0b42feae961b3e77c2a55f0f27922fda733821a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauricio=20S=C3=A1nchez?= Date: Sun, 18 Oct 2026 10:16:28 -0500 Subject: [PATCH] =?UTF-8?q?docs:=20decision=200045=20=E2=80=94=20an=20upgr?= =?UTF-8?q?ade=20runs=20a=20script=20from=20the=20new=20release,=20with=20?= =?UTF-8?q?a=20smaller=20approval=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Records the design for #86 before implementation: a thin adf-upgrade wrapper in plugins/adf/bin/ (copied by build-plugins.sh from scripts/adf-upgrade.sh) that fetches a cached framework checkout and runs scripts/upgrade.py from the new release; old/new copies per install type, renames, deleted and new files; per-release idempotent migrations; the narrow rule for dropping covered allow rules; the amended "Plan before touching" ground rule; and the report format with a Follow-ups section for #89. Co-Authored-By: Claude Opus 5.5 --- ...027-worktree-scripts-as-plugin-commands.md | 2 +- docs/decisions/0028-plugins-are-the-source.md | 2 +- ...a-scripted-upgrade-from-the-new-release.md | 265 ++++++++++++++++++ docs/decisions/README.md | 5 +- 4 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 docs/decisions/0045-a-scripted-upgrade-from-the-new-release.md diff --git a/docs/decisions/0027-worktree-scripts-as-plugin-commands.md b/docs/decisions/0027-worktree-scripts-as-plugin-commands.md index 786afe4..185484f 100644 --- a/docs/decisions/0027-worktree-scripts-as-plugin-commands.md +++ b/docs/decisions/0027-worktree-scripts-as-plugin-commands.md @@ -1,6 +1,6 @@ # 0027: The worktree scripts are the plugin's commands — `adf-worktree-new`, `-ls`, `-rm` (parallel-agents module) -- **Status:** accepted; amended by [0032](0032-local-environment-layout.md) (the module's folder is `ops/agent/`; the commands read `scripts/agent/` until a project moves it) +- **Status:** accepted; amended by [0032](0032-local-environment-layout.md) (the module's folder is `ops/agent/`; the commands read `scripts/agent/` until a project moves it) and [0045](0045-a-scripted-upgrade-from-the-new-release.md) (`bin/` also carries `adf-upgrade`, a framework command the build copies from `scripts/adf-upgrade.sh`) - **Date:** 2026-10-09 - **Amends:** [0016](0016-packaged-install.md) — what a packaged project commits for a module; [0023](0023-plugins-by-concern.md) — what a module's plugin carries diff --git a/docs/decisions/0028-plugins-are-the-source.md b/docs/decisions/0028-plugins-are-the-source.md index c417972..74d4480 100644 --- a/docs/decisions/0028-plugins-are-the-source.md +++ b/docs/decisions/0028-plugins-are-the-source.md @@ -1,7 +1,7 @@ # 0028: The plugins are the machinery's source, and a committed install is written from them - **Status:** accepted; amended by [0029](0029-workflows-carry-agent-checklists.md) (the build also - generates the agent checklists `deep-review` carries) + generates the agent checklists `deep-review` carries) and [0045](0045-a-scripted-upgrade-from-the-new-release.md) (an upgrade builds both releases with `build-committed.py` from each release's own tree) - **Date:** 2026-10-09 - **Amends:** [0016](0016-packaged-install.md) — where the machinery's source lives ("generated from `skeleton/`", "the skeleton stays the single source"); [0019](0019-reference-docs-in-the-plugin.md) — diff --git a/docs/decisions/0045-a-scripted-upgrade-from-the-new-release.md b/docs/decisions/0045-a-scripted-upgrade-from-the-new-release.md new file mode 100644 index 0000000..5796dfc --- /dev/null +++ b/docs/decisions/0045-a-scripted-upgrade-from-the-new-release.md @@ -0,0 +1,265 @@ +# 0045: An upgrade runs a script from the new release, and the developer approves only what needs a person + +- **Status:** accepted +- **Date:** 2026-10-18 +- **Amends:** [0027](0027-worktree-scripts-as-plugin-commands.md) — what `bin/` carries and where it + comes from; [0028](0028-plugins-are-the-source.md) — how an upgrade diffs a committed install's + machinery + +## Context + +`/adf:upgrade` is a procedure an agent follows by hand. An adopting project on the packaged install, +with six modules, moved from v2.2.0 to v2.4.0 +([#86](https://github.com/aplyca/AgenticDevelopmentFramework/issues/86)): + +- **The agent found the releases by hand:** `gh release list`, a full clone, + `git rev-parse 'vX.Y.Z^{commit}'`, and an `awk` over `CHANGELOG.md`. +- **It merged eight files one at a time** with `git show OLD:path`, `git show NEW:path`, and + `git merge-file`. Six merged cleanly. `AGENTS.md` and `.claude/rules/deployment.md` had two + conflicting hunks each. +- **The rest was mechanical too:** rerunning the `docker` and `e2e` installers, moving the + marketplace's `ref` and adding `autoUpdate` (0041), dropping allow rules a broader one now covered, + `link-reference-docs.py --packaged`, and the restamp. +- **The developer approved a per-file plan** whose rows were mostly "clean merge". Two conflicts and + the new ask rules for the project's tasks (`dev-env`'s `SPECIFICATION.md` C9 and C10) needed a + person. +- **The hook smoke test failed with `unbound variable`.** The hooks use `set -u`, and Claude Code + always sets `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PROJECT_DIR`; the agent hadn't exported them. That's + a gap in the test, not in the hooks. + +Each step costs agent calls and a chance to slip, and none of them needs judgment. A design review on +the issue found what a script has to get right before it can take them over: + +- **The pinned plugin is the old release.** An `adf-upgrade` command in `bin/` is code from OLD + upgrading to NEW, so it can't know the moves or migrations NEW added. The skill already reruns the + module installers from NEW for this reason. The skill itself is old too. +- **`bin/` is generated** (0027): every command there is a module's script, built by + `scripts/build-plugins.sh`. An upgrade command isn't a module's, and a committed install may not + have the plugin's commands on its path. +- **`git show OLD:path` isn't always the merge base.** It is for `skeleton/` and + `modules/*/files/`. A committed install's machinery comes from `build-committed.py` (0028), so both + sides have to be built. Renamed folders (`scripts/agent` → `ops/agent`), files the project deleted, + and new files are most of the work; `git merge-file` is the easy part. +- **Release-specific steps don't belong in one script.** "Add `autoUpdate`" is a step of one release. + A single script would collect every release's special case. +- **"Covered" allow rules need a narrow definition.** A permission change is exactly what the + developer should still see. +- **A clean merge can still be wrong,** a duplicated section in `AGENTS.md` for one, so the reviewer + needs to know where to look. + +## Decision + +### 1. A thin command in the plugin, the real script in the framework + +- **`adf-upgrade [] [--dry-run] [--offline] [--