php-tui/cassowary
A PHP implementation of the Cassowary constraint solver for building flexible terminal interfaces. Add and remove linear equality and inequality constraints with priorities to automatically calculate widget sizes and positions in PHP-TUI layouts.
What it actually is: php-tui/cassowary is a userland PHP port of the Cassowary incremental constraint-solving algorithm (the dual-simplex solver behind Apple Auto Layout and the Kiwi C++ library). It ships Variable, Constraint, Expression, Strength, and Solver primitives and is deliberately framework-agnostic. It is a library, not a Laravel package — no service provider, no config file, no facade, no published Laravel version constraints.
Architecture fit: Good. The dependency is leaf-level, PSR-4 autoloaded, stateless at the framework boundary, and has essentially no transitive surface area. It composes cleanly into a layout or rendering pipeline that needs declarative geometry ("this panel is at least 40 cols and flush to its parent's right edge") rather than imperative arithmetic. It is not a fit for request/response business logic.
Integration feasibility: High for a spike, moderate for production. A working proof-of-concept is a few hours of work: instantiate a Solver, add variables, add constraints with strengths, call solve(). The absence of Laravel glue is trivial to bridge (a singleton binding + a thin internal wrapper), but that wrapper is work you own and must not skip.
Technical risk:
php-tui) whose primary artifact is the TUI framework itself. This package likely exists to serve that framework and is not independently roadmapped.UnsatisfiableConstraintException) need empirical characterization — these are exactly where ports diverge from the reference implementation.Key questions to answer before adoption:
addEditVariable/suggestValue), or only full-solve? Full-solve-only materially changes the performance ceiling.required/strong/medium/weak strengths and constraint priorities supported, and do they behave like the reference?Stack fit: Composer-native and Laravel-consumable, but it belongs in the presentation/layout layer, not the domain layer. It fits any of: TUI dashboards, dynamically sized console reports, PDF/HTML grid generation, form layout engines, or chart axis arrangement. It does not fit queue workers, API validation, or anything where the constraint graph changes hundreds of times per request.
Migration path: Do not rip out existing layout logic. Introduce the solver behind an internal LayoutSolver interface you own, with two implementations: the current imperative code and the Cassowary-backed one. Ship the Cassowary path behind a feature flag, diff rendered output against golden fixtures, and only cut over once the comparison is clean across a representative corpus. The interface is also your exit ramp to a native Kiwi binding or an FFI wrapper if PHP throughput disappoints.
Compatibility: Low conflict risk — the dependency tree is effectively empty, so Composer resolution should never be the blocker. The real compatibility question is PHP version floor versus your fleet. Verify it against every PHP minor you run, and pin the exact version with a committed composer.lock; a 0.x library should never float.
Sequencing:
required constraint.Maintenance: This is the dominant cost. MIT licensing permits forking, and you should assume you will. Budget roughly 2–5 engineer-days per year for dependency hygiene plus a standing provision to adopt the fork if upstream stalls. Keep the wrapper thin so a fork swap is a one-file change.
Support: Community-only, no SLA, no vendor, no commercial backing. There is no realistic path to upstream-driven bug fixes on your timeline. Internal ownership must be assigned by name before adoption — an unowned layout engine is a latent incident.
Scaling: Scales badly with constraint count and re-solve frequency; scales fine with request volume (it's stateless and cheap to instantiate). Guardrails: cap constraints per solve, cache solved layouts keyed by viewport dimensions, prefer incremental edits over rebuilds, and set a hard timeout around the solve call. If you cross roughly a few hundred constraints per frame, plan the native-solver exit.
Failure modes to instrument:
Ramp-up: The API surface is small (a day to productivity); the concepts are not. Engineers need working fluency in constraint strengths, priorities, and dual-simplex debugging to diagnose why a layout picked the solution it did. Plan one senior engineer as the designated owner and expect 3–5 days of genuine learning before they can debug a bad constraint graph. Documentation will come from your own notes, not from the package.
How can I help you explore Laravel packages today?