Skip to content

feat(framework): show the installed framework version at startup - #1088

Closed
alexsoyes wants to merge 8 commits into
nextfrom
codex/show-framework-version-at-startup
Closed

alexsoyes wants to merge 8 commits into
nextfrom
codex/show-framework-version-at-startup

Conversation

@alexsoyes

@alexsoyes alexsoyes commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

🎯 What & why

Implements #980: the startup greeting names the installed framework release, and a newer release from the same source is announced, read at session start rather than written into the agent files.

AI-Driven Development On ⚡ · Framework v5.12.0 · [Releases](https://github.com/ai-driven-dev/framework/releases)
AIDD framework v5.13.0 is available (installed: v5.12.0). To update, run `aidd marketplace refresh aidd-framework`, then `aidd plugin update`. Nothing is installed automatically.

This replaces the earlier iterations on this branch. Stamping Framework v5.12.0 into the AGENTS.md template failed the issue's own criterion ("after an upgrade, a new conversation resolves the updated installed version"). The template is copied into a project once: the version goes stale at the first upgrade, and every teammate shares it whatever they installed. The stamping script, its lefthook entry and its decision record are removed.

🛠️ How it works

Piece Where Does
Startup script plugins/aidd-context/hooks/framework-version.cjs, declared in hooks.json SessionStart Dependency-free. Reads the marketplace version (never a plugin's or the CLI's) from the installation's provenance and returns it as additionalContext. When a newer release is known, it also returns a systemMessage, which Claude Code and Codex show without going through the model
Greeting AGENTS.md template + the framework's own AGENTS.md / CLAUDE.md / cli/CLAUDE.md Framework v{version}, taken from the AIDD framework: context, or Framework version unknown. The update notice is quoted verbatim
OpenCode bridge opencode-hooks-bridge.ts, opencode-events.js.txt Previously discarded SessionStart stdout. It now captures it and adds it to every model call: V1 through experimental.chat.system.transform, V2 through session.hook("context")
CLI menu-use-case.ts New System › Check for CLI update entry, which runs the existing aidd update --check (same self-update check and cache, no new checker)

Provenance, in resolution order. Anything else is reported as unknown:

Install mode Version read from Remote comparison Update path shown
Claude Code native <plugins>/cache/<mkt>/<plugin>/<ver> → known_marketplaces.json → the marketplace clone's marketplace.json GitHub source on its branch /plugin marketplace update <mkt>, then /plugin
aidd CLI copy (OpenCode, Codex flat…) .aidd/manifest.json → marketplaces.json (project scope, then user scope) GitHub source on its branch aidd marketplace refresh <mkt>, then aidd plugin update
Local marketplace directory / framework checkout nearest .claude-plugin/marketplace.json never: the checkout is its own channel —

Remote check: raw.githubusercontent.com/<repo>/<ref or HEAD>/.claude-plugin/marketplace.json, which is the same component, source and channel. main only ever holds released versions. Pinned tags and commits, local checkouts and non-GitHub hosts are never compared. The result is cached for 24h in the CLI's own cache directory (<aidd config>/cache/framework-release-check.json, purged by aidd clean) and refreshed by a detached child. A session start never waits on the network. An unreachable source keeps the previous answer, or gives none, and never reads as "up to date". Cost of this design: the first session after the cache expires learns nothing new; the next one does.

🧪 How to verify

Gates: lefthook run pre-commit 15/15 ✔️ · lefthook run pre-push: knip ✔️, CLI 6871 passed / 1 skipped · node --test scripts/__tests__/*.test.js 618 passed.

New tests:

Real remote check: --refresh against raw.githubusercontent.com/ai-driven-dev/framework/HEAD/... recorded "latest":"5.12.0".

Real sessions. Each is a new process. Projects were installed by the CLI built from this branch (aidd setup --source local --ai opencode --plugins aidd-context), with the AGENTS.md template as their agent file, in a git-ignored tmp/ of the worktree:

Host Scenario First reply
OpenCode 2.1.4 installed from a local marketplace AI-Driven Development On ⚡ · Framework v5.12.0 · [Releases](…)
OpenCode 2.1.4 GitHub provenance, newer release in cache (simulated 5.13.0) greeting v5.12.0 + AIDD framework v5.13.0 is available (installed: v5.12.0). To update, run \aidd marketplace refresh aidd-framework`, then `aidd plugin update`. Nothing is installed automatically.`
OpenCode 2.1.4 after the upgrade (recorded version → 5.13.0) … Framework v5.13.0 …, no notice
OpenCode 2.1.4 no AIDD install, template only AI-Driven Development On ⚡ · Framework version unknown · [Releases](…)
OpenCode 1.19.4 (V1, npm latest) installed from a local marketplace AI-Driven Development On ⚡ · Framework v5.12.0 · [Releases](…); instrumented, the V1 experimental.chat.system.transform carried AIDD framework: v5.12.0…
OpenCode 1.19.4 (V1) same project, framework-version.cjs removed AI-Driven Development On ⚡ · Framework version unknown · [Releases](…)
Claude Code 2.1.310 --plugin-dir local plugin … Framework v5.12.0 …; hook_response carries the context
Claude Code 2.1.310 Claude cache layout + known_marketplaces.json with a GitHub source, newer release in cache greeting + notice with /plugin marketplace update aidd-framework; systemMessage present in the stream

OpenCode, server initialization vs conversation: instrumented, the V2 context hook fired once per model call and the V1 transform was called only through it, so the context is never injected twice. The scripts run once at plugin initialization, so the version is resolved per opencode process, not per conversation. Memory refresh (update_memory.js) still runs from the same SessionStart table.

⚠️ Heads-up

  • Codex: not verified at runtime. Codex has no login on this machine. Its documented SessionStart contract (additionalContext, systemMessage) is the one Claude Code honors, and Codex still requires each hook to be trusted once. Kilo's bridge is untouched, so Kilo is unverified. Copilot and Cursor are unverified as before.
  • The simulated cases are the GitHub provenance and the 5.13.0 cache entry: no release newer than 5.12.0 exists yet. The resolution and display code paths are the real ones.
  • An aidd CLI install reports the version recorded at its last marketplace add/refresh, which is the catalog its plugins came from. A user-scope CLI install, whose scripts live outside the project, resolves as unknown.
  • The framework's own CLAUDE.md greeting drops the date/TZ line for the canonical one. In this repo, OpenCode without an AIDD install greets with Framework version unknown. Claude Code with the repo's enabledPlugins resolves it.
  • OpenCode's bundle grew by ~2.6 KB (708.6 / 709 KB budget).

💬 On the issue comment (challenge)

"pour les utilisateurs je pense que ça les inciterait à upgrade en voyant qu'on a rajouté plein de choses sur les nouvelles versions mais que eux sont toujours en v3"

  1. The version alone incites nothing. "Framework v5.12.0" answers "which release am I on", which is the maintainer's need. It says nothing about what is new. Upgrades come from the notice, which this PR adds, and the [Releases] link, which shows the changes.
  2. "Still on v3" is not the case to design for. A v3 installation does not carry this hook, so it will never see the notice. Only users who are already on a release with this script benefit. The incentive starts working from the release after this one ships.
  3. The previous iteration of this PR contradicted the issue. A stamped version is exactly what the issue forbids ("after an upgrade, a new conversation resolves the updated installed version"), hence the rewrite.

✅ Acceptance criteria (#980)

  • CLI version + update availability: aidd update --check and menu System › Check for CLI update, reusing self-update
  • Native marketplace install runs the plugin-owned check without the AIDD CLI (Claude cache layout, proven)
  • Version + provenance for native remote, local directory and CLI-translated installs, or unknown
  • Greeting once per new conversation; the updated version after an upgrade (OpenCode, proven)
  • Same component / source / channel; the notice says each plugin keeps its own version
  • Visible notice with the install-mode update path; nothing auto-installed
  • Cached checks, never blocking, never a false up-to-date
  • Evidence per tool: Claude Code ✔️, OpenCode ✔️, Codex not run (see heads-up)
  • OpenCode: server initialization vs conversation distinguished; existing hooks preserved

🔗 Linked issue

Refs #980 (stays open until a Codex session proves the notice)

…tartup greeting

The startup greeting now carries the framework version resolved locally,
once per new conversation:

    AI-Driven Development On ⚡ · Framework v<version> · [Releases](https://github.com/ai-driven-dev/framework/releases)

<version> is read from the "version" field of .claude-plugin/marketplace.json
at the repository root — the framework release version, kept equal to the "."
entry of .release-please-manifest.json by release-please. When it cannot be
established, the greeting displays "Framework version unknown". The CLI
version, a plugin version, and the root package.json 0.0.0 placeholder are
never substituted.

- AGENTS.md, CLAUDE.md and cli/CLAUDE.md carried three drifted greetings;
  they now share one canonical instruction (drift tracked by #619).
- Version-source decision recorded in
  aidd_docs/memory/internal/decisions/startup-greeting-resolves-framework-version-locally.md

Verified in new OpenCode sessions: in this worktree the greeting reads
"Framework v5.12.0" after a local read of .claude-plugin/marketplace.json;
in a project without that file it reads "Framework version unknown".
aidd-dev check passes (527 test files, 6866 tests).

Implements the visible behavior of #980. The update-notification half
(CLI surface, plugin-owned startup check, cached remote comparison,
install provenance) stays open.
@alexsoyes
alexsoyes requested a review from a team as a code owner October 25, 2026 15:37
…g, bumped by release PRs

The greeting in AGENTS.md, CLAUDE.md and cli/CLAUDE.md now carries the literal
release version ("Framework v5.12.0"), annotated with x-release-please-version,
and the three files join the root package's extra-files in
release-please-config.json. Every release PR bumps the stamped version, alongside
marketplace.json: the version is dynamic, delivered by the pull request process.

This replaces the previous runtime-resolution instruction (the agent read
marketplace.json at conversation start): non-deterministic, and "Framework
version unknown" in projects installed from the marketplace, where no
marketplace.json exists at the project root. The agent now repeats the greeting
verbatim.

Decision: aidd_docs/memory/internal/decisions/startup-greeting-carries-the-framework-release-version.md

Verified in new OpenCode sessions in the feature worktree: the greeting shows
v5.12.0 verbatim; with only the agent file present (no marketplace.json) it still
shows v5.12.0; simulating a release PR (Generic updater logic applied to the
annotated lines, 5.12.0 -> 5.13.0) shows v5.13.0. aidd-dev check passes.

Implements the visible behavior of #980. The update-notification half (CLI
surface, plugin-owned startup check, cached remote comparison, install
provenance) stays open.
…script

The startup greeting carries the framework release version, stamped by
scripts/sync-greeting-version.mjs: the script reads the release version from
.claude-plugin/marketplace.json (as cut on the next branch) and rewrites
Framework v<semver> on the greeting line of every target — the framework's own
agent files (AGENTS.md, CLAUDE.md, cli/CLAUDE.md) and the usage template
shipped to user projects
(plugins/aidd-context/skills/02-project-memory/assets/templates/AGENTS.md).

The usage template gains the greeting (it had none since 4446fff), so a project
set up from a release greets with that release's version.

A lefthook pre-commit hook (sync-greeting-version, same pattern as
sync-readme-counts) runs the script on every commit and re-stages the touched
files, so the greeting never drifts from the release. The script is idempotent
and supports --check.

This replaces the release-please extra-files stamping from the previous commit:
the upkeep now belongs to the framework's own transformation script, matching
the issue's direction that the framework generates information dynamically with
tooling.

Decision: aidd_docs/memory/internal/decisions/startup-greeting-carries-the-framework-release-version.md

Verified: 5 new tests for the script pass; simulating a release (marketplace
version 5.12.0 -> 5.13.0) and running the script re-stamps all four targets to
v5.13.0; a new OpenCode session in a project built from the template greets
with "Framework v5.12.0" verbatim. aidd-dev check passes.
Comment thread scripts/sync-greeting-version.mjs Fixed
…tart

The greeting no longer carries a version stamped into the agent files:
a copied template goes stale at the first upgrade and is shared by every
teammate. aidd-context's SessionStart script reads the marketplace version
from the installation's own provenance (Claude Code cache, aidd CLI record,
local marketplace) and hands it to the conversation, or reports it unknown.

A newer release on the same GitHub source and branch is announced from a
24h cache refreshed by a detached child, with the update path of the
installation mode; pinned refs, local checkouts and other hosts are never
compared and nothing is installed.

OpenCode's generated bridge now forwards SessionStart output to every
model call (V1 system transform, V2 context hook). The CLI menu gains a
CLI version entry over `aidd update --check`.

Refs #980
@alexsoyes alexsoyes changed the title feat(framework): show the locally resolved framework version in the startup greeting feat(framework): show the installed framework version and newer releases at startup Oct 26, 2026
@alexsoyes alexsoyes changed the title feat(framework): show the installed framework version and newer releases at startup feat(framework): show the installed framework version at startup Oct 26, 2026
…ctory

On Windows a live child's working directory cannot be removed, so the detached refresh held the project for up to its fetch timeout. The test sandbox resolves macOS's symlinked temp dir.
@alexsoyes alexsoyes closed this Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants