Skip to main content

Release: 0.44 - Feedback Loop

Latest update

0.44.0 - Feedback Loop

Released 2026-06-13 · GitHub release

Config tooling (phel config, optimization levels, composable setters) + sharper test runner (--watch, coverage, clearer failures) + LSP PHP interop + REPL reload.

Two themes: project configuration (phel config, optimization levels, composable config setters) and a sharper test runner (--watch, startup progress, clearer failures).

🎉 Added

  • phel config: prints the merged config with provenance (--json for machine output)
  • phel test --coverage[=text|clover]: line coverage collected via pcov or xdebug and mapped back to .phel sources through the build source maps. Per-file and total percentages in text, or Clover XML via --coverage-output=<path> for CI (Codecov etc.). Only project source files count (vendor and core excluded); requires pcov or xdebug (clear error otherwise); runs serially (a clear message disables --parallel for the run) (#2433)
  • phel build --report: prints a build summary (namespace count, per-namespace compiled size, total size, fresh/cached breakdown, build time) to spot bloat and verify CI builds. The http-json-api example gains a DEPLOYMENT.md (build flow, opcache, nginx + php-fpm, worker-mode caveats) and a multi-stage Dockerfile (#2432)
  • LSP PHP interop (#2431): completion for instance methods/properties after (php/-> receiver ...), static methods/constants after (php/:: Class ...), class names in (php/new ...) and \Fully\Qualified positions, and global functions after php/; hover with the reflected signature for PHP methods/functions/classes; signature help for (php/new ...) and method calls. Receiver types come from :tag metadata, inline (php/new \Foo), or a local (php/new ...) binding; an unknown type degrades to no completion with no diagnostics
  • phel init --template=<name> (-t): scaffold a runnable project from a bundled example (http-json-api, todo-app, cli-wordcount), with namespaces/composer/entry points renamed to the project name; --list-templates (or -t with no value) lists them. Composes with --dry-run/--force. Templates are sourced from resources/agents/examples/ (now shipped inside phel.phar) (#2430)
  • Optimization levels: PhelConfig::withOptimizationLevel(int) and phel build -O <level>; level 2 enables ^:pure inlining + self-recursive tail-call rewriting (REPL/nREPL stay at 0) (#2387)
  • phel test --watch: re-runs the selected tests on every .phel/phel-config.php change
  • phel test: startup progress on stderr, and an expected/actual diff with a caret on failed = assertions
  • withBuildConfig()/withExportConfig() accept a configurator closure
  • REPL-driven workflow (#2429): (reload!) re-evaluates project namespaces whose source changed since the last load (plus their dependents) in dependency order; (reload-all!) force-reloads every project namespace; (run-tests 'ns ...) and (run-test 'ns/test) run tests from the REPL. Matching nREPL ops reload (all param) and run-tests (ns + optional var param) let editors bind "reload changed" and "run test under cursor"

⚖️ Changed

  • phel test: FAIL/ERROR headlines now carry the deftest name (FAIL my-test (file.phel:4))
  • phel init scaffolds a documented phel-config.php
  • User-facing guides moved to phel-lang.org (incl. a new Deployment guide); docs/ is now contributor-facing only (#2424)

🐛 Fixed

  • Runtime stack traces point at .phel sources (#2428): phel run prints the Phel frames of an uncaught error as file.phel:line (PHP-internal frames collapsed), also when the namespace was loaded from the build cache; the REPL no longer hides user fn frames; phel test --stack-trace actually prints the trace; macro-expansion errors show where the macro was defined (Defined: file.phel:line)
  • phel test exit codes: no longer exits 0 when nothing ran, bad paths/selectors fail loudly, and --list no longer appends a false No tests matched
  • await-all (and pmap, which builds on it) now return results in input order; Amp\Future\await fills its result array in completion order, so concurrent Futures that resolved out of order came back shuffled
  • Editing phel-config.php takes effect immediately again: Phel clears Gacela's stale merged-config cache (requires gacela-project/gacela: ^1.15)
  • Build config withers are order-independent: cacheDir is normalized and withMainPhelNamespace(...) no longer pins the entry point
  • Source maps resolve again: phel build runtime errors map back to .phel, and inline eval maps are scanned past <?php/declare
  • Removed the docs doctest harness (composer test-docs, tests/doctest/): its guides moved to phel-lang.org

👥 Contributors

@JesusValeraDev @chemaclass

Full Changelog: v0.43.0...v0.44.0

Downloads

v0.44.0


View release on GitHub