rector/jack
Jack is an experimental Composer tool that helps you raise PHP dependencies safely, one version at a time. Its CI breakpoint command flags outdated major packages and prioritizes low-risk upgrades, helping you avoid risky large jumps and years-old dependencies.
Architecture fit
Jack sits entirely at the Composer manifest layer: it reads composer.json, compares declared constraints against Packagist metadata, and rewrites version ranges. It ships no service provider, no runtime code, and no Laravel coupling, so it is framework-agnostic by construction — it will "fit" any Composer project, including Laravel. That is also its ceiling: it has no model of Laravel's internal version matrix (framework ↔ illuminate/* ↔ Symfony components ↔ PHP floor), so it can produce a technically valid composer.json that is framework-incompatible. For a TPM, the correct framing is that Jack is a process tool, not a library — its value is the pacing policy it enforces (breakpoint as a debt alarm, open-versions as incremental widening, raise-to-installed as constraint hygiene), and that policy is separable from the binary.
Integration feasibility
Mechanically trivial: one --dev require, three commands, CI-friendly exit codes, --dry-run on every mutating path. Integration cost is measured in hours, not sprints. The blocker is not technical feasibility but lifecycle: the repository is archived and marked deprecated with a redirect, has zero dependents, carries an explicit experimental disclaimer, and shows conflicting metadata (README claims PHP 7.2+, release 1.2.1 claims 7.4–8.5; a release is dated 2026-09-30 while the project is listed as archived). Those inconsistencies are themselves a diligence finding — release provenance cannot be trusted for compliance or audit records.
Technical risk High and concentrated in lifecycle rather than code quality:
open-versions emits wide ranges (^9.0|^10.0) that can silently raise the transitive PHP floor (PHPUnit 10 → PHP 8.1) and resolve to versions our runtime cannot execute; raise-to-installed can over-tighten and block future patch/security releases.Key questions
breakpoint's exit-code contract, and does it require live Packagist access at CI time (rate limits, air-gapped runners, flaky-network false failures)?composer audit, which we likely already run? Is this additive or duplicative?Stack fit
Fits Laravel at the manifest level but must be paired with framework-aware validation that Jack does not perform: Laravel version → PHP floor → illuminate/* alignment → Symfony component compatibility (e.g., Laravel 10/11 against Symfony 6.4/7.x). Position Jack as the pacing policy layer, not the update engine — Composer remains the resolver, Dependabot/Renovate remains the automation, composer audit remains the security gate.
Migration path Because the package is archived, the realistic path is a harvest, don't adopt pattern:
composer outdated --direct --strict as the debt signal, grouped Dependabot/Renovate PRs for incremental widening, and composer show --platform / composer why-not php as the floor check.Compatibility
PHP 7.4–8.5 per the latest release (README's 7.2+ is stale), Composer 2 only, symfony/process ^5.4–^8.1, dev-only install, no PHAR. Windows runners must be on ≥0.2.7. Note that a tool that widens constraints must itself be compatible with the oldest runtime it edits — verify before running on the PHP 7.4 services in a monorepo.
Sequencing
breakpoint --dev --limit 5 in CI non-blocking, log-only, to size the debt.open-versions --dev --limit 3 --dry-run, review the diff, composer validate, run the full test matrix, commit, then composer update. Repeat in small batches.--package-prefix illuminate first, then symfony/*, then long tail — one prefix per PR to isolate failure surfaces.raise-to-installed --dry-run after every merge that changes the lockfile.breakpoint blocking, and only after two clean sprints with no flaky failures.Maintenance Archived status flips the cost model. Casual CLI use costs near zero; pinning, vendoring, or patching costs real engineering time with no upstream to share it with. Budget a named dependency owner and a calendar review (quarterly) to re-evaluate the successor — otherwise the tool we adopted to fight dependency rot becomes dependency rot itself.
Support
No vendor, no SLA, no maintainer triage, no dependents to search for prior art. Every issue is self-diagnosed. Ramp-up is asymmetric: the CLI takes half a day to learn, but safe judgment — reasoning about whether ^9.0|^10.0 is acceptable for our PHP floor — takes a sprint and should sit with a senior reviewer, not be delegated.
Scaling
Fine for single-app repos with tens of packages. Degrades in monorepos: constraint conflicts compound across workspaces, breakpoint needs live Packagist metadata and can time out in CI, and open-versions --limit N becomes a blunt instrument when N spans unrelated package families. Mitigate with composer.lock caching, running after composer install, and prefix-scoped runs.
Failure modes
| Failure | Impact | Detection | Mitigation |
|---|---|---|---|
| Silent upstream rot (no security patches) | Unknown-vuln exposure | SCA tool independent of Jack | Pin exact version; quarterly successor review |
| Over-broad range merged | Prod runtime incompatibility | Staging/CI test matrix | Mandatory --dry-run + diff review + composer validate |
raise-to-installed over-tightening |
Blocks security patches later | Diff review | Prefer caret on installed minor, not exact |
| PHP floor drift (PHPUnit 10 → 8.1) | Build breaks on legacy runtimes | composer show --platform, why-not php |
Platform check gate before commit |
| Packagist/network flakiness in CI | Alert fatigue, ignored gate | Failure-rate tracking | Non-blocking mode first, retries, cached metadata |
| Windows diff corruption (<0.2.7) | Unreadable review artifacts | Visual diff check | Pin ≥0.2.7 |
Ramp-up
Timebox a one-week trial, dev dependencies only, --dry-run mandatory on every mutating command, rollback defined as git checkout composer.json composer.lock. Success criteria: measurable reduction in behind-major dev packages with zero production incidents and no increase in CI flake rate. Exit criteria: any of the failure modes above reproduces twice, or the successor becomes viable — migrate and drop the pin.
How can I help you explore Laravel packages today?