Skip to content

fix: Repair the phar build on PHP 8.4. - #46

Merged
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build
Aug 31, 2026
Merged

fix: Repair the phar build on PHP 8.4.#46
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build

Conversation

@fago

@fagofago commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #45 (merged). Refs #43.

Problem

composer build — the command needed to produce a new phar for a 0.7.3 release — is broken:

> drunomics\Phapp\ScriptHandler::installPharTools
Downloading box.phar...
$ composer build
[InvalidArgumentException]
Command "compile" is not defined.
Script php -d phar.readonly=0 vendor/bin/box compile handling the build event returned with error code 1

Not a regression from #45. It is a latent bug since 69ac445 (Dec 2024), which bumped the pinned box from box2/2.7.5/box-2.7.5.phar to box/4.6.1/box.phar. Fresh clones happened to work, which is why it went unnoticed; any checkout that predates that bump is broken.

Root cause

Two independent defects in ScriptHandler::installPharTools():

a) The tool symlink was never repointed.

if (!$fs->exists("$bin_dir/$tool")) {
$fs->symlink("$bin_dir/$filename", "$bin_dir/$tool");
}

On a pre-bump checkout vendor/bin/box already existed, pointing at the leftover box-2.7.5.phar. The new box.pharwas downloaded — different basename, so the download guard let it through — but nothing ever linked to it. So composer build kept invoking box 2.7.5, whose command is build, not compile. Hence the error.

b) The download was keyed on the file name only.

if (!$fs->exists("$bin_dir/$filename")) { … }

A new box published under the same box.phar name would never be fetched, so the next version bump would have silently kept the old binary.

Fix

The installer now reconciles vendor/bin with the currently pinned URL:

  • the installed URL is recorded in vendor/bin/.<tool>.url;
  • the phar is re-downloaded whenever that URL changes, and the phar of the previously pinned version is removed;
  • the symlink is updated unconditionally, and is now relative (box -> box.phar) so it keeps working when the project directory is mounted at another path, e.g. inside a container.

Two smaller bugs surfaced along the way:

  • $fs->dumpFile($path, $content, 0755)Filesystem::dumpFile() takes no mode argument, so the third one was silently ignored and the downloaded phar was left non-executable (-rw-rw-r--). Now set explicitly via chmod().
  • README: composer install --devcomposer install (--dev is a no-op that Composer 2 warns about and Composer 3 will reject).

Box pinned 4.6.1 → 4.7.0

Box 4.6.1 (Dec 2023) does not run on PHP 8.4 at all, so even with the symlink fixed composer build could not produce a phar there:

boxcompile on PHP 8.4deprecations emitted
4.6.1 (was pinned)fails, exit 255260
4.6.10succeeds0
4.7.0 (now pinned)succeeds0

4.7.0 still builds on PHP 8.3 too, so this does not force maintainers onto 8.4.

Verification

Verified:

  • Reproduced the reported failure exactly by restoring the pre-bump vendor/bin state (a box -> box-2.7.5.phar symlink) and running composer install && composer build[InvalidArgumentException] Command "compile" is not defined.
  • That same broken checkout now self-heals: composer install repoints box -> box.phar (4.7.0), and composer build produces phapp.phar.
  • Fresh clone path: rm -rf vendor && composer install && composer build succeeds; vendor/bin/box.phar is now correctly -rwxr-xr-x.
  • Version-bump path: with .box.url recording 4.6.1 and composer.json pinning 4.7.0, composer install re-downloads and the symlink follows.
  • Compiled on PHP 8.4 with box 4.7.0 — 0 deprecations, exit 0 — and the resulting phar runs clean on PHP 8.4 (list, status).
  • composer validate → valid (lock content-hash refreshed via composer update --lock; no package versions changed); php -l clean.

Not verified / caveats:

  • The PHP 8.4 compile was run with git-version removed from the box config, because the bare php:8.4-cli image has no git binary and my sandbox could not install one. That setting only substitutes the version placeholder and is orthogonal to the PHP version; the full config including git-version was verified on PHP 8.3. The deprecation counts above come from identical configs, so the 4.6.1-vs-4.7.0 comparison is unaffected.
  • No test suite exists in this repo, so there is no automated coverage for the installer. Verification was the manual scenarios listed above.
  • phpstan analyse src --level=0 still reports the same 2 pre-existing errors in src/ScriptHandler.php (Composer\Script\Event / Composer\Util\StreamContextFactory unknown — composer/composer is not a dependency). Count unchanged by this PR.
  • Upgrading checkouts keep a stale vendor/bin/box-2.7.5.phar, since there is no record of it to clean up. It is no longer referenced and is harmless; rm -rf vendor clears it.

Why this matters for #43

#43 is only actually fixed for consumers once a 0.7.3 phar is released, and that phar cannot be built on PHP 8.4 without this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd

"composer build" failed with 'Command "compile" is not defined' on checkouts
that predate the box 2.7.5 -> 4.6.1 bump, and box 4.6.1 does not run on PHP
8.4 at all.
- ScriptHandler::installPharTools only created the tool symlink when it was
missing, so vendor/bin/box kept pointing at the box 2.7.5 phar of the
previously pinned URL. Update the symlink unconditionally and keep it
relative, so it survives the project being mounted at another path.
- The phar was only downloaded when its file name was absent, so a new version
published under the same name was never picked up. Record the installed URL
and re-download whenever the pinned URL changes, removing the phar of the
previously pinned version.
- dumpFile() ignored the mode argument, leaving the downloaded phar
non-executable. Set the mode via chmod().
- Pin box 4.7.0: 4.6.1 aborts on PHP 8.4 after emitting 260 implicit-nullable
deprecations.
- README: drop the deprecated "composer install --dev".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd
@fago
fago merged commit 8f402c6 into masterAug 31, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fago
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix: Repair the phar build on PHP 8.4. by fago · Pull Request #46 · drunomics/phapp-cli · GitHub
Skip to content

fix: Repair the phar build on PHP 8.4. - #46

Merged
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build
Aug 31, 2026
Merged

fix: Repair the phar build on PHP 8.4.#46
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build

Conversation

@fago

@fagofago commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #45 (merged). Refs #43.

Problem

composer build — the command needed to produce a new phar for a 0.7.3 release — is broken:

> drunomics\Phapp\ScriptHandler::installPharTools
Downloading box.phar...
$ composer build
[InvalidArgumentException]
Command "compile" is not defined.
Script php -d phar.readonly=0 vendor/bin/box compile handling the build event returned with error code 1

Not a regression from #45. It is a latent bug since 69ac445 (Dec 2024), which bumped the pinned box from box2/2.7.5/box-2.7.5.phar to box/4.6.1/box.phar. Fresh clones happened to work, which is why it went unnoticed; any checkout that predates that bump is broken.

Root cause

Two independent defects in ScriptHandler::installPharTools():

a) The tool symlink was never repointed.

if (!$fs->exists("$bin_dir/$tool")) {
$fs->symlink("$bin_dir/$filename", "$bin_dir/$tool");
}

On a pre-bump checkout vendor/bin/box already existed, pointing at the leftover box-2.7.5.phar. The new box.pharwas downloaded — different basename, so the download guard let it through — but nothing ever linked to it. So composer build kept invoking box 2.7.5, whose command is build, not compile. Hence the error.

b) The download was keyed on the file name only.

if (!$fs->exists("$bin_dir/$filename")) { … }

A new box published under the same box.phar name would never be fetched, so the next version bump would have silently kept the old binary.

Fix

The installer now reconciles vendor/bin with the currently pinned URL:

  • the installed URL is recorded in vendor/bin/.<tool>.url;
  • the phar is re-downloaded whenever that URL changes, and the phar of the previously pinned version is removed;
  • the symlink is updated unconditionally, and is now relative (box -> box.phar) so it keeps working when the project directory is mounted at another path, e.g. inside a container.

Two smaller bugs surfaced along the way:

  • $fs->dumpFile($path, $content, 0755)Filesystem::dumpFile() takes no mode argument, so the third one was silently ignored and the downloaded phar was left non-executable (-rw-rw-r--). Now set explicitly via chmod().
  • README: composer install --devcomposer install (--dev is a no-op that Composer 2 warns about and Composer 3 will reject).

Box pinned 4.6.1 → 4.7.0

Box 4.6.1 (Dec 2023) does not run on PHP 8.4 at all, so even with the symlink fixed composer build could not produce a phar there:

boxcompile on PHP 8.4deprecations emitted
4.6.1 (was pinned)fails, exit 255260
4.6.10succeeds0
4.7.0 (now pinned)succeeds0

4.7.0 still builds on PHP 8.3 too, so this does not force maintainers onto 8.4.

Verification

Verified:

  • Reproduced the reported failure exactly by restoring the pre-bump vendor/bin state (a box -> box-2.7.5.phar symlink) and running composer install && composer build[InvalidArgumentException] Command "compile" is not defined.
  • That same broken checkout now self-heals: composer install repoints box -> box.phar (4.7.0), and composer build produces phapp.phar.
  • Fresh clone path: rm -rf vendor && composer install && composer build succeeds; vendor/bin/box.phar is now correctly -rwxr-xr-x.
  • Version-bump path: with .box.url recording 4.6.1 and composer.json pinning 4.7.0, composer install re-downloads and the symlink follows.
  • Compiled on PHP 8.4 with box 4.7.0 — 0 deprecations, exit 0 — and the resulting phar runs clean on PHP 8.4 (list, status).
  • composer validate → valid (lock content-hash refreshed via composer update --lock; no package versions changed); php -l clean.

Not verified / caveats:

  • The PHP 8.4 compile was run with git-version removed from the box config, because the bare php:8.4-cli image has no git binary and my sandbox could not install one. That setting only substitutes the version placeholder and is orthogonal to the PHP version; the full config including git-version was verified on PHP 8.3. The deprecation counts above come from identical configs, so the 4.6.1-vs-4.7.0 comparison is unaffected.
  • No test suite exists in this repo, so there is no automated coverage for the installer. Verification was the manual scenarios listed above.
  • phpstan analyse src --level=0 still reports the same 2 pre-existing errors in src/ScriptHandler.php (Composer\Script\Event / Composer\Util\StreamContextFactory unknown — composer/composer is not a dependency). Count unchanged by this PR.
  • Upgrading checkouts keep a stale vendor/bin/box-2.7.5.phar, since there is no record of it to clean up. It is no longer referenced and is harmless; rm -rf vendor clears it.

Why this matters for #43

#43 is only actually fixed for consumers once a 0.7.3 phar is released, and that phar cannot be built on PHP 8.4 without this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd

"composer build" failed with 'Command "compile" is not defined' on checkouts
that predate the box 2.7.5 -> 4.6.1 bump, and box 4.6.1 does not run on PHP
8.4 at all.
- ScriptHandler::installPharTools only created the tool symlink when it was
missing, so vendor/bin/box kept pointing at the box 2.7.5 phar of the
previously pinned URL. Update the symlink unconditionally and keep it
relative, so it survives the project being mounted at another path.
- The phar was only downloaded when its file name was absent, so a new version
published under the same name was never picked up. Record the installed URL
and re-download whenever the pinned URL changes, removing the phar of the
previously pinned version.
- dumpFile() ignored the mode argument, leaving the downloaded phar
non-executable. Set the mode via chmod().
- Pin box 4.7.0: 4.6.1 aborts on PHP 8.4 after emitting 260 implicit-nullable
deprecations.
- README: drop the deprecated "composer install --dev".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd
@fago
fago merged commit 8f402c6 into masterAug 31, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fago
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix: Repair the phar build on PHP 8.4. by fago · Pull Request #46 · drunomics/phapp-cli · GitHub
Skip to content

fix: Repair the phar build on PHP 8.4. - #46

Merged
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build
Aug 31, 2026
Merged

fix: Repair the phar build on PHP 8.4.#46
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build

Conversation

@fago

@fagofago commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #45 (merged). Refs #43.

Problem

composer build — the command needed to produce a new phar for a 0.7.3 release — is broken:

> drunomics\Phapp\ScriptHandler::installPharTools
Downloading box.phar...
$ composer build
[InvalidArgumentException]
Command "compile" is not defined.
Script php -d phar.readonly=0 vendor/bin/box compile handling the build event returned with error code 1

Not a regression from #45. It is a latent bug since 69ac445 (Dec 2024), which bumped the pinned box from box2/2.7.5/box-2.7.5.phar to box/4.6.1/box.phar. Fresh clones happened to work, which is why it went unnoticed; any checkout that predates that bump is broken.

Root cause

Two independent defects in ScriptHandler::installPharTools():

a) The tool symlink was never repointed.

if (!$fs->exists("$bin_dir/$tool")) {
$fs->symlink("$bin_dir/$filename", "$bin_dir/$tool");
}

On a pre-bump checkout vendor/bin/box already existed, pointing at the leftover box-2.7.5.phar. The new box.pharwas downloaded — different basename, so the download guard let it through — but nothing ever linked to it. So composer build kept invoking box 2.7.5, whose command is build, not compile. Hence the error.

b) The download was keyed on the file name only.

if (!$fs->exists("$bin_dir/$filename")) { … }

A new box published under the same box.phar name would never be fetched, so the next version bump would have silently kept the old binary.

Fix

The installer now reconciles vendor/bin with the currently pinned URL:

  • the installed URL is recorded in vendor/bin/.<tool>.url;
  • the phar is re-downloaded whenever that URL changes, and the phar of the previously pinned version is removed;
  • the symlink is updated unconditionally, and is now relative (box -> box.phar) so it keeps working when the project directory is mounted at another path, e.g. inside a container.

Two smaller bugs surfaced along the way:

  • $fs->dumpFile($path, $content, 0755)Filesystem::dumpFile() takes no mode argument, so the third one was silently ignored and the downloaded phar was left non-executable (-rw-rw-r--). Now set explicitly via chmod().
  • README: composer install --devcomposer install (--dev is a no-op that Composer 2 warns about and Composer 3 will reject).

Box pinned 4.6.1 → 4.7.0

Box 4.6.1 (Dec 2023) does not run on PHP 8.4 at all, so even with the symlink fixed composer build could not produce a phar there:

boxcompile on PHP 8.4deprecations emitted
4.6.1 (was pinned)fails, exit 255260
4.6.10succeeds0
4.7.0 (now pinned)succeeds0

4.7.0 still builds on PHP 8.3 too, so this does not force maintainers onto 8.4.

Verification

Verified:

  • Reproduced the reported failure exactly by restoring the pre-bump vendor/bin state (a box -> box-2.7.5.phar symlink) and running composer install && composer build[InvalidArgumentException] Command "compile" is not defined.
  • That same broken checkout now self-heals: composer install repoints box -> box.phar (4.7.0), and composer build produces phapp.phar.
  • Fresh clone path: rm -rf vendor && composer install && composer build succeeds; vendor/bin/box.phar is now correctly -rwxr-xr-x.
  • Version-bump path: with .box.url recording 4.6.1 and composer.json pinning 4.7.0, composer install re-downloads and the symlink follows.
  • Compiled on PHP 8.4 with box 4.7.0 — 0 deprecations, exit 0 — and the resulting phar runs clean on PHP 8.4 (list, status).
  • composer validate → valid (lock content-hash refreshed via composer update --lock; no package versions changed); php -l clean.

Not verified / caveats:

  • The PHP 8.4 compile was run with git-version removed from the box config, because the bare php:8.4-cli image has no git binary and my sandbox could not install one. That setting only substitutes the version placeholder and is orthogonal to the PHP version; the full config including git-version was verified on PHP 8.3. The deprecation counts above come from identical configs, so the 4.6.1-vs-4.7.0 comparison is unaffected.
  • No test suite exists in this repo, so there is no automated coverage for the installer. Verification was the manual scenarios listed above.
  • phpstan analyse src --level=0 still reports the same 2 pre-existing errors in src/ScriptHandler.php (Composer\Script\Event / Composer\Util\StreamContextFactory unknown — composer/composer is not a dependency). Count unchanged by this PR.
  • Upgrading checkouts keep a stale vendor/bin/box-2.7.5.phar, since there is no record of it to clean up. It is no longer referenced and is harmless; rm -rf vendor clears it.

Why this matters for #43

#43 is only actually fixed for consumers once a 0.7.3 phar is released, and that phar cannot be built on PHP 8.4 without this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd

"composer build" failed with 'Command "compile" is not defined' on checkouts
that predate the box 2.7.5 -> 4.6.1 bump, and box 4.6.1 does not run on PHP
8.4 at all.
- ScriptHandler::installPharTools only created the tool symlink when it was
missing, so vendor/bin/box kept pointing at the box 2.7.5 phar of the
previously pinned URL. Update the symlink unconditionally and keep it
relative, so it survives the project being mounted at another path.
- The phar was only downloaded when its file name was absent, so a new version
published under the same name was never picked up. Record the installed URL
and re-download whenever the pinned URL changes, removing the phar of the
previously pinned version.
- dumpFile() ignored the mode argument, leaving the downloaded phar
non-executable. Set the mode via chmod().
- Pin box 4.7.0: 4.6.1 aborts on PHP 8.4 after emitting 260 implicit-nullable
deprecations.
- README: drop the deprecated "composer install --dev".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd
@fago
fago merged commit 8f402c6 into masterAug 31, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fago
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix: Repair the phar build on PHP 8.4. by fago · Pull Request #46 · drunomics/phapp-cli · GitHub
Skip to content

fix: Repair the phar build on PHP 8.4. - #46

Merged
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build
Aug 31, 2026
Merged

fix: Repair the phar build on PHP 8.4.#46
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build

Conversation

@fago

@fagofago commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #45 (merged). Refs #43.

Problem

composer build — the command needed to produce a new phar for a 0.7.3 release — is broken:

> drunomics\Phapp\ScriptHandler::installPharTools
Downloading box.phar...
$ composer build
[InvalidArgumentException]
Command "compile" is not defined.
Script php -d phar.readonly=0 vendor/bin/box compile handling the build event returned with error code 1

Not a regression from #45. It is a latent bug since 69ac445 (Dec 2024), which bumped the pinned box from box2/2.7.5/box-2.7.5.phar to box/4.6.1/box.phar. Fresh clones happened to work, which is why it went unnoticed; any checkout that predates that bump is broken.

Root cause

Two independent defects in ScriptHandler::installPharTools():

a) The tool symlink was never repointed.

if (!$fs->exists("$bin_dir/$tool")) {
$fs->symlink("$bin_dir/$filename", "$bin_dir/$tool");
}

On a pre-bump checkout vendor/bin/box already existed, pointing at the leftover box-2.7.5.phar. The new box.pharwas downloaded — different basename, so the download guard let it through — but nothing ever linked to it. So composer build kept invoking box 2.7.5, whose command is build, not compile. Hence the error.

b) The download was keyed on the file name only.

if (!$fs->exists("$bin_dir/$filename")) { … }

A new box published under the same box.phar name would never be fetched, so the next version bump would have silently kept the old binary.

Fix

The installer now reconciles vendor/bin with the currently pinned URL:

  • the installed URL is recorded in vendor/bin/.<tool>.url;
  • the phar is re-downloaded whenever that URL changes, and the phar of the previously pinned version is removed;
  • the symlink is updated unconditionally, and is now relative (box -> box.phar) so it keeps working when the project directory is mounted at another path, e.g. inside a container.

Two smaller bugs surfaced along the way:

  • $fs->dumpFile($path, $content, 0755)Filesystem::dumpFile() takes no mode argument, so the third one was silently ignored and the downloaded phar was left non-executable (-rw-rw-r--). Now set explicitly via chmod().
  • README: composer install --devcomposer install (--dev is a no-op that Composer 2 warns about and Composer 3 will reject).

Box pinned 4.6.1 → 4.7.0

Box 4.6.1 (Dec 2023) does not run on PHP 8.4 at all, so even with the symlink fixed composer build could not produce a phar there:

boxcompile on PHP 8.4deprecations emitted
4.6.1 (was pinned)fails, exit 255260
4.6.10succeeds0
4.7.0 (now pinned)succeeds0

4.7.0 still builds on PHP 8.3 too, so this does not force maintainers onto 8.4.

Verification

Verified:

  • Reproduced the reported failure exactly by restoring the pre-bump vendor/bin state (a box -> box-2.7.5.phar symlink) and running composer install && composer build[InvalidArgumentException] Command "compile" is not defined.
  • That same broken checkout now self-heals: composer install repoints box -> box.phar (4.7.0), and composer build produces phapp.phar.
  • Fresh clone path: rm -rf vendor && composer install && composer build succeeds; vendor/bin/box.phar is now correctly -rwxr-xr-x.
  • Version-bump path: with .box.url recording 4.6.1 and composer.json pinning 4.7.0, composer install re-downloads and the symlink follows.
  • Compiled on PHP 8.4 with box 4.7.0 — 0 deprecations, exit 0 — and the resulting phar runs clean on PHP 8.4 (list, status).
  • composer validate → valid (lock content-hash refreshed via composer update --lock; no package versions changed); php -l clean.

Not verified / caveats:

  • The PHP 8.4 compile was run with git-version removed from the box config, because the bare php:8.4-cli image has no git binary and my sandbox could not install one. That setting only substitutes the version placeholder and is orthogonal to the PHP version; the full config including git-version was verified on PHP 8.3. The deprecation counts above come from identical configs, so the 4.6.1-vs-4.7.0 comparison is unaffected.
  • No test suite exists in this repo, so there is no automated coverage for the installer. Verification was the manual scenarios listed above.
  • phpstan analyse src --level=0 still reports the same 2 pre-existing errors in src/ScriptHandler.php (Composer\Script\Event / Composer\Util\StreamContextFactory unknown — composer/composer is not a dependency). Count unchanged by this PR.
  • Upgrading checkouts keep a stale vendor/bin/box-2.7.5.phar, since there is no record of it to clean up. It is no longer referenced and is harmless; rm -rf vendor clears it.

Why this matters for #43

#43 is only actually fixed for consumers once a 0.7.3 phar is released, and that phar cannot be built on PHP 8.4 without this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd

"composer build" failed with 'Command "compile" is not defined' on checkouts
that predate the box 2.7.5 -> 4.6.1 bump, and box 4.6.1 does not run on PHP
8.4 at all.
- ScriptHandler::installPharTools only created the tool symlink when it was
missing, so vendor/bin/box kept pointing at the box 2.7.5 phar of the
previously pinned URL. Update the symlink unconditionally and keep it
relative, so it survives the project being mounted at another path.
- The phar was only downloaded when its file name was absent, so a new version
published under the same name was never picked up. Record the installed URL
and re-download whenever the pinned URL changes, removing the phar of the
previously pinned version.
- dumpFile() ignored the mode argument, leaving the downloaded phar
non-executable. Set the mode via chmod().
- Pin box 4.7.0: 4.6.1 aborts on PHP 8.4 after emitting 260 implicit-nullable
deprecations.
- README: drop the deprecated "composer install --dev".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd
@fago
fago merged commit 8f402c6 into masterAug 31, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fago
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix: Repair the phar build on PHP 8.4. by fago · Pull Request #46 · drunomics/phapp-cli · GitHub
Skip to content

fix: Repair the phar build on PHP 8.4. - #46

Merged
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build
Aug 31, 2026
Merged

fix: Repair the phar build on PHP 8.4.#46
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build

Conversation

@fago

@fagofago commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #45 (merged). Refs #43.

Problem

composer build — the command needed to produce a new phar for a 0.7.3 release — is broken:

> drunomics\Phapp\ScriptHandler::installPharTools
Downloading box.phar...
$ composer build
[InvalidArgumentException]
Command "compile" is not defined.
Script php -d phar.readonly=0 vendor/bin/box compile handling the build event returned with error code 1

Not a regression from #45. It is a latent bug since 69ac445 (Dec 2024), which bumped the pinned box from box2/2.7.5/box-2.7.5.phar to box/4.6.1/box.phar. Fresh clones happened to work, which is why it went unnoticed; any checkout that predates that bump is broken.

Root cause

Two independent defects in ScriptHandler::installPharTools():

a) The tool symlink was never repointed.

if (!$fs->exists("$bin_dir/$tool")) {
$fs->symlink("$bin_dir/$filename", "$bin_dir/$tool");
}

On a pre-bump checkout vendor/bin/box already existed, pointing at the leftover box-2.7.5.phar. The new box.pharwas downloaded — different basename, so the download guard let it through — but nothing ever linked to it. So composer build kept invoking box 2.7.5, whose command is build, not compile. Hence the error.

b) The download was keyed on the file name only.

if (!$fs->exists("$bin_dir/$filename")) { … }

A new box published under the same box.phar name would never be fetched, so the next version bump would have silently kept the old binary.

Fix

The installer now reconciles vendor/bin with the currently pinned URL:

  • the installed URL is recorded in vendor/bin/.<tool>.url;
  • the phar is re-downloaded whenever that URL changes, and the phar of the previously pinned version is removed;
  • the symlink is updated unconditionally, and is now relative (box -> box.phar) so it keeps working when the project directory is mounted at another path, e.g. inside a container.

Two smaller bugs surfaced along the way:

  • $fs->dumpFile($path, $content, 0755)Filesystem::dumpFile() takes no mode argument, so the third one was silently ignored and the downloaded phar was left non-executable (-rw-rw-r--). Now set explicitly via chmod().
  • README: composer install --devcomposer install (--dev is a no-op that Composer 2 warns about and Composer 3 will reject).

Box pinned 4.6.1 → 4.7.0

Box 4.6.1 (Dec 2023) does not run on PHP 8.4 at all, so even with the symlink fixed composer build could not produce a phar there:

boxcompile on PHP 8.4deprecations emitted
4.6.1 (was pinned)fails, exit 255260
4.6.10succeeds0
4.7.0 (now pinned)succeeds0

4.7.0 still builds on PHP 8.3 too, so this does not force maintainers onto 8.4.

Verification

Verified:

  • Reproduced the reported failure exactly by restoring the pre-bump vendor/bin state (a box -> box-2.7.5.phar symlink) and running composer install && composer build[InvalidArgumentException] Command "compile" is not defined.
  • That same broken checkout now self-heals: composer install repoints box -> box.phar (4.7.0), and composer build produces phapp.phar.
  • Fresh clone path: rm -rf vendor && composer install && composer build succeeds; vendor/bin/box.phar is now correctly -rwxr-xr-x.
  • Version-bump path: with .box.url recording 4.6.1 and composer.json pinning 4.7.0, composer install re-downloads and the symlink follows.
  • Compiled on PHP 8.4 with box 4.7.0 — 0 deprecations, exit 0 — and the resulting phar runs clean on PHP 8.4 (list, status).
  • composer validate → valid (lock content-hash refreshed via composer update --lock; no package versions changed); php -l clean.

Not verified / caveats:

  • The PHP 8.4 compile was run with git-version removed from the box config, because the bare php:8.4-cli image has no git binary and my sandbox could not install one. That setting only substitutes the version placeholder and is orthogonal to the PHP version; the full config including git-version was verified on PHP 8.3. The deprecation counts above come from identical configs, so the 4.6.1-vs-4.7.0 comparison is unaffected.
  • No test suite exists in this repo, so there is no automated coverage for the installer. Verification was the manual scenarios listed above.
  • phpstan analyse src --level=0 still reports the same 2 pre-existing errors in src/ScriptHandler.php (Composer\Script\Event / Composer\Util\StreamContextFactory unknown — composer/composer is not a dependency). Count unchanged by this PR.
  • Upgrading checkouts keep a stale vendor/bin/box-2.7.5.phar, since there is no record of it to clean up. It is no longer referenced and is harmless; rm -rf vendor clears it.

Why this matters for #43

#43 is only actually fixed for consumers once a 0.7.3 phar is released, and that phar cannot be built on PHP 8.4 without this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd

"composer build" failed with 'Command "compile" is not defined' on checkouts
that predate the box 2.7.5 -> 4.6.1 bump, and box 4.6.1 does not run on PHP
8.4 at all.
- ScriptHandler::installPharTools only created the tool symlink when it was
missing, so vendor/bin/box kept pointing at the box 2.7.5 phar of the
previously pinned URL. Update the symlink unconditionally and keep it
relative, so it survives the project being mounted at another path.
- The phar was only downloaded when its file name was absent, so a new version
published under the same name was never picked up. Record the installed URL
and re-download whenever the pinned URL changes, removing the phar of the
previously pinned version.
- dumpFile() ignored the mode argument, leaving the downloaded phar
non-executable. Set the mode via chmod().
- Pin box 4.7.0: 4.6.1 aborts on PHP 8.4 after emitting 260 implicit-nullable
deprecations.
- README: drop the deprecated "composer install --dev".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd
@fago
fago merged commit 8f402c6 into masterAug 31, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fago
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix: Repair the phar build on PHP 8.4. by fago · Pull Request #46 · drunomics/phapp-cli · GitHub
Skip to content

fix: Repair the phar build on PHP 8.4. - #46

Merged
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build
Aug 31, 2026
Merged

fix: Repair the phar build on PHP 8.4.#46
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build

Conversation

@fago

@fagofago commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #45 (merged). Refs #43.

Problem

composer build — the command needed to produce a new phar for a 0.7.3 release — is broken:

> drunomics\Phapp\ScriptHandler::installPharTools
Downloading box.phar...
$ composer build
[InvalidArgumentException]
Command "compile" is not defined.
Script php -d phar.readonly=0 vendor/bin/box compile handling the build event returned with error code 1

Not a regression from #45. It is a latent bug since 69ac445 (Dec 2024), which bumped the pinned box from box2/2.7.5/box-2.7.5.phar to box/4.6.1/box.phar. Fresh clones happened to work, which is why it went unnoticed; any checkout that predates that bump is broken.

Root cause

Two independent defects in ScriptHandler::installPharTools():

a) The tool symlink was never repointed.

if (!$fs->exists("$bin_dir/$tool")) {
$fs->symlink("$bin_dir/$filename", "$bin_dir/$tool");
}

On a pre-bump checkout vendor/bin/box already existed, pointing at the leftover box-2.7.5.phar. The new box.pharwas downloaded — different basename, so the download guard let it through — but nothing ever linked to it. So composer build kept invoking box 2.7.5, whose command is build, not compile. Hence the error.

b) The download was keyed on the file name only.

if (!$fs->exists("$bin_dir/$filename")) { … }

A new box published under the same box.phar name would never be fetched, so the next version bump would have silently kept the old binary.

Fix

The installer now reconciles vendor/bin with the currently pinned URL:

  • the installed URL is recorded in vendor/bin/.<tool>.url;
  • the phar is re-downloaded whenever that URL changes, and the phar of the previously pinned version is removed;
  • the symlink is updated unconditionally, and is now relative (box -> box.phar) so it keeps working when the project directory is mounted at another path, e.g. inside a container.

Two smaller bugs surfaced along the way:

  • $fs->dumpFile($path, $content, 0755)Filesystem::dumpFile() takes no mode argument, so the third one was silently ignored and the downloaded phar was left non-executable (-rw-rw-r--). Now set explicitly via chmod().
  • README: composer install --devcomposer install (--dev is a no-op that Composer 2 warns about and Composer 3 will reject).

Box pinned 4.6.1 → 4.7.0

Box 4.6.1 (Dec 2023) does not run on PHP 8.4 at all, so even with the symlink fixed composer build could not produce a phar there:

boxcompile on PHP 8.4deprecations emitted
4.6.1 (was pinned)fails, exit 255260
4.6.10succeeds0
4.7.0 (now pinned)succeeds0

4.7.0 still builds on PHP 8.3 too, so this does not force maintainers onto 8.4.

Verification

Verified:

  • Reproduced the reported failure exactly by restoring the pre-bump vendor/bin state (a box -> box-2.7.5.phar symlink) and running composer install && composer build[InvalidArgumentException] Command "compile" is not defined.
  • That same broken checkout now self-heals: composer install repoints box -> box.phar (4.7.0), and composer build produces phapp.phar.
  • Fresh clone path: rm -rf vendor && composer install && composer build succeeds; vendor/bin/box.phar is now correctly -rwxr-xr-x.
  • Version-bump path: with .box.url recording 4.6.1 and composer.json pinning 4.7.0, composer install re-downloads and the symlink follows.
  • Compiled on PHP 8.4 with box 4.7.0 — 0 deprecations, exit 0 — and the resulting phar runs clean on PHP 8.4 (list, status).
  • composer validate → valid (lock content-hash refreshed via composer update --lock; no package versions changed); php -l clean.

Not verified / caveats:

  • The PHP 8.4 compile was run with git-version removed from the box config, because the bare php:8.4-cli image has no git binary and my sandbox could not install one. That setting only substitutes the version placeholder and is orthogonal to the PHP version; the full config including git-version was verified on PHP 8.3. The deprecation counts above come from identical configs, so the 4.6.1-vs-4.7.0 comparison is unaffected.
  • No test suite exists in this repo, so there is no automated coverage for the installer. Verification was the manual scenarios listed above.
  • phpstan analyse src --level=0 still reports the same 2 pre-existing errors in src/ScriptHandler.php (Composer\Script\Event / Composer\Util\StreamContextFactory unknown — composer/composer is not a dependency). Count unchanged by this PR.
  • Upgrading checkouts keep a stale vendor/bin/box-2.7.5.phar, since there is no record of it to clean up. It is no longer referenced and is harmless; rm -rf vendor clears it.

Why this matters for #43

#43 is only actually fixed for consumers once a 0.7.3 phar is released, and that phar cannot be built on PHP 8.4 without this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd

"composer build" failed with 'Command "compile" is not defined' on checkouts
that predate the box 2.7.5 -> 4.6.1 bump, and box 4.6.1 does not run on PHP
8.4 at all.
- ScriptHandler::installPharTools only created the tool symlink when it was
missing, so vendor/bin/box kept pointing at the box 2.7.5 phar of the
previously pinned URL. Update the symlink unconditionally and keep it
relative, so it survives the project being mounted at another path.
- The phar was only downloaded when its file name was absent, so a new version
published under the same name was never picked up. Record the installed URL
and re-download whenever the pinned URL changes, removing the phar of the
previously pinned version.
- dumpFile() ignored the mode argument, leaving the downloaded phar
non-executable. Set the mode via chmod().
- Pin box 4.7.0: 4.6.1 aborts on PHP 8.4 after emitting 260 implicit-nullable
deprecations.
- README: drop the deprecated "composer install --dev".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd
@fago
fago merged commit 8f402c6 into masterAug 31, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fago
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix: Repair the phar build on PHP 8.4. by fago · Pull Request #46 · drunomics/phapp-cli · GitHub
Skip to content

fix: Repair the phar build on PHP 8.4. - #46

Merged
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build
Aug 31, 2026
Merged

fix: Repair the phar build on PHP 8.4.#46
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build

Conversation

@fago

@fagofago commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #45 (merged). Refs #43.

Problem

composer build — the command needed to produce a new phar for a 0.7.3 release — is broken:

> drunomics\Phapp\ScriptHandler::installPharTools
Downloading box.phar...
$ composer build
[InvalidArgumentException]
Command "compile" is not defined.
Script php -d phar.readonly=0 vendor/bin/box compile handling the build event returned with error code 1

Not a regression from #45. It is a latent bug since 69ac445 (Dec 2024), which bumped the pinned box from box2/2.7.5/box-2.7.5.phar to box/4.6.1/box.phar. Fresh clones happened to work, which is why it went unnoticed; any checkout that predates that bump is broken.

Root cause

Two independent defects in ScriptHandler::installPharTools():

a) The tool symlink was never repointed.

if (!$fs->exists("$bin_dir/$tool")) {
$fs->symlink("$bin_dir/$filename", "$bin_dir/$tool");
}

On a pre-bump checkout vendor/bin/box already existed, pointing at the leftover box-2.7.5.phar. The new box.pharwas downloaded — different basename, so the download guard let it through — but nothing ever linked to it. So composer build kept invoking box 2.7.5, whose command is build, not compile. Hence the error.

b) The download was keyed on the file name only.

if (!$fs->exists("$bin_dir/$filename")) { … }

A new box published under the same box.phar name would never be fetched, so the next version bump would have silently kept the old binary.

Fix

The installer now reconciles vendor/bin with the currently pinned URL:

  • the installed URL is recorded in vendor/bin/.<tool>.url;
  • the phar is re-downloaded whenever that URL changes, and the phar of the previously pinned version is removed;
  • the symlink is updated unconditionally, and is now relative (box -> box.phar) so it keeps working when the project directory is mounted at another path, e.g. inside a container.

Two smaller bugs surfaced along the way:

  • $fs->dumpFile($path, $content, 0755)Filesystem::dumpFile() takes no mode argument, so the third one was silently ignored and the downloaded phar was left non-executable (-rw-rw-r--). Now set explicitly via chmod().
  • README: composer install --devcomposer install (--dev is a no-op that Composer 2 warns about and Composer 3 will reject).

Box pinned 4.6.1 → 4.7.0

Box 4.6.1 (Dec 2023) does not run on PHP 8.4 at all, so even with the symlink fixed composer build could not produce a phar there:

boxcompile on PHP 8.4deprecations emitted
4.6.1 (was pinned)fails, exit 255260
4.6.10succeeds0
4.7.0 (now pinned)succeeds0

4.7.0 still builds on PHP 8.3 too, so this does not force maintainers onto 8.4.

Verification

Verified:

  • Reproduced the reported failure exactly by restoring the pre-bump vendor/bin state (a box -> box-2.7.5.phar symlink) and running composer install && composer build[InvalidArgumentException] Command "compile" is not defined.
  • That same broken checkout now self-heals: composer install repoints box -> box.phar (4.7.0), and composer build produces phapp.phar.
  • Fresh clone path: rm -rf vendor && composer install && composer build succeeds; vendor/bin/box.phar is now correctly -rwxr-xr-x.
  • Version-bump path: with .box.url recording 4.6.1 and composer.json pinning 4.7.0, composer install re-downloads and the symlink follows.
  • Compiled on PHP 8.4 with box 4.7.0 — 0 deprecations, exit 0 — and the resulting phar runs clean on PHP 8.4 (list, status).
  • composer validate → valid (lock content-hash refreshed via composer update --lock; no package versions changed); php -l clean.

Not verified / caveats:

  • The PHP 8.4 compile was run with git-version removed from the box config, because the bare php:8.4-cli image has no git binary and my sandbox could not install one. That setting only substitutes the version placeholder and is orthogonal to the PHP version; the full config including git-version was verified on PHP 8.3. The deprecation counts above come from identical configs, so the 4.6.1-vs-4.7.0 comparison is unaffected.
  • No test suite exists in this repo, so there is no automated coverage for the installer. Verification was the manual scenarios listed above.
  • phpstan analyse src --level=0 still reports the same 2 pre-existing errors in src/ScriptHandler.php (Composer\Script\Event / Composer\Util\StreamContextFactory unknown — composer/composer is not a dependency). Count unchanged by this PR.
  • Upgrading checkouts keep a stale vendor/bin/box-2.7.5.phar, since there is no record of it to clean up. It is no longer referenced and is harmless; rm -rf vendor clears it.

Why this matters for #43

#43 is only actually fixed for consumers once a 0.7.3 phar is released, and that phar cannot be built on PHP 8.4 without this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd

"composer build" failed with 'Command "compile" is not defined' on checkouts
that predate the box 2.7.5 -> 4.6.1 bump, and box 4.6.1 does not run on PHP
8.4 at all.
- ScriptHandler::installPharTools only created the tool symlink when it was
missing, so vendor/bin/box kept pointing at the box 2.7.5 phar of the
previously pinned URL. Update the symlink unconditionally and keep it
relative, so it survives the project being mounted at another path.
- The phar was only downloaded when its file name was absent, so a new version
published under the same name was never picked up. Record the installed URL
and re-download whenever the pinned URL changes, removing the phar of the
previously pinned version.
- dumpFile() ignored the mode argument, leaving the downloaded phar
non-executable. Set the mode via chmod().
- Pin box 4.7.0: 4.6.1 aborts on PHP 8.4 after emitting 260 implicit-nullable
deprecations.
- README: drop the deprecated "composer install --dev".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd
@fago
fago merged commit 8f402c6 into masterAug 31, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fago
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); fix: Repair the phar build on PHP 8.4. by fago · Pull Request #46 · drunomics/phapp-cli · GitHub
Skip to content

fix: Repair the phar build on PHP 8.4. - #46

Merged
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build
Aug 31, 2026
Merged

fix: Repair the phar build on PHP 8.4.#46
fago merged 1 commit into
masterfrom
feature/43-fix-phar-build

Conversation

@fago

@fagofago commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #45 (merged). Refs #43.

Problem

composer build — the command needed to produce a new phar for a 0.7.3 release — is broken:

> drunomics\Phapp\ScriptHandler::installPharTools
Downloading box.phar...
$ composer build
[InvalidArgumentException]
Command "compile" is not defined.
Script php -d phar.readonly=0 vendor/bin/box compile handling the build event returned with error code 1

Not a regression from #45. It is a latent bug since 69ac445 (Dec 2024), which bumped the pinned box from box2/2.7.5/box-2.7.5.phar to box/4.6.1/box.phar. Fresh clones happened to work, which is why it went unnoticed; any checkout that predates that bump is broken.

Root cause

Two independent defects in ScriptHandler::installPharTools():

a) The tool symlink was never repointed.

if (!$fs->exists("$bin_dir/$tool")) {
$fs->symlink("$bin_dir/$filename", "$bin_dir/$tool");
}

On a pre-bump checkout vendor/bin/box already existed, pointing at the leftover box-2.7.5.phar. The new box.pharwas downloaded — different basename, so the download guard let it through — but nothing ever linked to it. So composer build kept invoking box 2.7.5, whose command is build, not compile. Hence the error.

b) The download was keyed on the file name only.

if (!$fs->exists("$bin_dir/$filename")) { … }

A new box published under the same box.phar name would never be fetched, so the next version bump would have silently kept the old binary.

Fix

The installer now reconciles vendor/bin with the currently pinned URL:

  • the installed URL is recorded in vendor/bin/.<tool>.url;
  • the phar is re-downloaded whenever that URL changes, and the phar of the previously pinned version is removed;
  • the symlink is updated unconditionally, and is now relative (box -> box.phar) so it keeps working when the project directory is mounted at another path, e.g. inside a container.

Two smaller bugs surfaced along the way:

  • $fs->dumpFile($path, $content, 0755)Filesystem::dumpFile() takes no mode argument, so the third one was silently ignored and the downloaded phar was left non-executable (-rw-rw-r--). Now set explicitly via chmod().
  • README: composer install --devcomposer install (--dev is a no-op that Composer 2 warns about and Composer 3 will reject).

Box pinned 4.6.1 → 4.7.0

Box 4.6.1 (Dec 2023) does not run on PHP 8.4 at all, so even with the symlink fixed composer build could not produce a phar there:

boxcompile on PHP 8.4deprecations emitted
4.6.1 (was pinned)fails, exit 255260
4.6.10succeeds0
4.7.0 (now pinned)succeeds0

4.7.0 still builds on PHP 8.3 too, so this does not force maintainers onto 8.4.

Verification

Verified:

  • Reproduced the reported failure exactly by restoring the pre-bump vendor/bin state (a box -> box-2.7.5.phar symlink) and running composer install && composer build[InvalidArgumentException] Command "compile" is not defined.
  • That same broken checkout now self-heals: composer install repoints box -> box.phar (4.7.0), and composer build produces phapp.phar.
  • Fresh clone path: rm -rf vendor && composer install && composer build succeeds; vendor/bin/box.phar is now correctly -rwxr-xr-x.
  • Version-bump path: with .box.url recording 4.6.1 and composer.json pinning 4.7.0, composer install re-downloads and the symlink follows.
  • Compiled on PHP 8.4 with box 4.7.0 — 0 deprecations, exit 0 — and the resulting phar runs clean on PHP 8.4 (list, status).
  • composer validate → valid (lock content-hash refreshed via composer update --lock; no package versions changed); php -l clean.

Not verified / caveats:

  • The PHP 8.4 compile was run with git-version removed from the box config, because the bare php:8.4-cli image has no git binary and my sandbox could not install one. That setting only substitutes the version placeholder and is orthogonal to the PHP version; the full config including git-version was verified on PHP 8.3. The deprecation counts above come from identical configs, so the 4.6.1-vs-4.7.0 comparison is unaffected.
  • No test suite exists in this repo, so there is no automated coverage for the installer. Verification was the manual scenarios listed above.
  • phpstan analyse src --level=0 still reports the same 2 pre-existing errors in src/ScriptHandler.php (Composer\Script\Event / Composer\Util\StreamContextFactory unknown — composer/composer is not a dependency). Count unchanged by this PR.
  • Upgrading checkouts keep a stale vendor/bin/box-2.7.5.phar, since there is no record of it to clean up. It is no longer referenced and is harmless; rm -rf vendor clears it.

Why this matters for #43

#43 is only actually fixed for consumers once a 0.7.3 phar is released, and that phar cannot be built on PHP 8.4 without this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd

"composer build" failed with 'Command "compile" is not defined' on checkouts
that predate the box 2.7.5 -> 4.6.1 bump, and box 4.6.1 does not run on PHP
8.4 at all.
- ScriptHandler::installPharTools only created the tool symlink when it was
missing, so vendor/bin/box kept pointing at the box 2.7.5 phar of the
previously pinned URL. Update the symlink unconditionally and keep it
relative, so it survives the project being mounted at another path.
- The phar was only downloaded when its file name was absent, so a new version
published under the same name was never picked up. Record the installed URL
and re-download whenever the pinned URL changes, removing the phar of the
previously pinned version.
- dumpFile() ignored the mode argument, leaving the downloaded phar
non-executable. Set the mode via chmod().
- Pin box 4.7.0: 4.6.1 aborts on PHP 8.4 after emitting 260 implicit-nullable
deprecations.
- README: drop the deprecated "composer install --dev".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ouHkvipwQik1mwsrrBmUd
@fago
fago merged commit 8f402c6 into masterAug 31, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@fago