Skip to content

About

Focused PHP coding standards, explicit fixes and changed-file checks.

Topics

Resources

Code of conduct

Contributing

Security policy

Accessibility

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

129 Commits

Folders and files

Fast Forward Code Standards

Dash, the Fast Forward fox, aligning source cards to illustrate consistent code style. PHP Composer Package Tests Docs License GitHub Sponsors

Focused PHP style and static syntax checks, independent of DevTools. The library provides an extendable ECS PER Coding Style 3.0 preset; the CLI checks tracked PHP files or the files changed by an exact PR head. It validates PHP syntax and style; type analysis, application tests and coverage belong to their respective tools.

✨ Features

  • Native ECS configuration with consumer overrides applied last.
  • Read-only syntax/style checking and explicitly requested local fixes.
  • Exact PR merge-base selection with binary-safe file paths.
  • Invocable Symfony Console commands composed with Fast Forward Container.
  • An unprivileged reusable workflow with explicit optional analysis summaries and a portable consumption skill.

πŸ“¦ Installation and requirements

Install the published development tool in your Git project:

composer require --dev fast-forward/code-standards
vendor/bin/code-standards check --all

CPX can invoke the installed package directly with cpx fast-forward/code-standards list. The CLI resolves Composer dependencies from its installation, including when run outside the package checkout.

The GitHub v0 workflow channel and the Composer package are separate distribution mechanisms.

Requires PHP 8.3 or later in the 8.x series, Git and Composer runtime API 2.2+ for installed binary proxies. Composer resolves the tool with the project's dependency constraints; syntax is checked using the executing PHP binary. No PHP migration rules are enabled. Review compatibility with the application's minimum PHP before adopting a preset.

Workflow guards and their contributor tests additionally require Bash and jq. Hosted Ubuntu runners provide both; the Composer library and CLI use the PHP dependencies declared in this package.

Composer exposes the portable skills through extra.skills.source at resources/skills. llm/skills is an optional consumer integration; installation and activation are explicit. The development check script validates Composer metadata and the actual platform before running this package's tests and style check.

Use the Code Standards skill for tool adoption and explicit formatting. Use the dedicated PHPDoc skill to write or review concise summaries, semantic contracts, useful tags and inherited documentation. Each payload includes its license and relative references; neither activates an agent or installs another tool automatically. See the optional skill installation and lifecycle guide for project discovery, trust and update ownership.

For a reviewed source checkout:

composer install --no-plugins --no-scripts
php bin/code-standards help
php bin/code-standards check --all
php bin/code-standards check --base=BASE_COMMIT_SHA --head=HEAD_COMMIT_SHA
php bin/code-standards fix --all
composer test

πŸ› οΈ Usage

check reports violations with a nonzero status and does not change source. Use check --all --format=json for an explicit single-document machine report, including native ECS findings, failure classification and remaining-work counts. See the structured check contract. Text is the default; fix uses text output. Use --format=json-pretty for the same report with indentation; see result presentation. The default preset stores its ECS cache beneath the system temporary directory, in fast-forward-code-standards/<SHA-256 of the executing checkout path>/<owned-policy fingerprint>. The fingerprint includes the installed preset and owned checker paths and source bytes. Different checkouts cannot invalidate each other's cache, and a changed owned rule cannot reuse an earlier passing result. Native withCache() overrides remain supported and apply last; share cache directories only when their invalidation and concurrent use are intentionally coordinated. fix explicitly applies ECS fixes. It does not commit, push or update dependencies. After each successful formatter batch, a read-only check verifies the result. Any remaining violation or tool error is returned as a nonzero status. A formatter pass can expose another rule, such as EOF normalization preceding opening-tag spacing; inspect the partial diff before explicitly requesting another fix. Recheck and inspect the diff afterward; failures can leave already applied fixes. An empty PHP selection is a successful no-op. Invalid options, configuration paths, Git history or head mismatch fail closed with exit 2. Syntax/style tool failures, including executable configuration errors inside ECS, retain their tool status. Changed mode requires a clean tracked checkout of the requested head. --all includes tracked files and permits inspecting local tracked edits. Symfony Console provides help check, standard global flags and both --option=value and --option value. Error diagnostics use stderr. Empty paths, conflicting scan modes and unsupported arguments are rejected explicitly.

βš™οΈ Configuration and extension

Install fast-forward/code-standards as development tooling. Select the Composer package and workflow/runtime refs independently: Composer resolves package dependencies, while the GitHub workflow uses its reviewed ref.

<?php

declare(strict_types=1);

use FastForward\CodeStandards\Config\ECSConfig;
use Symplify\EasyCodingStandard\Configuration\ECSConfigBuilder;

require __DIR__ . '/vendor/autoload.php';

return ECSConfig::configure(static function (ECSConfigBuilder $config): void {
    // Local rule imports/overrides go last; review their semantic risk.
    $config->withConfiguredRule(
        \PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer::class,
        ['align' => 'left'],
    );
});

Select it explicitly with --config=ecs.php. PHP configuration is executable code and belongs in an unprivileged environment. The CLI defaults to its own preset, does not discover or overwrite consumer configuration, and never runs both ECS and a competing PHP-CS-Fixer pass. Standalone ECS users may import the same library preset and set their own paths. CLI selection uses the scope below; ECS's configured paths do not expand the CLI's explicit selected file list.

For braced multiline if, elseif, while and do-while conditions, the native PSR-12 wrapper places the first expression on the next line and the closing parenthesis on its own line () {, or ); for do-while). The native leading-operator policy follows PER 3.0. An owned whitespace policy additionally puts each symbolic && and || on its own line in those multiline conditions. The policy includes grouped expressions, call arguments and array indexes within that condition; function, arrow and anonymous-class declarations remain opaque. Single-line conditions and other expression contexts retain their native rules. Splitting every operator, including nested expression parts, is a project extension rather than an additional PER requirement. The default is four spaces and LF. Native ECS withSpacing() overrides for two spaces, tabs or CRLF remain supported as explicit deviations from PSR-12/PER, not standards-compliant alternatives. Consumers can explicitly skip FastForward\CodeStandards\Sniff\MultilineBooleanConditionSniff through withSkip(); that native method replaces the skip list, so preserve any other intended preservation skips. See the resolved preset. The separate MultilineConditionSpacingSniff adapts the native wrapper to the same spacing service. Alternative colon syntax is preserved; the wrapper tests do not certify that syntax, or the complete preset, against every PSR/PER rule.

The formatter worker uses ECS's public factory and command APIs with this tool's own Composer installation. An isolated tool does not implicitly load the target checkout's vendor/autoload.php. Explicit PHP configuration retains the checkout as getcwd(), keeps __DIR__ and relative paths intact, and may deliberately require consumer autoloaders or register custom checkers. When the tool is a development dependency in the consumer's own Composer graph, that installation's normal binary-proxy bootstrap remains intentional; it is not a separate import of another checkout's dependency graph.

πŸ”Œ Integration and file scope

  • Tracked *.php and PHP entrypoints under bin/ are included.
  • The consumer's root and nested .gitignore files dynamically exclude matching paths, including already tracked/force-added files. Git interprets patterns, anchors, escapes and negations; this tool has no replacement glob parser. Global ignores and .git/info/exclude do not alter this project-owned policy. Untracked files remain outside the CLI's candidate universe. Only .git metadata is structurally excluded, including worktree metadata files; names such as public, resources or backup are eligible unless the consumer ignores them. Containment and PHP symlink rejection still apply.
  • Candidate PHP/bin symlink paths fail closed; unrelated non-PHP aliases are ignored. Spaces, tabs, newlines and leading dashes remain individual subprocess arguments; deleted files are omitted, renames use destinations.
  • Changed mode uses base...head, so unrelated base-branch changes are excluded. Composer, ECS, EditorConfig and root/nested .gitignore changes escalate to a complete tracked scan.
  • Tools run in bounded batches and stop on failure. Syntax checks use php -n -l, so selected application sources are parsed without executing them.

Start with the usage guide. See policy and differences, workflow/ref adoption and the consumer skill. The architecture decision defines library/tool dependency directions and CPX/autoload limits. The formatter preserves descriptive PHPDoc and inherited documentation. The separate opt-in refactor command previews an explicit native Rector configuration and requires --apply for semantic writes. It is never invoked by formatting check or fix; target PHP and cache remain native consumer configuration decisions. Custom PHPDoc transformations and deeper static analysis remain separate; no DevTools extraction parity is asserted.

The reusable workflow accepts normalize-composer: true to check the consumer's root Composer metadata without writes (default: false). This project's own CI enables the check. See workflow behavior.

The optional runs-on JSON input selects an existing Linux self-hosted runner for same-repository data-only checks. Forks, executable ECS config and Rector use hosted Ubuntu. See runner trust and requirements.

🧰 API summary

The reusable keeps optional analyses disabled by default. Enable magic-numbers: true or rector: true explicitly; Rector also requires rector-config. Each tool's *-policy accepts report or fail for verified findings. Operational failures always fail, including invalid/incomplete native reports. A visible summary distinguishes disabled, not executed, clean, findings and operational error, with native counts and available file/line information. See optional workflow analyses for inputs, limits, trust boundaries and consumer examples. The selected workflow revision defines its input contract independently of Composer package constraints.

Entry point Contract
code-standards check Parse selected PHP and check style without changing source.
code-standards fix Explicitly format selected source, then verify; failures may leave partial changes.
code-standards normalize-composer Check Composer metadata without writing; --apply changes only composer.json and reports stale lock hashes.
code-standards refactor --config=rector.php Preview native semantic rules; only --apply permits writes, followed by verification.
code-standards magic-numbers Analyze selected source with opt-in PHPMND, independently of check/fix; findings keep a nonzero status.
code-standards refactor --config=rector.php --format=json Emit native JSON for preview only; JSON cannot be combined with --apply.
ECSConfig::configure(?callable $customize) Return the native ECS builder; apply the optional callback last.
help check / help fix / help refactor / help magic-numbers Show the installed Symfony option definitions.
help normalize-composer Show metadata normalization options and explicit write authority.

Internal CLI services are implementation details. Supported configuration uses native ECS rule imports, skips and configured rules; there is no second DSL.

πŸ“ Package layout

bin/code-standards                       CLI entrypoint
config/ecs.php                          default native ECS configuration
src/Config/ECSConfig.php                 reusable preset API
resources/skills/fast-forward-code-standards/  canonical consumer skill
resources/skills/fast-forward-phpdoc/     portable PHPDoc authoring skill
resources/workflows/code-standards.yml   consumer workflow wrapper
.github/actions/check/                  small check adapter
docs/                                   architecture, policy and integration guides

πŸ› οΈ Versioning and compatibility

Development releases stay in 0.x. A compatible correction uses a patch; functionality and breaking development changes use a minor. Changelog automation prepares and publishes versions through reviewed PRs. Verify actual releases before selecting a Composer constraint. The GitHub v0 channel follows verified publications and can advance across development minors; it is not a Composer package constraint.

❓ FAQ

Optional magic-number analysis

Run vendor/bin/code-standards magic-numbers --all explicitly for PHPMND analysis. Add --format=xml for its native machine-readable report. The command uses the same tracked-file/Git ignore policy and does not run as part of check or fix. See options, status and adoption guidance.

Can I use this as a staged-only pre-commit check? The CLI selects working-tree files from Git, not staged index blobs. Changed mode requires a clean tracked checkout and cannot certify staged-only content.

Do formatting check/fix run PHPStan, Rector or my application's tests? No. Formatting checks syntax and style. The separate opt-in refactor command uses an explicit native Rector configuration; it never runs through check/fix. Type analysis and application testing remain separate scopes.

Does a successful fix always mean the source is clean? The CLI verifies each formatted batch and reports remaining violations. Rules can interact across passes; inspect the diff before explicitly fixing again.

Where do agent skills come from? The canonical payload is under resources/skills, advertised by extra.skills.source. Consumers may explicitly select the optional LLM Skills manager. This package does not provide another installer, activate skills or migrate consumer settings.

πŸ›‘οΈ License

MIT. Dash artwork follows the PHP Fast Forward brand references; the upstream artwork provenance record records its generative origin and historical rights limits separately.

🀝 Contributing

Read AGENTS.md, add a focused regression and a unique .changelog fragment, then open a scoped PR. Preserve check's source/lock no-write guarantee.

composer install --no-plugins --no-scripts
composer check

Workflow contributor checks also need Bash and jq. Changes use normal current-head CI and review gates; this guide does not authorize release, security-setting changes or consumer rollout.

πŸ”— Links

About

Focused PHP coding standards, explicit fixes and changed-file checks.

Topics

Resources

Code of conduct

Contributing

Security policy

Accessibility

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages