Skip to content

Correct Wayfinder generation and route fidelity - #7

Merged
binaryfire merged 22 commits into
0.4from
audit/wayfinder-correctness-generation-parity
Aug 9, 2026
Merged

binaryfire merged 22 commits into
0.4from
audit/wayfinder-correctness-generation-parity

Conversation

@binaryfire

@binaryfire binaryfire commented Aug 9, 2026 •

Copy link
Copy Markdown
Member

Summary

This change makes Wayfinder's generated TypeScript match Hypervel Routing across route defaults, model bindings, domains, booleans, null omission, query values, and actions registered with multiple verbs.

It also makes generated names and barrel files deterministic, closes output-path collisions, publishes changed files atomically with ordinary file modes, restores cached test application state correctly, and adds dedicated frontend checks for normal and cached routes.

What changed

  • Resolve global and middleware URL defaults against each route's real parameter and binding metadata.
  • Replace the single-value middleware parser with a bounded tokenizer that handles every supported URL::defaults() array call without evaluating PHP.
  • Keep binding-aware defaults authoritative in Routing, normalize boolean URL parameters, prevent consumed root defaults from leaking into query strings, and reject conflicting root and route placeholders.
  • Use one generated route-parameter formatter for path and domain values, including backend-compatible encoding and named missing-parameter errors.
  • Make optional null values, boolean scalars, binding keys, tuple labels, and query arrays agree between generated types and runtime behavior.
  • Allocate controller, named-route, form-helper, and barrel identifiers within their actual TypeScript scopes. Leaf and namespace collisions remain reachable through stable public keys, while impossible filesystem layouts fail before publication.
  • Coalesce compatible same-action, same-URI routes into one stable multi-verb definition and reject conflicting default metadata.
  • Preserve unchanged generated files, replace changed files atomically, report stale-file deletion failures, and keep generated files non-executable unless a caller explicitly requests another mode.
  • Prefer model cast evidence for binding types, retain bounded worker caches, and reset every cache through the existing test cleanup path.
  • Reject an explicitly empty output path before any filesystem work and keep controller source paths relative only when they are actually inside the application root.
  • Restore cached configuration and route state across repeated Foundation and Testbench application boots. Testbench now defines routes before cache capture and leaves cached-route loading to the route provider.
  • Replace copied dependency-version assertions with relationship-based package metadata checks.
  • Add normal Vitest, cached-route Vitest, and strict TypeScript checks to a dedicated Wayfinder CI job.
  • Add first-party Wayfinder documentation covering setup, imports, parameters, bindings, forms, query values, URL defaults, SSR usage, and deployment ordering.

Compatibility and performance

The public surface remains Laravel-shaped: generated imports, parameter forms, named arguments, protected extension points, form helpers, and URL-default APIs are preserved. The behavior changes correct invalid or contradictory URLs and adapt generation to Hypervel's request-scoped origin and long-lived runtime.

Most work runs only during generation, compilation, tests, or frontend builds. Routing adds one primitive boolean branch per supplied URL parameter; the remaining Routing changes replace existing lookups and removals without adding I/O. No request-path lock, retry, polling loop, registry, or retained per-request state is introduced.

Validation

The change passes the complete formatter, static analysis, parallel PHP suite, Testbench package checks, and dogfood checks. Wayfinder's PHP tests, normal and cached Vitest suites, and strict generated TypeScript checks also pass, along with the focused Routing, Filesystem, Foundation, Testbench, Rate Limiter, and package metadata coverage.

For more details, see: docs/plans/2026-08-08-1709-wayfinder-correctness-generation-parity-and-bounded-lifecycles.md

Summary by CodeRabbit

  • New Features

    • Expanded Wayfinder support for typed route generation, optional parameters, booleans, enums, model bindings, URL defaults, forms, query parameters, SSR, and Inertia.
    • Added route-caching and TypeScript type-checking workflows.
    • Added comprehensive Wayfinder documentation and navigation.
  • Bug Fixes

    • Improved URL encoding, parameter validation, route defaults, naming collision handling, and duplicate route generation.
    • Corrected generated file permissions and cached application state behavior.
    • Improved encoded-path handling for filesystem URLs and uploads.
  • Tests

    • Added broad regression coverage for routing, caching, generation, bindings, filesystem behavior, and package metadata.

Normalize boolean route parameters to the same scalar values used by generated Wayfinder calls. Keep binding-aware defaults authoritative when callers supply null, consume forced-root defaults exactly once, and prevent root fallbacks from leaking into the query string.

Resolve root and route placeholders before final formatting so shared parameters cannot produce contradictory hosts and paths. Add regressions for boolean values, bound defaults, route domains, forced roots, query cleanup, and placeholder collisions.
Make mode-less atomic replacement create files with the same non-executable default used by normal writes while preserving explicitly supplied modes and atomic inode replacement.

Cover new files, replacements, active umasks, environment encryption, and configuration publication so generated framework data cannot silently gain executable bits.
Re-arm retained configuration and route caches before each opted-in Foundation application boot. Preserve the cached-route marker without introducing worker-lifetime filesystem memoization, and reuse the existing recursive trait identity map.

Add repeated-boot coverage proving cached configuration and compiled routes survive application recreation while remaining isolated to tests that use the matching cache traits.
Register the application route provider through Testbench's resolved provider list and define Testbench routes immediately after application creation, before cached-route traits capture the collection. Re-arm retained Foundation cache state at the matching pre-bootstrap seam.

Remove duplicate cached-file loading, keep uncached route synchronization independent from provider-owned caches, and cover repeated boots, mixed cached and stash routes, provider overrides, workbench registration, and every supported refresh path.
Separate exact consumption and denial decisions from refill recovery so the shared store contract no longer depends on subsecond scheduling during a multi-call sequence.

Use stable policy keys with exception-safe cleanup, a slow policy for exact atomic decisions, and a fast policy only for the bounded recovery assertion. Production rate-limiter behavior is unchanged.
Move the PHPDoc parser into root runtime requirements because Wayfinder generation and the Facade Documenter binary load it in production. Declare Wayfinder's direct tokenizer, reflection, and parser requirements without redundant core extensions.

Replace copied dependency-version assertions with relationship checks derived from root constraints and package branch aliases. Cover Wayfinder provider discovery and keep package metadata tests focused on installable contracts rather than version transcription.
Normalize binding-aware URL defaults once per route, distinguish caller-optional arguments from optional URI segments, and preserve scalar default types including booleans and enum-valued binding fields.

Infer model binding types from primitive casts before schema and PHPDoc evidence, keep decimal values as strings, support primitive unions, and flush every bounded worker metadata cache. Add focused coverage for defaults, binding evidence, paths, and cache cleanup.
Normalize boolean values, encode substituted route parameters with backend-equivalent semantics, preserve Routing's allowed characters, and report missing required parameters by name.

Extend query serialization to boolean values and arrays while retaining nested object behavior. Add direct runtime coverage for boolean, array, and parameter-formatting cases without adding state or repeated I/O.
Parse every supported URL default expression without evaluating PHP, resolve generated arguments before validation, and emit truthful boolean, null, tuple, binding, domain, and multi-verb contracts.

Allocate identifiers within their real TypeScript scopes, preserve callable leaf and namespace pairs, retain public camel keys with collision-safe raw fallbacks, and reject only real controller/barrel path conflicts. Scope syntax cleanup to generated fragments so route literals remain untouched.

Publish changed files atomically, avoid no-op writes, fail truthful stale deletion, keep View registration idempotent, isolate fixture generation, preserve external controller paths, and reject an explicitly empty output path. Add normal and cached-route regressions for generation, imports, collisions, defaults, encoding, forms, publication, and deterministic repeat output.
Run normal generated-route behavior, cached-route behavior, and strict TypeScript validation through package and root scripts. Configure the generated ESM fixtures with bundler module resolution and no emitted output.

Add a standalone CI job with the repository's supported PHP, Swoole, Node, and pnpm toolchain so frontend generation is checked once outside the PHP matrix and remains separate from Composer workflows.
Add one canonical Laravel-prose guide covering installation, generated files, imports, parameter shapes, model bindings, multi-route actions, forms, queries, URL defaults, Inertia, SSR, and deployment ordering.

Keep the package README minimal while recording Hypervel's request-scoped origin difference and linking developers to the canonical guide. Add the guide to the documentation index.
Call the generated route's url helper before supplying query options. The previous example invoked the route definition directly and did not match the public generated API.
Replace PHPUnit's removed result-cache option with the current test-run-history option in the parallel-testing warning. ParaTest's transitional worker argument remains owned by its upstream correction.
Record the Vite plugin's instance context, argument parsing, Windows path, serialized scheduling, burst collapse, and failure-recovery requirements for an upstream fix rather than adding Components-side shims.

Also make the planned Boost implementation consume the Wayfinder and Horizon skill templates that already ship with their packages.
Document the final generation, Routing, Filesystem, Foundation, Testbench, Rate Limiter, Testing, metadata, and documentation designs together with their evidence, rejected machinery, performance boundaries, and regression coverage.

Add durable finding ownership and cross-package revalidation entries, account for IDs already allocated on the merge target, record the external plugin and Boost ownership boundaries, and mark Wayfinder complete only after all gates, self-review, and independent review signed off.
# 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
#	tests/Routing/PackageMetadataTest.php
@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b880c8be-e614-40cc-9a44-b6960f844392

📥 Commits

Reviewing files that changed from the base of the PR and between 6c56016 and 8b430d2.

📒 Files selected for processing (21)
  • 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
  • docs/plans/2026-08-08-1709-wayfinder-correctness-generation-parity-and-bounded-lifecycles.md
  • src/boost/docs/filesystem.md
  • src/filesystem/src/FilesystemAdapter.php
  • src/filesystem/src/LocalFilesystemAdapter.php
  • src/routing/src/RouteUrlGenerator.php
  • src/testbench/src/Concerns/HandlesRoutes.php
  • src/wayfinder/resources/js/wayfinder.ts
  • src/wayfinder/tests/DefaultParameters.test.ts
  • src/wayfinder/tests/KeyController.test.ts
  • src/wayfinder/tests/UrlDefaultsController.test.ts
  • tests/Filesystem/AwsS3V3AdapterTest.php
  • tests/Filesystem/FilesystemAdapterTest.php
  • tests/Filesystem/GoogleCloudStorageAdapterTest.php
  • tests/Integration/Filesystem/ReceiveFileTest.php
  • tests/Integration/Filesystem/ServeFileTest.php
  • tests/Routing/RoutingUrlGeneratorTest.php
  • tests/Testbench/Concerns/DefineCacheRoutesTest.php
  • tests/Wayfinder/Fixtures/Middleware/UrlDefaultsMiddleware.php
  • tests/Wayfinder/Fixtures/routes.php
💤 Files with no reviewable changes (1)
  • src/boost/docs/filesystem.md
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/wayfinder/tests/UrlDefaultsController.test.ts
  • src/wayfinder/tests/KeyController.test.ts
  • tests/Wayfinder/Fixtures/Middleware/UrlDefaultsMiddleware.php
  • src/testbench/src/Concerns/HandlesRoutes.php
  • src/wayfinder/tests/DefaultParameters.test.ts
  • tests/Wayfinder/Fixtures/routes.php
  • docs/plans/2026-07-12-0900-framework-coroutine-state-lifecycle-audit.md
  • src/wayfinder/resources/js/wayfinder.ts

📝 Walkthrough

Walkthrough

Wayfinder now supports typed route parameters, URL-default parsing, collision-safe generation, route coalescing, encoded filesystem URLs, atomic publication, and cached-route validation. Foundation and Testbench lifecycle handling, package metadata, CI, documentation, and regression tests were updated.

Changes

Wayfinder correctness and framework integration

Layer / File(s) Summary
Framework lifecycle and routing integration
src/foundation/..., src/testbench/..., src/routing/..., src/filesystem/...
Cached application state, route synchronization, boolean URL formatting, root defaults, filesystem URL encoding, and replacement permissions were updated.
Wayfinder generation and type contracts
src/wayfinder/src/*, src/wayfinder/resources/*
Generation now handles typed parameters, binding metadata, URL defaults, identifier collisions, route coalescing, and atomic output updates.
Wayfinder runtime validation
src/wayfinder/tests/*, tests/Wayfinder/*, tests/Routing/*, tests/Filesystem/*
Tests cover generated URLs, optional parameters, model bindings, defaults, naming, cached routes, stale files, filesystem URLs, and inferred types.
Validation and documentation
.github/workflows/*, docs/*, src/boost/docs/*, tests/*/PackageMetadataTest.php
CI scripts, package metadata checks, audit records, implementation plans, and Wayfinder documentation were added or updated.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GenerateCommand
  participant Route
  participant TypeScript
  participant Filesystem
  GenerateCommand->>Route: collect route defaults and parameter metadata
  Route->>GenerateCommand: return normalized route descriptors
  GenerateCommand->>TypeScript: render typed route modules and barrels
  GenerateCommand->>Filesystem: atomically replace changed generated files
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary changes to Wayfinder generation and route behavior.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch audit/wayfinder-correctness-generation-parity

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

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@greptile-apps

greptile-apps Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR aligns generated Wayfinder URLs and types with Hypervel Routing while hardening generation, publication, filesystem URL handling, and cached test-application lifecycles.

  • Unifies route defaults, bindings, parameter encoding, optional values, query handling, domains, booleans, and multi-verb actions.
  • Makes generated identifiers, barrels, output paths, file replacement, permissions, and stale-file cleanup deterministic.
  • Restores cached Foundation and Testbench state correctly across repeated application boots and adds dedicated frontend, cached-route, and strict TypeScript validation.
  • Adds first-party Wayfinder documentation and relationship-based package metadata checks.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/routing/src/RouteUrlGenerator.php Escapes delimiter and placeholder syntax at the parameter-substitution boundary while preserving intended path characters.
src/routing/src/UrlGenerator.php Updates URL-default handling and parameter normalization to preserve routing metadata and prevent consumed defaults from leaking into queries.
src/filesystem/src/FilesystemAdapter.php Encodes raw storage paths at Hypervel-owned URL-construction boundaries while preserving delegated adapter ownership.
src/filesystem/src/LocalFilesystemAdapter.php Passes raw local temporary-route paths to the routing layer so values are encoded exactly once.
src/testbench/src/Concerns/HandlesRoutes.php Re-arms route synchronization after application reloads clear lifecycle callback state.
src/foundation/src/Application.php Restores cached application configuration and route state across repeated boots.
src/wayfinder/src/GenerateCommand.php Hardens deterministic generation, output-path validation, atomic publication, stale-file cleanup, and file modes.
src/wayfinder/src/Route.php Aligns generated route metadata, defaults, bindings, domains, and compatible multi-verb action coalescing.
src/wayfinder/resources/js/wayfinder.ts Centralizes backend-compatible route-parameter formatting, null omission, boolean normalization, and query behavior.
src/wayfinder/src/TypeScript.php Allocates generated identifiers within their actual TypeScript scopes and rejects impossible filesystem layouts.

Reviews (3): Last reviewed commit: "Finalize the Wayfinder URL integrity pla..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/wayfinder/resources/js/wayfinder.ts (1)

170-186: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a result type that matches null/undefined inputs.

applyUrlDefaults(null) and applyUrlDefaults(undefined) return objects at runtime, but the generic signature keeps the result as null or undefined. This blocks consumers from using runtime default parameters even when the generated call passes those inputs.

Return UrlDefaults for nullish inputs, while preserving the object input type for non-null inputs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/wayfinder/resources/js/wayfinder.ts` around lines 170 - 186, Update the
return type of applyUrlDefaults so null or undefined inputs are typed as
UrlDefaults, while non-null object inputs retain their existing object type.
Preserve the current runtime default-merging behavior and use a conditional
return type that distinguishes nullish from non-null T.
🧹 Nitpick comments (1)
tests/Wayfinder/Fixtures/Middleware/UrlDefaultsMiddleware.php (1)

27-34: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Explain why $unrelated exists.

$unrelated is a deliberate decoy. It verifies that the token parser reads only arrays passed to URL::defaults(). Without a comment, a later reader can remove it and silently drop that coverage.

♻️ Proposed change
+        // Decoy array. The generator must not harvest arrays that are not
+        // arguments to URL::defaults().
         $unrelated = ['neighbor' => 'not-a-default'];
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Wayfinder/Fixtures/Middleware/UrlDefaultsMiddleware.php` around lines
27 - 34, Add a brief comment explaining that the `$unrelated` array is a
deliberate decoy used to verify the token parser only reads arrays passed to
`URL::defaults()`. Keep the decoy and its existing value unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@docs/plans/2026-08-08-1709-wayfinder-correctness-generation-parity-and-bounded-lifecycles.md`:
- Line 366: Update the Markdown spans describing JavaScript replacement tokens
at both occurrences of the backtick token, including the text near “this also
prevents” and the corresponding occurrence later in the document. Replace the
ambiguous single-backtick markup with an unambiguous double-backtick span or
equivalent escaped form, while preserving the literal token text and surrounding
explanation.

In `@src/testbench/src/Concerns/HandlesRoutes.php`:
- Around line 176-199: Update syncTestbenchRoutes and its state tracking so each
defineCacheRoutes(..., false) call synchronizes newly written uncached route
files after application reloads instead of returning solely because
synchronization previously ran. Track which route files have already been
synchronized or otherwise load only the newly created file, preserving existing
synchronization for previously seen files. Add coverage for two calls that
verifies routes from both files resolve.

In `@src/wayfinder/resources/js/wayfinder.ts`:
- Around line 52-55: Update the parameter-decoding logic in wayfinder.ts so
route parameters retain the encoded forms of %3F, %26, %23, and %25 instead of
converting them to URL delimiters or additional escapes. Preserve decoding for
other supported characters while ensuring formatted path parameters cannot
introduce query strings, fragments, or encoded slashes.

In `@src/wayfinder/src/TypeScript.php`:
- Around line 121-126: Update the regex patterns in cleanUp’s $regexReplacements
to handle platform-independent line endings, replacing literal newline matching
in the arrow-function and blank-line normalization rules with \R-based matching.
Preserve the existing replacement formatting and other cleanup rules.

---

Outside diff comments:
In `@src/wayfinder/resources/js/wayfinder.ts`:
- Around line 170-186: Update the return type of applyUrlDefaults so null or
undefined inputs are typed as UrlDefaults, while non-null object inputs retain
their existing object type. Preserve the current runtime default-merging
behavior and use a conditional return type that distinguishes nullish from
non-null T.

---

Nitpick comments:
In `@tests/Wayfinder/Fixtures/Middleware/UrlDefaultsMiddleware.php`:
- Around line 27-34: Add a brief comment explaining that the `$unrelated` array
is a deliberate decoy used to verify the token parser only reads arrays passed
to `URL::defaults()`. Keep the decoy and its existing value unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a5a11771-7e4d-445d-aa6e-dd5a2fb30e99

📥 Commits

Reviewing files that changed from the base of the PR and between 089a8b3 and 6c56016.

📒 Files selected for processing (90)
  • .github/workflows/tests.yml
  • composer.json
  • 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
  • docs/plans/2026-08-08-1709-wayfinder-correctness-generation-parity-and-bounded-lifecycles.md
  • docs/todo.md
  • package.json
  • src/boost/docs/documentation.md
  • src/boost/docs/testing.md
  • src/boost/docs/wayfinder.md
  • src/filesystem/src/Filesystem.php
  • src/foundation/src/Application.php
  • src/foundation/src/Testing/Concerns/InteractsWithTestCaseLifecycle.php
  • src/foundation/src/Testing/TestCase.php
  • src/foundation/src/Testing/WithCachedConfig.php
  • src/foundation/src/Testing/WithCachedRoutes.php
  • src/routing/src/RouteUrlGenerator.php
  • src/routing/src/UrlGenerator.php
  • src/testbench/src/Concerns/CreatesApplication.php
  • src/testbench/src/Concerns/HandlesRoutes.php
  • src/testbench/src/TestCase.php
  • src/wayfinder/README.md
  • src/wayfinder/composer.json
  • src/wayfinder/package.json
  • src/wayfinder/resources/boost/skills/wayfinder-development/SKILL.blade.php
  • src/wayfinder/resources/function-arguments.blade.ts
  • src/wayfinder/resources/js/wayfinder.ts
  • src/wayfinder/resources/method.blade.ts
  • src/wayfinder/resources/multi-method.blade.ts
  • src/wayfinder/src/BindingResolver.php
  • src/wayfinder/src/GenerateCommand.php
  • src/wayfinder/src/Parameter.php
  • src/wayfinder/src/Route.php
  • src/wayfinder/src/TypeScript.php
  • src/wayfinder/tests/CamelCaseRouteParameter.test.ts
  • src/wayfinder/tests/DefaultParameters.test.ts
  • src/wayfinder/tests/DisallowedMethodNames.test.ts
  • src/wayfinder/tests/GeneratedOutput.test.ts
  • src/wayfinder/tests/IdentifierCollisions.test.ts
  • src/wayfinder/tests/InvokablePlusController.test.ts
  • src/wayfinder/tests/KeyController.test.ts
  • src/wayfinder/tests/ModelBindingController.test.ts
  • src/wayfinder/tests/OptionalController.test.ts
  • src/wayfinder/tests/QueryParams.test.ts
  • src/wayfinder/tests/RepeatedNamespaceController.test.ts
  • src/wayfinder/tests/StorageRoute.test.ts
  • src/wayfinder/tests/TwoRoutesSameAction.test.ts
  • src/wayfinder/tests/UrlDefaultsController.test.ts
  • src/wayfinder/tests/build.ts
  • src/wayfinder/tests/generate.php
  • src/wayfinder/tsconfig.json
  • tests/Broadcasting/PackageMetadataTest.php
  • tests/FacadeDocumenter/PackageMetadataTest.php
  • tests/Filesystem/FilesystemTest.php
  • tests/Foundation/PackageMetadataTest.php
  • tests/Foundation/Testing/WithCachedStateTest.php
  • tests/Integration/Console/EnvironmentEncryptCommandTest.php
  • tests/Integration/Foundation/Console/ConfigPublishCommandWithoutMergedConfigurationTest.php
  • tests/Mail/PackageMetadataTest.php
  • tests/Passkeys/PackageMetadataTest.php
  • tests/RateLimiter/Fixtures/RateLimiterStoreContract.php
  • tests/Routing/PackageMetadataTest.php
  • tests/Routing/RoutingUrlGeneratorTest.php
  • tests/Scout/PackageMetadataTest.php
  • tests/Testbench/Concerns/DefineCacheRoutesTest.php
  • tests/Testbench/Concerns/HandlesRoutesTest.php
  • tests/Testbench/Concerns/WithCachedStateTest.php
  • tests/Testbench/Integrations/ApplicationProvidersWithDisabledServicesTest.php
  • tests/Testbench/WithWorkbenchTest.php
  • tests/Wayfinder/BindingResolverTest.php
  • tests/Wayfinder/Fixtures/Controllers/BarrelCollisionController.php
  • tests/Wayfinder/Fixtures/Controllers/BarrelCollisionController/NestedController.php
  • tests/Wayfinder/Fixtures/Controllers/DisallowedMethodNameController.php
  • tests/Wayfinder/Fixtures/Controllers/DomainController.php
  • tests/Wayfinder/Fixtures/Controllers/Index.php
  • tests/Wayfinder/Fixtures/Controllers/InvokablePlusController.php
  • tests/Wayfinder/Fixtures/Controllers/KeyController.php
  • tests/Wayfinder/Fixtures/Controllers/ModelBindingController.php
  • tests/Wayfinder/Fixtures/Controllers/OptionalController.php
  • tests/Wayfinder/Fixtures/Controllers/ReverseBarrelCollisionController.php
  • tests/Wayfinder/Fixtures/Controllers/ReverseBarrelCollisionController/NestedController.php
  • tests/Wayfinder/Fixtures/Controllers/TwoRoutesSameActionController.php
  • tests/Wayfinder/Fixtures/Controllers/UrlDefaultsController.php
  • tests/Wayfinder/Fixtures/Middleware/UrlDefaultsMiddleware.php
  • tests/Wayfinder/Fixtures/Models/User.php
  • tests/Wayfinder/Fixtures/routes.php
  • tests/Wayfinder/GenerateCommandTest.php
  • tests/Wayfinder/PackageMetadataTest.php
  • tests/Wayfinder/PruneStaleFilesTest.php
  • tests/Wayfinder/RouteTest.php
💤 Files with no reviewable changes (1)
  • src/wayfinder/tests/CamelCaseRouteParameter.test.ts

Comment thread src/testbench/src/Concerns/HandlesRoutes.php
Comment thread src/wayfinder/resources/js/wayfinder.ts Outdated
Comment thread src/wayfinder/src/TypeScript.php
Escape percent, query, fragment, and brace delimiters while values are still known to be route parameters. This prevents later URL and placeholder passes from reinterpreting user data while preserving structural query and fragment syntax.

Add regressions for named, positional, Stringable, enum-backed, domain, configured-root, brace, and query-consumption behavior.
Retain encoded route delimiters in generated paths so TypeScript cannot turn parameter data into URL syntax. Correct exact nullish default return types without widening union inputs.

Make the neighboring-array parser fixture load-bearing and extend generated runtime coverage for dynamic domains, literal delimiters, and omitted decoy parameters.
Reset the per-test synchronization flag after an application reload discards its callback registry. Each later uncached route definition can then register the callback needed by the new application.

Cover two successive stash route definitions and verify that both accumulated route files remain dispatchable after the second reload.
Treat storage paths as raw keys until the final URL owner is known. Hypervel-owned local, FTP, configured S3, and GCS URLs now encode once while native S3 and delegated adapters keep their existing ownership.

Remove the superseded temporary local pre-encoding now that Routing protects parameter data. Preserve nested separators, normalize leading separators, keep literal percent escapes as filename data, and cover signed upload and download round trips.

Remove the obsolete documentation warning that required callers to choose URL-safe local filenames.
Add routing-28, wayfinder-23, and filesystem-18 to the dependency index and completed audit ledger. Record the shared parameter-data boundary, ordinary storage URL ownership, removed temporary URL workaround, lifecycle coverage, and bounded runtime costs.

Update the completed Wayfinder assessment so future audits preserve the corrected contracts without restoring local encoders or pre-encoded input detection.
Specify the final Routing, Wayfinder, Testbench, and Filesystem ownership model after review. Include the exact delimiter map, raw storage path contract, leading-separator handling, signed path round trips, performance costs, regression coverage, durable IDs, and rejected workaround machinery.

Keep the document as the concise final design a fresh session can implement without relying on review history.
@binaryfire

Copy link
Copy Markdown
Member Author

@coderabbitai @greptile-apps Review follow-up is complete.

  • Route parameter values now escape %, ?, #, {, and } at the shared PHP substitution boundary, before the values can become query, fragment, percent-escape, or placeholder syntax. Generated Wayfinder URLs use the same contract. & and / remain valid path data.
  • Filesystem URL handling now encodes raw storage keys only at Hypervel-owned URL construction boundaries. Temporary local routes no longer pre-encode values, and delegated adapters such as native S3 keep ownership of their own encoding.
  • Testbench now re-arms uncached route synchronization when an application reload discards the previous callback registry. Successive route definitions remain available after reloads without adding a per-file registry.
  • applyUrlDefaults() now handles exact nullish inputs with a non-distributive conditional type while preserving generated union inference. The parser decoy is also load-bearing.
  • The replacement-token Markdown is corrected. The \R suggestion is intentionally not applied because supported Swoole checkouts are LF-only and the cleanup pipeline consistently uses PHP_EOL. Biome is not applied to Blade TypeScript templates because they are not standalone TypeScript inputs; generated output is validated instead.

composer fix, the Wayfinder frontend checks, and focused Routing, Filesystem, and Testbench regressions are green.

@binaryfire

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== Changed files ==='
git diff --name-only HEAD^ HEAD

printf '%s\n' '=== Relevant diff excerpts ==='
git diff HEAD^ HEAD -- \
  src/routing/src/UrlGenerator.php \
  src/routing/src/RouteUrlGenerator.php \
  src/filesystem \
  src/testbench \
  src/wayfinder/resources/js/wayfinder.ts \
  src/wayfinder/resources \
  src/wayfinder/src \
  docs \
  tests/Routing \
  tests/Filesystem \
  tests/Testbench \
  tests/Wayfinder \
  | sed -n '1,2200p'

printf '%s\n' '=== Relevant test names and assertions ==='
rg -n -C 3 \
  '(%|\\\?|#|\\\{|\\\}|applyUrlDefaults|cached|synchron|encoding|encode|replacement|markdown|PHP_EOL)' \
  tests/Routing tests/Filesystem tests/Testbench tests/Wayfinder src/wayfinder/tests \
  || true

Length of output: 192160


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== Follow-up commit ==='
git show --no-ext-diff --format=fuller --stat HEAD

printf '%s\n' '=== Follow-up changed paths ==='
git diff-tree --no-commit-id --name-only -r HEAD

printf '%s\n' '=== Follow-up patch ==='
git show --no-ext-diff --format= --find-renames --find-copies HEAD | sed -n '1,1800p'

printf '%s\n' '=== Focused implementation references ==='
rg -n -C 8 \
  '(rawurlencode|urlencode|formatRouteParameter|applyUrlDefaults|routesSynchronized|SyncTestbenchCachedRoutes|replaceNamedParameters|replaceRouteParameters|%7B|%7D|PHP_EOL)' \
  src/routing/src src/filesystem/src src/testbench/src src/wayfinder/resources src/wayfinder/src \
  || true

printf '%s\n' '=== Focused regression test references ==='
rg -n -C 8 \
  '(report\?v2|a\{x\}b|100%|applyUrlDefaults|reload|synchron|S3|storage key|replacement token|PHP_EOL)' \
  tests/Routing/RoutingUrlGeneratorTest.php tests/Filesystem tests/Testbench/Concerns tests/Wayfinder src/wayfinder/tests \
  || true

Length of output: 121311


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== Testbench synchronization implementation ==='
nl -ba src/testbench/src/Concerns/HandlesRoutes.php | sed -n '120,215p'

printf '%s\n' '=== Testbench direct regression tests ==='
rg -n -C 12 \
  '(successive|refreshApplication|defineCacheRoutes|syncTestbenchRoutesHasRun|synchronization|dispatch)' \
  tests/Testbench/Concerns/DefineCacheRoutesTest.php \
  tests/Testbench/Concerns/HandlesRoutesTest.php \
  || true

printf '%s\n' '=== Filesystem URL and temporary-route regressions ==='
rg -n -C 8 \
  '(encode|raw|temporary|signed|report%2F|leading|separator|Storage::url)' \
  tests/Filesystem/AwsS3V3AdapterTest.php \
  tests/Filesystem/FilesystemAdapterTest.php \
  tests/Filesystem/FilesystemManagerTest.php \
  || true

Length of output: 1168


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== Testbench synchronization implementation ==='
sed -n '120,215p' src/testbench/src/Concerns/HandlesRoutes.php

printf '%s\n' '=== Testbench direct regression tests ==='
rg -n -C 12 \
  '(successive|refreshApplication|defineCacheRoutes|syncTestbenchRoutesHasRun|synchronization|dispatch)' \
  tests/Testbench/Concerns/DefineCacheRoutesTest.php \
  tests/Testbench/Concerns/HandlesRoutesTest.php \
  || true

printf '%s\n' '=== Filesystem URL and temporary-route regressions ==='
rg -n -C 8 \
  '(encode|raw|temporary|signed|report%2F|leading|separator|Storage::url)' \
  tests/Filesystem/AwsS3V3AdapterTest.php \
  tests/Filesystem/FilesystemAdapterTest.php \
  tests/Filesystem/FilesystemManagerTest.php \
  || true

Length of output: 49434


@binaryfire: Verified. The follow-up changes address the reviewed concerns.

  • Routing escapes %, ?, #, {, and } before parameter substitution. The regression tests cover named, positional, domain, root-default, Stringable, and enum values.
  • Wayfinder preserves the same delimiter contract. applyUrlDefaults() uses the non-distributive nullish conditional type, and type tests cover exact nullish inputs and unions.
  • Filesystem URL generation encodes raw keys at Hypervel-owned boundaries. Tests cover local, FTP, configured S3, and native S3 paths.
  • Testbench resets $syncTestbenchRoutesHasRun after application reload. The regression test verifies that two uncached route definitions remain dispatchable.

The sandbox did not execute the reported test commands. Static inspection found the corresponding implementations and regression coverage. No further follow-up findings.

🐇 ✅


✏️ Learnings added
Learnt from: binaryfire
URL: https://github.com/hypervel/components-backup/pull/7

Timestamp: 2026-08-09T12:55:36.069Z
Learning: In `src/routing/src/RouteUrlGenerator.php`, route parameter values must escape literal `%`, `?`, `#`, `{`, and `}` before named, positional, domain, or configured-root placeholder substitution. Keep `&` and `/` as path data. This prevents parameter data from becoming percent escapes, query/fragment delimiters, or route placeholders.

Learnt from: binaryfire
URL: https://github.com/hypervel/components-backup/pull/7

Timestamp: 2026-08-09T12:55:36.069Z
Learning: In `src/testbench/src/Concerns/HandlesRoutes.php`, application reload clears after-created callbacks. Reset `$syncTestbenchRoutesHasRun` in the reload `finally` block so later uncached route definitions register replacement synchronization callbacks. Do not use a per-file callback registry.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

You are interacting with an AI system.

@binaryfire
binaryfire merged commit 5c41e9d into 0.4 Aug 9, 2026
40 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