Release: 0.44 - Feedback Loop
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 (--jsonfor machine output)phel test --coverage[=text|clover]: line coverage collected via pcov or xdebug and mapped back to.phelsources through the build source maps. Per-file and total percentages intext, 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--parallelfor 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. Thehttp-json-apiexample gains aDEPLOYMENT.md(build flow, opcache, nginx + php-fpm, worker-mode caveats) and a multi-stageDockerfile(#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\Qualifiedpositions, and global functions afterphp/; hover with the reflected signature for PHP methods/functions/classes; signature help for(php/new ...)and method calls. Receiver types come from:tagmetadata, 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-twith no value) lists them. Composes with--dry-run/--force. Templates are sourced fromresources/agents/examples/(now shipped insidephel.phar) (#2430)- Optimization levels:
PhelConfig::withOptimizationLevel(int)andphel build -O <level>; level 2 enables^:pureinlining + self-recursive tail-call rewriting (REPL/nREPL stay at 0) (#2387) phel test --watch: re-runs the selected tests on every.phel/phel-config.phpchangephel test: startup progress on stderr, and an expected/actual diff with a caret on failed=assertionswithBuildConfig()/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 opsreload(allparam) andrun-tests(ns+ optionalvarparam) let editors bind "reload changed" and "run test under cursor"
⚖️ Changed
phel test:FAIL/ERRORheadlines now carry thedeftestname (FAIL my-test (file.phel:4))phel initscaffolds a documentedphel-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
.phelsources (#2428):phel runprints the Phel frames of an uncaught error asfile.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-traceactually prints the trace; macro-expansion errors show where the macro was defined (Defined: file.phel:line) phel testexit codes: no longer exits 0 when nothing ran, bad paths/selectors fail loudly, and--listno longer appends a falseNo tests matchedawait-all(andpmap, which builds on it) now return results in input order;Amp\Future\awaitfills its result array in completion order, so concurrent Futures that resolved out of order came back shuffled- Editing
phel-config.phptakes effect immediately again: Phel clears Gacela's stale merged-config cache (requiresgacela-project/gacela: ^1.15) - Build config withers are order-independent:
cacheDiris normalized andwithMainPhelNamespace(...)no longer pins the entry point - Source maps resolve again:
phel buildruntime 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
Full Changelog: v0.43.0...v0.44.0
Downloads
v0.44.0
- phel.phar (1.75 MB)