Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5e3ee24
test: qualify PHAR packaging and preserve copyable resources
coisa Oct 28, 2026
806f298
chore: reconcile PHAR experiment with release-channel cleanup
coisa Oct 28, 2026
62f49d2
ci: qualify PHAR runtime in the existing PHP matrix
coisa Oct 28, 2026
7185eac
feat: build the direct Composer executable with PHP
coisa Oct 28, 2026
4f01ae9
merge: reconcile current source and bind PHAR identity
coisa Oct 28, 2026
cbb5d77
fix: bind PHAR inventory to the actual staged inputs
coisa Oct 28, 2026
4eb9442
fix: qualify normalized PHP builds and source installs
coisa Oct 28, 2026
3c9729f
feat: include the ready PHAR in standard Composer distributions
coisa Oct 28, 2026
73fb64e
test: recognize the published artifact upload channel
coisa Oct 28, 2026
2f5627e
Merge branch 'main' into codex/phar-distribution-poc
coisa Oct 29, 2026
d5e7aa6
fix: bound PHAR cache lifetime and verify executable parity
coisa Oct 29, 2026
9b9362a
docs: format Composer scripts and clarify compiled cache lifetime
coisa Oct 29, 2026
bc90378
test: qualify compiled ECS consumer development rules
coisa Oct 29, 2026
502841a
Merge main into compiled distribution qualification
coisa Oct 29, 2026
e4c6f84
Merge branch 'main' into codex/phar-distribution-poc
coisa Oct 29, 2026
8f34ec5
fix: build current distribution with locked Composer
coisa Oct 29, 2026
406ce3b
Preserve remote main reconciliation in PHAR branch
coisa Oct 29, 2026
ea45a13
Merge branch 'main' into codex/phar-distribution-poc
coisa Nov 3, 2026
392c861
test: accept the published GitHub Script v9 workflow ref
coisa Nov 10, 2026
be42d8a
fix: qualify the compiled distribution on current main
coisa Nov 10, 2026
5bef00c
Merge current main into PHAR distribution qualification
coisa Nov 11, 2026
15e93f2
build: refresh compiled distribution for the reconciled lock
coisa Nov 11, 2026
b25da19
fix: refresh compiled distribution and published Changelog runtime
coisa Nov 11, 2026
2f649f8
Merge the maintainer refresh without replacing its executable
coisa Nov 11, 2026
cbee4af
ci: refresh compiled distribution on pull requests
coisa Nov 11, 2026
610ab2b
Merge branch 'main' into codex/phar-distribution-poc
coisa Nov 11, 2026
0ae6c1a
refactor: compile distribution with Box in dist
coisa Nov 11, 2026
48b8d05
refactor: simplify PHAR tooling and CI autocommit
coisa Nov 11, 2026
3c4b01c
build: adopt the qualified CI artifact and standard refresh workflow
coisa Nov 11, 2026
cf2c0bc
fix: name temporary runtimes after package
coisa Nov 12, 2026
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
14 changes: 14 additions & 0 deletions .changelog/compiled-composer-distribution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
category: added
type: minor
---

Distribute Code Standards as a ready-to-run PHAR for project and global Composer
installations, keeping bundled libraries out of the consumer dependency graph.
Preserve the complete resources and skills payload, support explicitly loaded
consumer ECS rules, and remove invocation-owned formatter caches at shutdown.
Build from the locked runtime and verify the complete executable against a fresh
build before execution. Compile with Box and a tracked configuration, keeping
the compiler isolated in CI. Refresh stale compiled executables through a separate
CI autocommit on unchanged same-repository PR heads. Use the compatible published Changelog workflow for
contribution checks and the existing release lifecycle.
8 changes: 7 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
* text=auto
*.php text eol=lf
/bin/code-standards text eol=lf
/dist/code-standards binary

# Local state and synchronized copies never belong to package distributions.
/.git export-ignore
Expand All @@ -12,13 +13,18 @@

# Contributor-only configuration and test infrastructure.
/tests/ export-ignore
/scripts/phar/ export-ignore
/.github/workflows/ export-ignore
/AGENTS.md export-ignore
/skills.json export-ignore
/phpunit.xml export-ignore
/box.json export-ignore
/.editorconfig export-ignore
/.gitignore export-ignore
/.gitattributes export-ignore
/.changelog/ export-ignore

# Keep src/, bin/, config/, resources/, composer.lock, README and its Dash image.
# Ready distributions retain the PHAR, manifests, complete resources and documentation.
/src/ export-ignore
/config/ export-ignore
/bin/ export-ignore
2 changes: 1 addition & 1 deletion .github/workflows/code-standards-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
env:
COMPOSER_HOME: ${{ runner.temp }}/standards-analysis-composer-home
COMPOSER_CACHE_DIR: ${{ runner.temp }}/standards-analysis-composer-cache
run: composer install --no-dev --no-plugins --no-scripts --no-interaction --prefer-dist --no-progress
run: composer install --no-plugins --no-scripts --no-interaction --prefer-dist --no-progress
- name: Check out exact consumer head
if: inputs.magic-numbers || inputs.rector
uses: actions/checkout@v7
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/code-standards-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
env:
COMPOSER_HOME: ${{ runner.temp }}/standards-composer-home
COMPOSER_CACHE_DIR: ${{ runner.temp }}/standards-composer-cache
run: composer install --no-dev --no-plugins --no-scripts --no-interaction --prefer-dist --no-progress
run: composer install --no-plugins --no-scripts --no-interaction --prefer-dist --no-progress
- name: Check out exact consumer head
uses: actions/checkout@v7
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/repository-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ jobs:
pull-requests: write
issues: read
statuses: write
# Reviewed integration candidate combines publication API and original-PR provenance fixes.
uses: php-fast-forward/changelog/.github/workflows/changelog.yml@42bc58fbab55596ee03d480ebf71d2a3dfc48fb4
# Verified v0 currently supplies the publication-only App API.
uses: php-fast-forward/changelog/.github/workflows/changelog.yml@v0
Comment thread
coisa marked this conversation as resolved.
Resolved
with:
runs-on: '["ubuntu-latest"]'
base-branch: main
Expand Down
44 changes: 43 additions & 1 deletion .github/workflows/repository-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ jobs:
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, posix
coverage: none
tools: composer:v2
tools: composer:v2, box:4.7.1
- run: composer install --no-plugins --no-scripts --no-interaction --prefer-dist --no-progress
env:
COMPOSER_HOME: ${{ runner.temp }}/standards-composer-home
Expand All @@ -36,6 +37,34 @@ jobs:
run: |
php "$STANDARDS_ROOT/bin/code-standards" normalize-composer "--directory=$STANDARDS_DIRECTORY"
- run: composer check
- name: Qualify ready PHAR distribution and native runtime
env:
COMPOSER_HOME: ${{ runner.temp }}/standards-phar-composer-home
COMPOSER_CACHE_DIR: ${{ runner.temp }}/standards-composer-cache
run: |
php scripts/phar/prepare.php "$RUNNER_TEMP/standards-runtime"
box validate "$RUNNER_TEMP/standards-runtime/box.json"
box compile --no-parallel --sort-compiled-files --config="$RUNNER_TEMP/standards-runtime/box.json"
install -m 755 "$RUNNER_TEMP/standards-runtime/dist/code-standards" "$RUNNER_TEMP/code-standards"
box verify "$RUNNER_TEMP/code-standards"
STANDARDS_PHAR="$RUNNER_TEMP/code-standards" vendor/bin/phpunit tests/Distribution/ArchiveTest.php --filter testCompiledDistributionRunsInDisposableConsumers
- name: Compare the committed executable before execution
id: parity
shell: bash
run: |
set +e
cmp "$RUNNER_TEMP/code-standards" dist/code-standards
status=$?
set -e
case "$status" in
0) echo 'stale=false' >> "$GITHUB_OUTPUT" ;;
1) echo 'stale=true' >> "$GITHUB_OUTPUT" ;;
*) exit "$status" ;;
esac
- name: Qualify the committed Composer distribution
if: steps.parity.outputs.stale == 'false'
run: |
STANDARDS_PHAR="$GITHUB_WORKSPACE/dist/code-standards" vendor/bin/phpunit tests/Distribution/ArchiveTest.php --filter testCompiledDistributionRunsInDisposableConsumers
- name: Provision isolated Twig evaluation dependencies
run: composer install --working-dir=tests/Evaluation/Twig --no-dev --no-plugins --no-scripts --no-interaction --prefer-dist --no-progress
env:
Expand All @@ -48,3 +77,16 @@ jobs:
TWIG_EVALUATION_AUTOLOAD: ${{ runner.temp }}/standards-twig-vendor/autoload.php
TWIG_EVALUATION_TEMP: ${{ runner.temp }}
- run: git diff --exit-code
- name: Retain the reviewed PHP 8.3 build
if: matrix.php == '8.3'
uses: actions/upload-artifact@v7
with:
name: code-standards-${{ steps.parity.outputs.stale == 'true' && 'update-' || '' }}${{ github.event.pull_request.head.sha || github.sha }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/code-standards
compression-level: 0
if-no-files-found: error
- name: Require the compiled refresh to pass on its own commit
if: steps.parity.outputs.stale == 'true'
run: |
echo 'The committed executable is stale. The trusted refresh workflow may update this same-repository PR; CI must pass again on that commit.' >&2
exit 1
58 changes: 58 additions & 0 deletions .github/workflows/repository-phar-refresh.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: 'Repository: Refresh compiled executable'
on:
workflow_run:
workflows: ['Repository: Quality']
types: [completed]
permissions:
contents: read
actions: read
concurrency:
group: phar-refresh-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: false
jobs:
refresh:
if: >-
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.head_repository.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 5
environment: release-channels
steps:
- name: Download the qualified update, if one was produced
id: artifact
continue-on-error: true
uses: actions/download-artifact@v8.0.2
with:
name: code-standards-update-${{ github.event.workflow_run.head_sha }}-${{ github.event.workflow_run.run_attempt }}
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}
path: ${{ runner.temp }}/phar-update
- if: steps.artifact.outcome == 'success'
id: writer
uses: actions/create-github-app-token@v3.3.0
with:
client-id: 'Iv23liHqRng02H747IYa'
private-key: ${{ secrets.RELEASE_CHANNEL_APP_PRIVATE_KEY }}
owner: php-fast-forward
repositories: code-standards
permission-contents: write
- if: steps.artifact.outcome == 'success'
uses: actions/checkout@v7
with:
ref: ${{ github.event.workflow_run.head_sha }}
token: ${{ steps.writer.outputs.token }}
- if: steps.artifact.outcome == 'success'
run: |
test "$(git log -1 --format=%s)" != 'build: refresh compiled executable'
test -f dist/code-standards && test ! -L dist && test ! -L dist/code-standards
test -f "$RUNNER_TEMP/phar-update/code-standards" && test ! -L "$RUNNER_TEMP/phar-update/code-standards"
install -m 755 "$RUNNER_TEMP/phar-update/code-standards" dist/code-standards
- if: steps.artifact.outcome == 'success'
uses: stefanzweifel/git-auto-commit-action@v7.2.1
with:
branch: ${{ github.event.workflow_run.head_branch }}
file_pattern: dist/code-standards
commit_message: 'build: refresh compiled executable'
skip_checkout: true
skip_fetch: true
42 changes: 22 additions & 20 deletions .github/workflows/repository-release-channels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,29 @@ jobs:
- name: Select the newest stable release for its major
id: release
env:
GH_TOKEN: ${{ github.token }}
FF_RELEASE_TAG: ${{ github.event.release.tag_name }}
uses: actions/github-script@v9
with:
script: |
const tag = process.env.FF_RELEASE_TAG;
const version = name => {
const match = /^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/.exec(name);
return match?.[0] === name ? match.slice(1).map(BigInt) : null;
};
const selected = version(tag);
if (!selected) throw new Error('The release version cannot be compared.');
const tags = await github.paginate(github.rest.repos.listTags, { ...context.repo, per_page: 100 });
const compare = (left, right) => {
for (let index = 0; index < 3; ++index) {
if (left[index] !== right[index]) return left[index] > right[index] ? 1 : -1;
run: |
gh api --paginate "repos/$GITHUB_REPOSITORY/tags?per_page=100" --jq '.[].name' > "$RUNNER_TEMP/release-tags"
php <<'PHP'
<?php
$tag = getenv('FF_RELEASE_TAG');
$pattern = '/^v(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)$/D';
if (!preg_match($pattern, $tag)) {
throw new RuntimeException('The release version cannot be compared.');
}
$major = explode('.', $tag)[0];
$promote = $latest = true;
foreach (file(getenv('RUNNER_TEMP') . '/release-tags', FILE_IGNORE_NEW_LINES) as $other) {
if (preg_match($pattern, $other) && version_compare(substr($other, 1), substr($tag, 1), '>')) {
$latest = false;
if (explode('.', $other)[0] === $major) {
$promote = false;
}
}
return 0;
};
const stable = tags.map(item => version(item.name)).filter(Boolean);
core.setOutput('promote', !stable.some(item => item[0] === selected[0] && compare(item, selected) > 0));
core.setOutput('latest', !stable.some(item => compare(item, selected) > 0));
}
file_put_contents(getenv('GITHUB_OUTPUT'), 'promote=' . ($promote ? 'true' : 'false') . "\nlatest=" . ($latest ? 'true' : 'false') . "\n", FILE_APPEND);
PHP
- name: Create the repository-scoped channel token
if: steps.release.outputs.promote == 'true'
id: channel-app
Expand All @@ -55,7 +57,7 @@ jobs:
skip-token-revoke: 'false'
- name: Update the released major branch
if: steps.release.outputs.promote == 'true'
uses: Actions-R-Us/actions-tagger@330ddfac760021349fef7ff62b372f2f691c20fb # v2.0.3
uses: Actions-R-Us/actions-tagger@v2.0.3
with:
token: ${{ steps.channel-app.outputs.token }}
prefer_branch_releases: 'true'
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/vendor/
/dist/*.phar
/.build/
/.phpunit.cache/

Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ reusables under `.github/workflows/code-standards*.yml`, own event workflows use
confirmed stable publications may promote their matching major channel. The
actions-tagger branch/tag integration requires stable-version selection and
approved publication/name-reservation setup; its mutation has no CAS.
GitHub channel refs are not Composer/CPX constraints.
GitHub channel refs are not Composer constraints.

## Work Guidance

Expand Down Expand Up @@ -89,7 +89,7 @@ for the exact local base/head before publication; do not claim remote CI evidenc
- [Legacy fixer comparison](docs/legacy-fixer-comparison.rst): fixed-source inventory, loaded dependencies and remaining profile decisions.
- [PHPDoc comparison](docs/phpdoc-comparison.rst): actual custom-rule registration, source contracts and remaining golden decisions.
- [Static-analysis evaluation](docs/static-analysis-evaluation.rst): candidate engines, whole-project analysis and unresolved domain ownership.
- [Architecture decision](docs/architecture.rst): library/tool dependencies, CPX/autoload limits and bootstrap without circular prerequisites.
- [Architecture decision](docs/architecture.rst): library/tool dependencies, runtime/autoload limits and bootstrap without circular prerequisites.
- [Automation](docs/automation.rst): trust, ref/bootstrap contracts and consumer adoption.
- [Instruction map](docs/instruction-map.rst): single root scope and skill ownership.
- [Consumer skill](resources/skills/fast-forward-code-standards/SKILL.md): portable consumption procedure; no automatic installation or rollout.
Expand Down
Loading
Loading