Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
cd92fa1
Fix Conditionable proxy truthiness
binaryfire Jul 12, 2026
54dc9d4
Test non-boolean Conditionable proxy values
binaryfire Jul 12, 2026
cc09540
Add return types to Conditionable tests
binaryfire Jul 12, 2026
d201e30
Declare the log Conditionable dependency
binaryfire Jul 12, 2026
d4f9d13
Isolate the Testbench package manifest
binaryfire Jul 12, 2026
df1d146
Test Testbench package manifest restoration
binaryfire Jul 12, 2026
840b45a
Harden route cache test preconditions
binaryfire Jul 12, 2026
fe4e638
Record the Conditionable audit
binaryfire Jul 12, 2026
39102d0
Stabilize remote manifest restoration coverage
binaryfire Jul 13, 2026
139b61b
Harden Macroable closure dispatch
binaryfire Jul 13, 2026
010bd42
Expand Macroable callable regression coverage
binaryfire Jul 13, 2026
7efb9dc
Complete existing framework macro resets
binaryfire Jul 13, 2026
8bffaff
Add static reset hooks to HTTP macro surfaces
binaryfire Jul 13, 2026
4b72880
Reset mutable Request state between tests
binaryfire Jul 13, 2026
51eaa8a
Add macro cleanup to NotificationFake
binaryfire Jul 13, 2026
be040f4
Register framework macro resets centrally
binaryfire Jul 13, 2026
9001d61
Cover centralized macro and Request cleanup
binaryfire Jul 13, 2026
15655ce
Declare direct Macroable package dependencies
binaryfire Jul 13, 2026
01b8dd5
Clarify framework macro cleanup in tests
binaryfire Jul 13, 2026
9a98445
Record the completed Macroable audit
binaryfire Jul 13, 2026
037fee8
Correct Collections package metadata
binaryfire Jul 13, 2026
7d4aafa
Improve Arr contracts and type inference
binaryfire Jul 13, 2026
fc69520
Expand Arr regression coverage
binaryfire Jul 13, 2026
6e6bc50
Correct enum helper default handling
binaryfire Jul 13, 2026
a32b787
Improve conditional helper inference
binaryfire Jul 13, 2026
fe851f5
Extend shared collection contracts
binaryfire Jul 13, 2026
52cb775
Correct eager collection behavior
binaryfire Jul 13, 2026
646498b
Correct lazy collection behavior
binaryfire Jul 13, 2026
f9b1c4a
Expand shared collection behavior coverage
binaryfire Jul 13, 2026
fb1edce
Expand lazy collection behavior coverage
binaryfire Jul 13, 2026
d972c9f
Preserve lazy evaluation coverage
binaryfire Jul 13, 2026
59cffbc
Standardize collection static-state tests
binaryfire Jul 13, 2026
e577797
Use the framework collection test base
binaryfire Jul 13, 2026
6997bc5
Standardize higher-order proxy tests
binaryfire Jul 13, 2026
7063622
Update the collections guide
binaryfire Jul 13, 2026
14e2535
Update collection helper documentation
binaryfire Jul 13, 2026
cf11d43
Document Collections differences from Laravel
binaryfire Jul 13, 2026
40aa706
Record the completed Collections audit
binaryfire Jul 13, 2026
2ed3658
Preserve console contracts during Composer scripts
binaryfire Jul 13, 2026
e03b8a6
Refine macro and collection fallbacks
binaryfire Jul 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

27 changes: 15 additions & 12 deletions docs/plans/2026-07-12-framework-coroutine-state-lifecycle-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -857,11 +857,11 @@ A package checkbox means the entire cycle below is finished, not merely that fil

### Branch and authorization model

This audit targets the repository's `0.4` integration branch. Each completed package or cross-package work unit uses a dedicated branch from the latest owner-approved `0.4` state and is reviewed as its own pull request. Name the branch for the work unit, such as `audit/contracts-coroutine-state-lifecycle`. Do not perform audit work directly on `0.4`.
This audit targets the repository's `0.4` integration branch. Start an audit branch from the latest owner-approved `0.4` state and do not perform audit work directly on `0.4`. The owner decides pull-request boundaries: one audit branch may accumulate one or several completed packages or cross-package work units before the owner determines that it contains enough coherent work for a pull request.

The owner has explicitly authorized coherent commits and pushes after each completed package or cross-package work unit for this audit. That authorization does not include opening, merging, or closing pull requests, and it does not automatically carry into a future audit run. Do not begin the next work unit until the preceding pull request has been integrated into `0.4` and the next branch includes that integrated state, unless the owner explicitly authorizes a stacked branch.
The owner has explicitly authorized coherent commits after each completed package or cross-package work unit for this audit, following the owner pre-commit checkpoint below. Continue the next package on the same active audit branch after those commits unless the owner directs otherwise. Do not push, open, merge, or close a pull request until the owner explicitly requests it, and do not infer that a completed package should become its own pull request.

A resumed session verifies the active branch, the last pushed package, and whether newer base-branch changes affect audited assumptions before editing. Never infer a different target branch from a hosting service's default branch.
A resumed session verifies the active branch, the last completed package commits, and whether an owner-requested base update affects audited assumptions before editing. Never infer a different target branch from a hosting service's default branch.

### 1. Audit

Expand Down Expand Up @@ -936,7 +936,7 @@ Request an independent review of the complete diff and validation. Continue unti

### 9. Prepare final audit records

Update the companion-ledger work-unit block with implemented changes, cross-package revalidation, tests/gates, and review sign-off. Its heading must match the pull-request title so the corresponding repository history is easy to locate without duplicating branch, pull-request, or commit references. Prepare the routing index, cross-package dependency index, and package-checklist changes in this plan. Remove wording that describes abandoned designs.
Update the companion-ledger work-unit block with implemented changes, cross-package revalidation, tests/gates, and review sign-off. Give it a concise work-unit heading; multiple ledger work units may later be included in one owner-selected pull request. Prepare the routing index, cross-package dependency index, and package-checklist changes in this plan. Remove wording that describes abandoned designs and do not duplicate branch, pull-request, or commit references in the audit documents.

### 10. Owner pre-commit checkpoint

Expand All @@ -949,11 +949,11 @@ After every code change is complete, all gates are green, the fresh self-review

Do not create any source, test, documentation, ledger, or bookkeeping commit before that explicit approval. If the owner requests changes, implement them, rerun proportionate validation and review, update the summary, notify again, and wait for approval.

### 11. Commit and push
### 11. Commit

Commit source, tests, and documentation in as many coherent commits as useful, with detailed bodies. Make one final audit-bookkeeping commit containing the ledger entry and this plan's checklist/index updates. Do not duplicate branch, pull-request, commit, or merge references in the audit documents; repository history already owns that information. A clean audit with no executable or documentation correction has only this bookkeeping commit.

Push the complete commit set only after the package is green and signed off. The checked box becomes authoritative when that push succeeds. If the push fails, do not begin the next package; repair the push or revert the unpushed completion bookkeeping so the branch does not claim externally completed work.
The checked box becomes authoritative when the final bookkeeping commit succeeds. Continue on the same audit branch after the owner approves the next work unit. Push only when the owner requests it, normally when the owner decides the accumulated work is ready for a pull request.

## Cross-package work units

Expand All @@ -974,7 +974,7 @@ An exceptionally large shared work unit may receive its own linked detail plan w

This compact index routes the completed-work history that must be consulted with the full plan after compaction. Detailed history remains in the [companion ledger](2026-07-12-framework-coroutine-state-lifecycle-audit-ledger.md).

- **Active package or work unit:** none; contracts work is complete and awaiting integration
- **Active package or work unit:** `reflection`
- **Ledger entries required for the active work:** none
- **Pending revalidation carried into the active work:** none

Expand All @@ -990,6 +990,9 @@ Add one row only for a shared finding or changed lower-level assumption that ano
| `view-01` | `view` | `contracts`, `foundation`; later full `view` and `foundation` audits | `Harden framework contracts and request-scoped state`; shared finding `view-01` |
| `filesystem-01` | `filesystem` | `contracts`; later full `filesystem` audit | `Harden framework contracts and request-scoped state`; shared finding `filesystem-01` |
| `queue-01` | `queue` | `contracts`; later full `queue` audit | `Harden framework contracts and request-scoped state`; shared finding `queue-01` |
| `testbench-01` | `testbench` | `foundation`; later full `testbench` and `foundation` audits | `Restore Conditionable proxy truthiness`; shared finding `testbench-01` |
| `http-01` | `http` | `macroable`, `testing`; later full `http` and `testing` audits | `Complete Macroable callable and test-state handling`; shared finding `http-01` |
| `console-01` | `console` | `contracts`; later full `console` audit | `Preserve typed console contracts during Composer scripts`; shared finding `console-01` |

## Package checklist

Expand All @@ -1013,9 +1016,9 @@ The order is lower-level first where practical. Hypervel has cross-cutting depen
### Core semantics and long-lived state

- [x] `contracts`
- [ ] `conditionable`
- [ ] `macroable`
- [ ] `collections`
- [x] `conditionable`
- [x] `macroable`
- [x] `collections`
- [ ] `reflection`
- [ ] `config`
- [ ] `container`
Expand Down Expand Up @@ -1106,7 +1109,7 @@ The order is lower-level first where practical. Hypervel has cross-cutting depen

### Before each package

- confirm the previous work-unit pull request is integrated into `0.4`, then create the current work-unit branch from that latest integrated state unless the owner explicitly authorized stacking;
- confirm the previous work unit is committed and the owner has authorized continuing on the active audit branch;
- set the active-package routing fields and list every exact ledger entry required for the work;
- read the current package's existing companion-ledger entry, if any, plus only the cross-referenced entries named by the routing/dependency indexes;
- check whether a completed lower-level package changed assumptions used here;
Expand All @@ -1128,7 +1131,7 @@ The order is lower-level first where practical. Hypervel has cross-cutting depen
- code review is signed off;
- every accepted hot-path regression, if any, received explicit owner approval before implementation;
- the owner reviewed the post-sign-off summary and explicitly approved committing;
- commits were pushed;
- the final bookkeeping commit succeeded;
- routing and dependency indexes reflect the next active work and every pending revalidation;
- any affected completed package was revalidated and its companion-ledger entry amended.

Expand Down
119 changes: 52 additions & 67 deletions src/boost/docs/collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ $upper = $collection->toUpper();

Typically, you should declare collection macros in the `boot` method of a [service provider](/docs/{{version}}/providers).

If you register a macro inside a test, flush the macro state before the test finishes. Macros are stored globally for the life of the PHP process.
Macros are stored globally for the life of the PHP process. Hypervel automatically flushes framework-owned collection macros after every test. If your application or package defines its own macroable class, add it to your [test-state cleanup](/docs/{{version}}/testing#macro-state).

<a name="macro-arguments"></a>
#### Macro Arguments
Expand Down Expand Up @@ -122,8 +122,6 @@ For the majority of the remaining collection documentation, we'll discuss each m
[combine](#method-combine)
[concat](#method-concat)
[contains](#method-contains)
[containsManyItems](#method-containsmanyitems)
[containsOneItem](#method-containsoneitem)
[containsStrict](#method-containsstrict)
[count](#method-count)
[countBy](#method-countBy)
Expand Down Expand Up @@ -209,6 +207,7 @@ For the majority of the remaining collection documentation, we'll discuss each m
[random](#method-random)
[range](#method-range)
[reduce](#method-reduce)
[reduceInto](#method-reduce-into)
[reduceSpread](#method-reduce-spread)
[reduceWithKeys](#method-reduce-with-keys)
[reject](#method-reject)
Expand Down Expand Up @@ -605,68 +604,6 @@ The `contains` method uses "loose" comparisons when checking item values, meanin

For the inverse of `contains`, see the [doesntContain](#method-doesntcontain) method.

<a name="method-containsmanyitems"></a>
#### `containsManyItems()` {.collection-method}

The `containsManyItems` method determines whether the collection contains more than one item:

```php
collect([])->containsManyItems();

// false

collect(['first'])->containsManyItems();

// false

collect(['first', 'second'])->containsManyItems();

// true
```

When using the `Collection` class, you may pass a closure to determine whether the collection contains more than one item matching a given truth test:

```php
$collection = collect(['ant', 'bear', 'cat', 'deer']);

$collection->containsManyItems(function (string $value) {
return strlen($value) === 4;
});

// true
```

<a name="method-containsoneitem"></a>
#### `containsOneItem()` {.collection-method}

The `containsOneItem` method determines whether the collection contains exactly one item:

```php
collect([])->containsOneItem();

// false

collect(['first'])->containsOneItem();

// true

collect(['first', 'second'])->containsOneItem();

// false
```

You may pass a closure to determine whether the collection contains exactly one item matching a given truth test:

```php
$collection = collect(['ant', 'bear', 'cat']);

$collection->containsOneItem(function (string $value) {
return strlen($value) === 4;
});

// true
```

<a name="method-containsstrict"></a>
#### `containsStrict()` {.collection-method}

Expand Down Expand Up @@ -2634,6 +2571,17 @@ $random->all();
// [2, 4, 5] - (retrieved randomly)
```

Pass `true` as the second argument to preserve the original keys when retrieving multiple items:

```php
$random = collect(['desk' => 100, 'chair' => 50, 'lamp' => 25])
->random(2, preserveKeys: true);

$random->keys()->all();

// ['desk', 'lamp'] - (retrieved randomly)
```

If the collection instance has fewer items than requested, the `random` method will throw an `InvalidArgumentException`.

The `random` method also accepts a closure, which will receive the current collection instance:
Expand Down Expand Up @@ -2708,6 +2656,35 @@ $collection->reduce(function (int $carry, int $value, string $key) use ($ratio)
// 4264
```

<a name="method-reduce-into"></a>
#### `reduceInto()` {.collection-method}

The `reduceInto` method reduces the collection to a single value by mutating the given initial value. Unlike the `reduce` method, the given callback does not need to return the accumulated value:

```php
class OrderStats
{
public int $total = 0;

public int $count = 0;
}

$orders = collect([
['amount' => 100],
['amount' => 250],
['amount' => 50],
]);

$stats = $orders->reduceInto(new OrderStats, function (OrderStats $stats, array $order) {
$stats->total += $order['amount'];
$stats->count++;
});

$stats->total;

// 400
```

<a name="method-reduce-spread"></a>
#### `reduceSpread()` {.collection-method}

Expand Down Expand Up @@ -3452,6 +3429,15 @@ $collection->sum(function (array $product) {
// 6
```

The callback receives the item key as its second argument:

```php
$total = collect(['standard' => 100, 'priority' => 200])
->sum(fn (int $price, string $type) => $type === 'priority' ? $price + 25 : $price);

// 325
```

<a name="method-take"></a>
#### `take()` {.collection-method}

Expand Down Expand Up @@ -4425,8 +4411,6 @@ Almost all methods available on the `Collection` class are also available on the
[combine](#method-combine)
[concat](#method-concat)
[contains](#method-contains)
[containsManyItems](#method-containsmanyitems)
[containsOneItem](#method-containsoneitem)
[containsStrict](#method-containsstrict)
[count](#method-count)
[countBy](#method-countBy)
Expand Down Expand Up @@ -4504,6 +4488,7 @@ Almost all methods available on the `Collection` class are also available on the
[random](#method-random)
[range](#method-range)
[reduce](#method-reduce)
[reduceInto](#method-reduce-into)
[reduceSpread](#method-reduce-spread)
[reduceWithKeys](#method-reduce-with-keys)
[reject](#method-reject)
Expand Down
28 changes: 24 additions & 4 deletions src/boost/docs/helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ $flattened = Arr::dot($array);
<a name="method-array-every"></a>
#### `Arr::every()` {.collection-method}

The `Arr::every` method ensures that all values in the array pass a given truth test:
The `Arr::every` method ensures that all values in an iterable pass a given truth test:

```php
use Hypervel\Support\Arr;
Expand All @@ -418,6 +418,20 @@ Arr::every($array, fn ($i) => $i > 2);
// false
```

The method also accepts any iterable, including generators:

```php
$values = function () {
yield 1;
yield 2;
yield 3;
};

Arr::every($values(), fn (int $value) => $value > 0);

// true
```

<a name="method-array-except"></a>
#### `Arr::except()` {.collection-method}

Expand Down Expand Up @@ -482,7 +496,7 @@ $exists = Arr::exists($array, 'salary');
<a name="method-array-first"></a>
#### `Arr::first()` {.collection-method}

The `Arr::first` method returns the first element of an array passing a given truth test:
The `Arr::first` method returns the first element of an iterable passing a given truth test:

```php
use Hypervel\Support\Arr;
Expand All @@ -496,6 +510,8 @@ $first = Arr::first($array, function (int $value, int $key) {
// 200
```

The first argument may be any iterable, including a generator.

A default value may also be passed as the third parameter to the method. This value will be returned if no value passes the truth test:

```php
Expand Down Expand Up @@ -754,7 +770,7 @@ $keyed = Arr::keyBy($array, 'product_id');
<a name="method-array-last"></a>
#### `Arr::last()` {.collection-method}

The `Arr::last` method returns the last element of an array passing a given truth test:
The `Arr::last` method returns the last element of an iterable passing a given truth test:

```php
use Hypervel\Support\Arr;
Expand All @@ -776,6 +792,8 @@ use Hypervel\Support\Arr;
$last = Arr::last($array, $callback, $default);
```

The first argument may be any iterable, including a generator.

<a name="method-array-map"></a>
#### `Arr::map()` {.collection-method}

Expand Down Expand Up @@ -1164,7 +1182,7 @@ $value = Arr::sole($array, fn (string $value) => $value === 'Desk');
<a name="method-array-some"></a>
#### `Arr::some()` {.collection-method}

The `Arr::some` method ensures that at least one of the values in the array passes a given truth test:
The `Arr::some` method ensures that at least one of the values in an iterable passes a given truth test:

```php
use Hypervel\Support\Arr;
Expand All @@ -1176,6 +1194,8 @@ Arr::some($array, fn ($i) => $i > 2);
// true
```

The first argument may be any iterable, including a generator.

<a name="method-array-sort"></a>
#### `Arr::sort()` {.collection-method}

Expand Down
2 changes: 1 addition & 1 deletion src/boost/docs/http-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ Once your macro has been configured, you may invoke it from anywhere in your app
$response = Http::github()->get('/');
```

Macros are stored globally for the life of the PHP process. If you register a macro inside a test, flush the macro state before the test finishes.
Macros are stored globally for the life of the PHP process. Hypervel automatically flushes framework-owned HTTP client macros after every test. If your application or package defines its own macroable class, add it to your [test-state cleanup](/docs/{{version}}/testing#macro-state).

<a name="testing"></a>
## Testing
Expand Down
2 changes: 1 addition & 1 deletion src/boost/docs/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -1121,4 +1121,4 @@ return response()->caps('foo');
```

> [!NOTE]
> Macros register on a static property and persist for the life of the Swoole worker. If you register a macro inside a test, call `Hypervel\Routing\ResponseFactory::flushState()` or `Response::flushMacros()` before the next test runs so the macro doesn't leak into other tests.
> Macros register on a static property and persist for the life of the Swoole worker. Hypervel automatically flushes framework-owned response macros after every test. If your application or package defines its own macroable class, add it to your [test-state cleanup](/docs/{{version}}/testing#macro-state).
14 changes: 14 additions & 0 deletions src/collections/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Collections for Hypervel
===

[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/hypervel/collections)

Ported from: https://github.com/laravel/framework/tree/13.x/src/Illuminate/Collections

## Differences From Laravel

Laravel's deprecated `containsOneItem()` and `containsManyItems()` aliases are intentionally not ported. Use `hasSole()` and `hasMany()` instead.

`Enumerable::random()` exposes the optional `preserveKeys` argument supported by both concrete collection implementations and reports the preserved key type accurately. Laravel exposes this argument only on the concrete classes and always reports integer keys through the contract.

`Arr::push()` accepts arrays only. Laravel also advertises `ArrayAccess`, but dot notation requires nested by-reference mutation that `ArrayAccess` cannot provide.
Loading