Problem
The startup notification for a newer DevTools release does not appear when fast-forward/dev-tools is installed globally, even when the installed version is outdated.
I reproduced this on April 30, 2026 with a clean Composer home by installing fast-forward/dev-tools v1.24.1 globally and then running dev-tools list while v1.24.3 was already available on Packagist. The command rendered the normal banner and command list, but it stayed silent instead of printing the expected update warning.
Current Behavior
- A global install on
v1.24.1 does not print the update notification while v1.24.3 is available.
- The command still succeeds, so the failure is easy to miss in manual testing.
- Repository checkouts do not expose the problem because
ComposerVersionChecker::check() returns early for repository mode.
Why It Happens
The failure is currently inside ComposerVersionChecker, not in the notification formatting itself.
FastForward\\DevTools\\SelfUpdate\\ComposerVersionChecker::resolveLatestStableVersion() compares the process exit code against Symfony\\Component\\Process\\Process::SUCCESS.
- In the supported runtime I reproduced (
symfony/process v8.0.8), Process::SUCCESS does not exist.
- That triggers a runtime
Error before the checker can return a VersionCheckResult.
FastForward\\DevTools\\SelfUpdate\\VersionCheckNotifier::notify() catches Throwable and intentionally stays silent, so the user sees no warning at all.
This explains why the feature appears to be broken specifically for global installs: that is the execution mode where the version check actually runs.
Reproduction
export COMPOSER_HOME="$(mktemp -d /tmp/dev-tools-global-check.XXXXXX)"
composer global require fast-forward/dev-tools:v1.24.1 --no-interaction --no-progress --no-plugins
"$COMPOSER_HOME/vendor/bin/dev-tools" list
Expected behavior:
dev-tools warns that a newer version is available.
Actual behavior:
- no update warning is printed.
Additional verification from the same runtime:
php <<PHP
<?php
require "$COMPOSER_HOME/vendor/autoload.php";
$checker = new FastForward\DevTools\SelfUpdate\ComposerVersionChecker(
new FastForward\DevTools\Process\ProcessBuilder(),
);
$checker->check();
PHP
That call currently fails with an Undefined constant Symfony\\Component\\Process\\Process::SUCCESS error.
Proposed Fix
- Update
ComposerVersionChecker to use a supported success check for the configured symfony/process range instead of Process::SUCCESS.
- Add regression coverage that exercises the real checker path used outside repository checkouts.
- Keep the version notification best-effort and non-blocking once the runtime failure is removed.
Acceptance Criteria
- A dependency/global DevTools install on an outdated version prints the update warning again.
ComposerVersionChecker no longer depends on a missing symfony/process constant in supported runtimes.
- Regression coverage is added for the runtime checker path so this failure is caught automatically.
- Existing skip behavior for CI and explicit version-check opt-out remains unchanged.
Non-Goals
- Redesigning the self-update flow.
- Changing the decision to skip version checks for repository checkouts.
Problem
The startup notification for a newer DevTools release does not appear when
fast-forward/dev-toolsis installed globally, even when the installed version is outdated.I reproduced this on April 30, 2026 with a clean Composer home by installing
fast-forward/dev-toolsv1.24.1globally and then runningdev-tools listwhilev1.24.3was already available on Packagist. The command rendered the normal banner and command list, but it stayed silent instead of printing the expected update warning.Current Behavior
v1.24.1does not print the update notification whilev1.24.3is available.ComposerVersionChecker::check()returns early for repository mode.Why It Happens
The failure is currently inside
ComposerVersionChecker, not in the notification formatting itself.FastForward\\DevTools\\SelfUpdate\\ComposerVersionChecker::resolveLatestStableVersion()compares the process exit code againstSymfony\\Component\\Process\\Process::SUCCESS.symfony/processv8.0.8),Process::SUCCESSdoes not exist.Errorbefore the checker can return aVersionCheckResult.FastForward\\DevTools\\SelfUpdate\\VersionCheckNotifier::notify()catchesThrowableand intentionally stays silent, so the user sees no warning at all.This explains why the feature appears to be broken specifically for global installs: that is the execution mode where the version check actually runs.
Reproduction
Expected behavior:
dev-toolswarns that a newer version is available.Actual behavior:
Additional verification from the same runtime:
That call currently fails with an
Undefined constant Symfony\\Component\\Process\\Process::SUCCESSerror.Proposed Fix
ComposerVersionCheckerto use a supported success check for the configuredsymfony/processrange instead ofProcess::SUCCESS.Acceptance Criteria
ComposerVersionCheckerno longer depends on a missingsymfony/processconstant in supported runtimes.Non-Goals