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
2 changes: 1 addition & 1 deletion .github/wiki
Submodule wiki updated from 546706 to caa2be
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Keep packaged `.agents` payloads exportable and synchronize packaged skills and agents with repository-relative symlink targets so consumer repositories no longer receive broken absolute machine paths (#188)
- Rewrite drifted Git hooks by removing the previous target first, restore the intended `0o755` executable mode, and report unwritable hook replacements cleanly when `.git/hooks` stays locked (#190)
- Keep Composer plugin command discovery compatible with consumer environments by moving unsupported Symfony Console named parameters out of command metadata/configuration and by decoupling the custom filesystem wrapper from Composer's bundled Symfony Filesystem signatures (#185)

## [1.20.0] - 2026-04-23

Expand Down
7 changes: 5 additions & 2 deletions src/Console/Command/AgentsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
*/
#[AsCommand(
name: 'agents',
description: 'Synchronizes Fast Forward project agents into .agents/agents directory.',
help: 'This command ensures the consumer repository contains linked Fast Forward project agents by creating symlinks to the packaged prompts and removing broken links.'
description: 'Synchronizes Fast Forward project agents into .agents/agents directory.'
)]
final class AgentsCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand All @@ -63,6 +62,10 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command ensures the consumer repository contains linked Fast Forward project agents by creating'
. ' symlinks to the packaged prompts and removing broken links.'
);
$this->addJsonOption();
}

Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/ChangelogCheckCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
*/
#[AsCommand(
name: 'changelog:check',
description: 'Checks whether a changelog file contains meaningful unreleased entries.',
help: 'This command validates the current Unreleased section and may compare it against a base git reference to enforce pull request changelog updates.'
description: 'Checks whether a changelog file contains meaningful unreleased entries.'
)]
final class ChangelogCheckCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand All @@ -61,6 +60,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command validates the current Unreleased section and may compare it against a base git'
. ' reference to enforce pull request changelog updates.'
);

$this->addJsonOption()
->addOption(
name: 'against',
Expand Down
12 changes: 6 additions & 6 deletions src/Console/Command/ChangelogEntryCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
*/
#[AsCommand(
name: 'changelog:entry',
description: 'Adds a changelog entry to Unreleased or a specific version section.',
help: 'This command appends one categorized changelog entry to the selected changelog file so it can be reused by local authoring flows and skills.'
description: 'Adds a changelog entry to Unreleased or a specific version section.'
)]
final class ChangelogEntryCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand All @@ -64,6 +63,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command appends one categorized changelog entry to the selected changelog file so it can be'
. ' reused by local authoring flows and skills.'
);

$this->addJsonOption()
->addArgument(
name: 'message',
Expand All @@ -76,10 +80,6 @@ protected function configure(): void
mode: InputOption::VALUE_REQUIRED,
description: 'The changelog category (added, changed, deprecated, removed, fixed, security).',
default: 'added',
suggestedValues: array_map(
static fn(ChangelogEntryType $type): string => strtolower($type->value),
ChangelogEntryType::ordered()
),
)
->addOption(
name: 'release',
Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/ChangelogNextVersionCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
*/
#[AsCommand(
name: 'changelog:next-version',
description: 'Infers the next semantic version from the Unreleased changelog section.',
help: 'This command inspects Unreleased changelog categories and prints the next semantic version inferred from the current changelog state.'
description: 'Infers the next semantic version from the Unreleased changelog section.'
)]
final class ChangelogNextVersionCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand All @@ -62,6 +61,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command inspects Unreleased changelog categories and prints the next semantic version inferred'
. ' from the current changelog state.'
);

$this->addJsonOption()
->addOption(
name: 'file',
Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/ChangelogPromoteCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
*/
#[AsCommand(
name: 'changelog:promote',
description: 'Promotes Unreleased entries into a published changelog version.',
help: 'This command moves the current Unreleased entries into a released version section, records the release date, and restores an empty Unreleased section.'
description: 'Promotes Unreleased entries into a published changelog version.'
)]
final class ChangelogPromoteCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand All @@ -66,6 +65,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command moves the current Unreleased entries into a released version section, records the'
. ' release date, and restores an empty Unreleased section.'
);

$this->addJsonOption()
->addArgument(
name: 'version',
Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/ChangelogShowCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@
*/
#[AsCommand(
name: 'changelog:show',
description: 'Prints the notes body for a released changelog version.',
help: 'This command renders the body of one released changelog section so it can be reused for GitHub release notes.'
description: 'Prints the notes body for a released changelog version.'
)]
final class ChangelogShowCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand All @@ -63,6 +62,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command renders the body of one released changelog section so it can be reused for GitHub'
. ' release notes.'
);

$this->addJsonOption()
->addArgument(
name: 'version',
Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/CodeOwnersCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@
*/
#[AsCommand(
name: 'codeowners',
description: 'Generates .github/CODEOWNERS from local project metadata.',
help: 'This command infers CODEOWNERS entries from composer.json metadata, falls back to a commented template, and supports drift-aware preview and overwrite flows.'
description: 'Generates .github/CODEOWNERS from local project metadata.'
)]
final class CodeOwnersCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -67,6 +66,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command infers CODEOWNERS entries from composer.json metadata, falls back to a commented'
. ' template, and supports drift-aware preview and overwrite flows.'
);

$this->addJsonOption()
->addOption(
name: 'file',
Expand Down
7 changes: 5 additions & 2 deletions src/Console/Command/CodeStyleCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
*/
#[AsCommand(
name: 'code-style',
description: 'Checks and fixes code style issues using EasyCodingStandard and Composer Normalize.',
help: 'This command runs EasyCodingStandard and Composer Normalize to check and fix code style issues.'
description: 'Checks and fixes code style issues using EasyCodingStandard and Composer Normalize.'
)]
final class CodeStyleCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -83,6 +82,10 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command runs EasyCodingStandard and Composer Normalize to check and fix code style issues.'
);

$this->addJsonOption()
->addOption(
name: 'progress',
Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/CopyResourceCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@
*/
#[AsCommand(
name: 'copy-resource',
description: 'Copies a file or directory resource into the current project.',
help: 'This command copies a configured source file or every file in a source directory into the target path.'
description: 'Copies a file or directory resource into the current project.'
)]
final class CopyResourceCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -71,6 +70,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command copies a configured source file or every file in a source directory into the target'
. ' path.'
);

$this->addJsonOption()
->addOption(
name: 'source',
Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/DependenciesCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@
#[AsCommand(
name: 'dependencies',
description: 'Analyzes missing, unused, misplaced, and outdated Composer dependencies.',
aliases: ['deps'],
help: 'This command runs composer-dependency-analyser and Jack to report missing, unused, misplaced, and outdated Composer dependencies.'
aliases: ['deps']
)]
final class DependenciesCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -76,6 +75,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command runs composer-dependency-analyser and Jack to report missing, unused, misplaced, and'
. ' outdated Composer dependencies.'
);

$this->addJsonOption()
->addOption(
name: 'max-outdated',
Expand Down
4 changes: 2 additions & 2 deletions src/Console/Command/DocsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@
*/
#[AsCommand(
name: 'docs',
description: 'Generates API documentation.',
help: 'This command generates API documentation using phpDocumentor.',
description: 'Generates API documentation.'
)]
final class DocsCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -83,6 +82,7 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp('This command generates API documentation using phpDocumentor.');
$this
->addJsonOption()
->addCacheOption('Whether to enable phpDocumentor caching.')
Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/FundingCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@
*/
#[AsCommand(
name: 'funding',
description: 'Synchronizes funding metadata between composer.json and .github/FUNDING.yml.',
help: 'This command merges supported funding entries across composer.json and .github/FUNDING.yml while preserving unsupported providers.'
description: 'Synchronizes funding metadata between composer.json and .github/FUNDING.yml.'
)]
final class FundingCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -79,6 +78,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command merges supported funding entries across composer.json and .github/FUNDING.yml while'
. ' preserving unsupported providers.'
);

$this->addJsonOption()
->addOption(
name: 'composer-file',
Expand Down
10 changes: 7 additions & 3 deletions src/Console/Command/GitAttributesCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@
*/
#[AsCommand(
name: 'gitattributes',
description: 'Manages .gitattributes export-ignore rules for leaner package archives.',
help: 'This command adds export-ignore entries for repository-only files and directories to keep them out of Composer package archives. '
. 'Only paths that exist in the repository are added, existing custom rules are preserved, and "extra.gitattributes.keep-in-export" paths stay in exported archives.'
description: 'Manages .gitattributes export-ignore rules for leaner package archives.'
)]
final class GitAttributesCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -98,6 +96,12 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command adds export-ignore entries for repository-only files and directories to keep them out of Composer package archives. '
. 'Only paths that exist in the repository are added, existing custom rules are preserved, and '
. '"extra.gitattributes.keep-in-export" paths stay in exported archives.'
);

$this->addJsonOption()
->addOption(
name: 'dry-run',
Expand Down
5 changes: 3 additions & 2 deletions src/Console/Command/GitHooksCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@
*/
#[AsCommand(
name: 'git-hooks',
description: 'Installs Fast Forward Git hooks.',
help: 'This command copies packaged Git hooks into the current repository.'
description: 'Installs Fast Forward Git hooks.'
)]
final class GitHooksCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -71,6 +70,8 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp('This command copies packaged Git hooks into the current repository.');

$this->addJsonOption()
->addOption(
name: 'source',
Expand Down
5 changes: 3 additions & 2 deletions src/Console/Command/GitIgnoreCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
*/
#[AsCommand(
name: 'gitignore',
description: 'Merges and synchronizes .gitignore files.',
help: "This command merges the canonical .gitignore from dev-tools with the project's existing .gitignore."
description: 'Merges and synchronizes .gitignore files.'
)]
final class GitIgnoreCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -88,6 +87,8 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp("This command merges the canonical .gitignore from dev-tools with the project's existing .gitignore.");

$this->addJsonOption()
->addOption(
name: 'source',
Expand Down
8 changes: 6 additions & 2 deletions src/Console/Command/LicenseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@
*/
#[AsCommand(
name: 'license',
description: 'Generates a LICENSE file from composer.json license information.',
help: 'This command generates a LICENSE file if one does not exist and a supported license is declared in composer.json.'
description: 'Generates a LICENSE file from composer.json license information.'
)]
final class LicenseCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -69,6 +68,11 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp(
'This command generates a LICENSE file if one does not exist and a supported license is declared in'
. ' composer.json.'
);

$this->addJsonOption()
->addOption(
name: 'target',
Expand Down
5 changes: 3 additions & 2 deletions src/Console/Command/MetricsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@

#[AsCommand(
name: 'metrics',
description: 'Analyzes code metrics with PhpMetrics.',
help: 'This command runs PhpMetrics to analyze the current working directory.',
description: 'Analyzes code metrics with PhpMetrics.'
)]
final class MetricsCommand extends BaseCommand implements LoggerAwareCommandInterface
{
Expand Down Expand Up @@ -72,6 +71,8 @@ public function __construct(
*/
protected function configure(): void
{
$this->setHelp('This command runs PhpMetrics to analyze the current working directory.');

$this->addJsonOption()
->addOption(
name: 'progress',
Expand Down
Loading
Loading