Skip to content

Fix Tinker execution and PsySH lifecycles - #570

Merged
binaryfire merged 18 commits into
0.4from
audit/tinker-correctness-lifecycle-parity
Sep 8, 2026
Merged

Fix Tinker execution and PsySH lifecycles#570
binaryfire merged 18 commits into
0.4from
audit/tinker-correctness-lifecycle-parity

Conversation

@binaryfire

Copy link
Copy Markdown
Member

Summary

This PR fixes Tinker's one-shot execution path and brings it onto PsySH's current include and signal lifecycles.

It also corrects alias boundaries, keeps caster failures local, removes stale package metadata, and completes the Tinker documentation.

Motivation

Tinker's direct execution path had several behaviors that differed from both its public options and current PsySH:

  • --execute=0 and --execute='' opened the interactive shell instead of executing the supplied value;
  • positional and project includes were configured but not loaded before direct execution;
  • requested exit codes were rendered as errors and changed to status 1;
  • direct execution could leave PsySH signal or error-handler state installed in the calling process;
  • disabled configured commands could reach PsySH as null;
  • Tinker changed the shared Console application's exception policy.

The alias loader also treated raw string prefixes as namespace and directory matches. A configured App\Nova alias could match App\NovaThing, and a vendor path could match a sibling with the same prefix.

Execution and PsySH

Direct and interactive execution now use PsySH's normal Shell.

PsySH loads configured includes at the outermost execution boundary, restores the caller's error handler after include failures, and pairs signal setup with cleanup. Hypervel keeps process forking disabled before the shell is created because pcntl_fork is incompatible with Swoole.

Every non-null --execute value selects direct execution. Requested exit codes are returned unchanged, ordinary failures return status 1, and the alias loader is unregistered on every exit path. Tinker no longer changes the Console application's exception policy.

The PsySH dependency temporarily tracks dev-main because the required lifecycle changes have been merged but are not in a stable release yet. Hypervel 0.4 must move to the first compatible stable release before it ships.

Aliases and casters

Configured aliases and exclusions are normalized once and matched as exact classes or real namespace descendants. Vendor exclusions require a real directory-child boundary.

Application presentation now contains failures per property, including native PHP errors, so one unavailable value does not hide the remaining application details.

The built-in Collection, HtmlString, Stringable, Model, ProcessResult, and Application casters are registered directly. Database and Process are already hard transitive dependencies through Foundation, so the old class checks and Database suggestion were misleading and have been removed. Application-defined casters still take precedence.

Documentation and metadata

The Artisan guide now covers:

  • one-shot execution and exit statuses;
  • positional includes and include failures;
  • alias and exclusion configuration;
  • custom casters;
  • project trust;
  • Hypervel's no-fork behavior.

The package README records the user-visible difference from Laravel and links back to its upstream source. Split-package metadata now matches the code and provider discovery is covered directly.

Performance and compatibility

These changes run only while starting or using the developer command. They add no request, queue, database, network, or worker hot-path work.

The final implementation removes the local shell subclass and two unnecessary autoload checks. It adds no locks, retries, polling, caches, context storage, or retained worker state.

Laravel-facing Tinker options and configuration remain compatible. Hypervel's coroutine execution and no-fork Swoole behavior remain intact.

Validation

The final tree passes formatting, both PHPStan configurations, Composer manifest validation, and the complete Tinker suite in normal and randomized order. Focused regressions cover direct execution, include loading and failure recovery, process-global cleanup, command filtering, alias boundaries, caster failures, nullable project trust, metadata, and coroutine execution.

For more details, see: docs/plans/2026-08-09-0219-tinker-correctness-psysh-lifecycles-and-current-parity.md

Summary by CodeRabbit

  • New Features

    • Tinker’s --execute mode now supports falsey values, preloaded files, and reliable exit statuses.
    • Tinker command filtering and ordering now respect configured enabled commands.
    • Class aliasing now matches exact classes and namespace boundaries more reliably.
    • Tinker continues displaying remaining application properties when one property cannot be read.
  • Bug Fixes

    • Improved handling of parse errors, interrupts, exceptions, and execution cleanup.
    • Vendor-path alias exclusions now avoid unintended matches.
  • Documentation

    • Expanded Tinker and Artisan guidance for execution, aliasing, custom casters, trust settings, and runtime behavior.
    • Tinker now prompts before loading unfamiliar project configuration by default.

Treat every non-null --execute value as one-shot code, including zero and the empty string. Preserve PsySH exit codes, contain ordinary execution failures, and stop mutating Symfony Console's shared exception policy.

Use a small execute-only shell that omits PsySH's interactive signal listener while keeping the normal interactive shell unchanged. Tighten configured command and alias inputs, keep loader cleanup exception-safe, and cover falsey code, signals, exit behavior, disabled commands, coroutine dispatch, and the disposable application subprocess path.
Normalize configured class and namespace names once, then match only exact classes or real namespace descendants. This prevents a prefix such as App\Nova from also admitting App\NovaThing.

Apply the same boundary rule to exclusions and require vendor paths to be actual children of the configured vendor directory. Add coverage for exact matches, descendants, prefix siblings, trailing separators, exclusions, vendor children, and vendor-prefix siblings.
Keep application presentation best-effort when one optional getter throws an Error or TypeError. Each property is resolved independently, so a failing value is omitted without hiding the remaining useful application details.

Retain null filtering and caster output order, and add a regression that proves later virtual properties are still rendered after an earlier getter fails.
Remove the unused Contracts dependency and align the split package's direct external constraints with the monorepo root. Keep Database as the one optional package that enables documented Tinker behavior and preserve provider discovery metadata.

Add focused metadata coverage so dependency constraints, the Database suggestion, and automatic provider discovery cannot drift. Complete return types in the neighboring provider tests while keeping their behavior unchanged.
Link the split package to Laravel Tinker, which remains its upstream source. Keep the README deliberately small so the Boost guide remains the single user-documentation surface.
Document one-shot execution and exit codes, positional includes, alias controls, custom casters, project trust, and Hypervel's process-forking limit in the same plain style as the surrounding Artisan guide.

Keep the section focused on supported user behavior. It avoids internal listener details and does not document direct include execution until the required public PsySH lifecycle ships in a stable release.
Record the verified Tinker command, alias, caster, metadata, and documentation findings together with their final designs, performance limits, rejected alternatives, and regression coverage.

Route the core audit and ledger to this work unit while keeping Tinker open for the one remaining release dependency: a stable PsySH version containing the public, exception-safe include lifecycle. Record the related upstream signal and full-run corrections without making them Hypervel completion gates.
…ss-lifecycle-parity

# Conflicts:
#	docs/plans/2026-07-12-0900-framework-coroutine-state-lifecycle-audit.md
#	docs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.md
Use PsySH dev-main while Hypervel 0.4 is under development and remove the obsolete local shell subclass from the final design.

Drop completed upstream PR history, preserve the newer Tinker work already on 0.4, point the guide at its current location, and keep only the dependency behavior needed to finish implementation and validation.
Bring the branch onto the current framework while preserving the newer Tinker command lifecycle, optional configuration, configured casters, public model-appends access, and relocated documentation.

Resolve the overlapping audit records without dropping later 0.4 work, and layer the existing Tinker correctness changes onto the newer source and test coverage.
Use PsySH's normal Shell for both direct and interactive execution now that the dependency owns include loading and paired signal cleanup. Remove the temporary local shell subclass, preserve exact exit codes, keep caller-owned Console policy unchanged, and retain disabled-command filtering.

Point both manifests at PsySH dev-main until the required behavior has a stable release. Remove metadata that no longer reflects the dependency graph, register built-in casters without dead class checks, and cover includes, process state, nullable trust, command selection, and split-package metadata.
Exercise vendor exclusion through the loader without creating a permanent PHP class alias. Remove the unused classmap fixture so the test remains isolated in normal, reverse, and randomized execution order.
Explain one-shot execution, exit statuses, positional includes, alias controls, custom casters, and project trust in the Artisan guide.

Record the user-visible no-fork difference in the package README while keeping detailed usage in the main documentation.
Record the final execution, include, alias, caster, metadata, and documentation design together with its focused regression coverage and performance limits.

Mark the Tinker work complete after validation and review, while keeping the stable PsySH release requirement explicit as a Hypervel 0.4 release gate.
Use PsySH's prompt mode by default so Tinker does not silently execute .psysh.php from an unfamiliar working directory. The existing trust_project setting and all supported values remain available for applications that want a different policy.

Keep the trusted include test explicit about its policy, add a regression proving non-interactive execution skips untrusted project configuration, and pin the shipped default in the provider test.
Explain how Tinker handles unfamiliar project configuration in interactive and non-interactive sessions. Show the supported environment override for trusted automation and the never mode for disabling local configuration.

Record the intentional Laravel default difference in the package README and porting guide so applications that rely on .psysh.php know when to opt into always.
Add the approved project-trust finding and final treatment to the Tinker plan and audit ledger. Record the compatibility boundary, rejected alternatives, focused regression, and load-bearing old-default counterfactual.

Also repair the malformed findings table cell and close the work unit after validation, self-review, and final review.
@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: c714c7f3-1e63-464a-b5d1-8bead8872c07

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@binaryfire
binaryfire merged commit 44c6e48 into 0.4 Sep 8, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant