Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c0667bd
Add Hypervel PHPStan rules plan
binaryfire Nov 12, 2026
5136e5c
Plan actionable unsupported-call diagnostics
binaryfire Nov 12, 2026
9d39e0f
Merge branch '0.4' into feature/phpstan-hypervel-rules
binaryfire Nov 12, 2026
b0df385
Keep facade roots within their container resolution lifetime
binaryfire Nov 12, 2026
c34dafb
Preserve return types through borrowed resource callbacks
binaryfire Nov 12, 2026
230ad23
Update the rules plan for completed runtime prerequisites
binaryfire Nov 12, 2026
29d1494
Report calls to unsupported implementations through native methods an…
binaryfire Nov 12, 2026
af10668
Check restricted calls against shared lifetimes and execution contexts
binaryfire Nov 12, 2026
737e79a
Update the rules plan for completed context and attribute analysis
binaryfire Nov 12, 2026
7a51de8
Record immutable date creation as a separate framework change
binaryfire Nov 12, 2026
634b830
Require driver-neutral Connection instances from database resolvers
binaryfire Nov 12, 2026
7826fec
Use a named syslog facility in shipped logging configuration
binaryfire Nov 12, 2026
e5e6002
Check borrowed resources, transaction ownership and framework usage
binaryfire Nov 12, 2026
14156eb
Update the rules plan through binding-cycle detection
binaryfire Nov 12, 2026
4c4c72d
Share cancellation receiver analysis and source method lookup
binaryfire Nov 13, 2026
81e4571
Detect swallowed cancellation and unsafe worker initialization patterns
binaryfire Nov 13, 2026
e96b46b
Update rules plan through cancellation and initialization checks
binaryfire Nov 13, 2026
18d85f1
Document lifecycle, cancellation and authoring diagnostics
binaryfire Nov 13, 2026
89e1555
Align development guidance with enforced lifecycle rules
binaryfire Nov 13, 2026
6d00806
Expose the working vendor path used by Testbench runtime copies
binaryfire Nov 13, 2026
a1fb7bd
Reuse package analysis results across disposable Testbench boots
binaryfire Nov 13, 2026
c329d6f
Clarify PHPStan documentation with usage-first examples
binaryfire Nov 13, 2026
fa56a45
Contain cleanup and logging failures in transport coroutines
binaryfire Nov 13, 2026
3027aa5
Correct PHPStan resource ownership and listener lifetime analysis
binaryfire Nov 13, 2026
5f93ac0
Give analyzer subprocess tests an appropriate bounded timeout
binaryfire Nov 13, 2026
f06eb26
Refine borrowed-resource and cloned-listener analysis
binaryfire Nov 13, 2026
68ffe69
Exclude parse-only binding fixtures from Composer classmaps
binaryfire Nov 13, 2026
e99d4f3
Correct reference captures and worker-state diagnostics
binaryfire Nov 13, 2026
a266a6c
Preserve nested callback captures and changed receiver types
binaryfire Nov 13, 2026
6c7be43
Model queued listener option instances and their cache dependencies
binaryfire Nov 13, 2026
dfaa674
Recognize cancellation guards after preceding statements
binaryfire Nov 13, 2026
4cf4556
Track global stores and detached borrowed-resource captures
binaryfire Nov 13, 2026
f1e09d0
Report worker-wide state stored in global variables
binaryfire Nov 13, 2026
c6a8624
Follow cancellation guards through the final rethrow
binaryfire Nov 13, 2026
5224bc8
Preserve borrowed-resource facts across reference detachment
binaryfire Nov 13, 2026
3eea346
Detect global writes through bindings and reference arguments
binaryfire Nov 13, 2026
2641940
Keep cleared borrowed-resource facts out of later copies
binaryfire Nov 13, 2026
6da760d
Synchronize facade root clearing in concurrent tests
binaryfire Nov 13, 2026
d0f207c
Rebuild only borrowed-resource facts affected by an unset
binaryfire Nov 13, 2026
33987b5
Preserve capture-time facts when rebuilding borrowed values
binaryfire Nov 14, 2026
dd5e162
Model borrowed-resource flow through branches and loops
binaryfire Nov 14, 2026
23ea7ac
Report generator callbacks in managed transactions
binaryfire Nov 14, 2026
50fdabe
Correct borrowed-resource exception and expression traversal
binaryfire Nov 14, 2026
c819511
Apply borrowed-resource target writes in execution order
binaryfire Nov 14, 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
15 changes: 4 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ Build complete, long-term solutions, not MVPs or local workarounds. A broad chan
- **Prefer union types over `mixed` when all types are known** — `mixed` is only for truly unconstrained values or cases that cannot be safely narrowed after control-flow analysis.
- **Type decisions must be evidence-based** — check corresponding Laravel/Hyperf signatures and docblocks as a reference, then trace the real control flow through method bodies across all callers and callees to confirm the types are correct.
- **Fail fast with framework and PHP exceptions** — don't add guards, wrapping, or defensive checks unless they handle a reachable invalid case or materially improve the error, and never swallow exceptions. If code would fail anyway (e.g. null passed to a typed parameter), let it fail naturally instead of adding a check that throws a custom exception — the stack trace is enough to diagnose.
- **Mark intentionally unsupported methods** — when a public method must be retained but intentionally rejects every call, mark it with `#[Unsupported]` from `Hypervel\Support\Attributes`, passing the supported alternative as its message when one exists. Exclude base defaults that supporting implementations override, extension hooks, deliberate control-flow throws, and conditional rejections.
- **Mark intentionally unsupported methods** — when a public method must be retained but intentionally rejects every call, mark it with `#[Unsupported]` from `Hypervel\Support\Attributes`, passing the supported alternative as its message when one exists. Exclude base defaults that supporting implementations override, extension hooks, deliberate control-flow throws, and conditional rejections. PHPStan reports calls that reach a marked method.
- **Use semantic column types in migrations** — `uuid()` / `foreignUuid()` / `uuidMorphs()` for UUIDs, `ipAddress()` / `macAddress()` for network addresses, and `jsonb()` for JSON the database queries, indexes or validates. Use `text()` for opaque serialized values that are only read back whole. PostgreSQL gets the real types (`jsonb`, `uuid`, `inet`, `macaddr`); the other supported databases fall back automatically to compatible types.
- **No arbitrary string lengths** — use `->string('name')`, not `->string('name', 100)`. Don't invent limits; specify a length only when the domain or protocol defines one — exact (UUID: 36, ULID: 26, sha-256 hex token: 64) or a defined maximum (IPv6 address: 45).
- **No database enums** — use string columns plus PHP enums. Adding a value to a database enum requires a migration.
Expand Down Expand Up @@ -300,20 +300,13 @@ $this->app->singleton('auth', fn ($app) => new AuthManager($app));
$this->app->singleton(FormatterInterface::class, DefaultFormatter::class);
```

**3. Abstract and concrete are the same class — do not bind merely to share it.** Hypervel's container auto-singletons unbound concrete classes on first resolution. An explicit `singleton(Foo::class)` is redundant unless the class declares an intrinsic fresh lifetime through `Transient` or `SelfBuilding`:

```php
// Wrong: redundant; auto-singleton handles this.
$this->app->singleton(BroadcastManager::class);

// Correct: do not bind it. The first make(BroadcastManager::class) auto-singletons it.
```
**3. Abstract and concrete are the same class — do not bind merely to share it.** Unbound concrete classes without a different declared lifetime are auto-singletons. Explicit registration can change lifetimes, `bound()`, optional constructor injection and rebinding; retain it when those effects are intended.

### Aliases and canonical keys

Before binding core framework services, check `Application::registerCoreContainerAliases()`.

If the abstract or concrete participates in the alias table, choose the binding key carefully. `bind()` and `singleton()` store bindings under the exact abstract key passed; `resolve()` resolves aliases before lookup. Binding an alias instead of the canonical key can orphan the binding.
If the abstract or concrete participates in the alias table, choose the binding key carefully. `bind()` and `singleton()` store bindings under the exact abstract key passed; `resolve()` resolves aliases before lookup. Binding an alias removes its mapping to the canonical key; the two keys can then resolve differently.

When adding a core alias, use the string key as the canonical abstract:

Expand Down Expand Up @@ -395,7 +388,7 @@ Decide where state lives before writing code:
- `#[TestsOnly]` — test fakes, swaps, and overrides
- `#[BootOrTestsOnly]` — configuration or cleanup allowed in either context

Use `whenNotDefault: 'parameter'` only when the restriction applies to values differing from that parameter's declared default, `whenProvided: 'parameter'` when it applies whenever the argument is passed, and `whenShared: true` when it applies only to a worker-shared receiver. Keep a concise docblock explaining the runtime harm. If an API is intended for runtime use, fix unsafe shared-state behavior through a peer second opinion rather than restricting it to boot or tests.
PHPStan checks marked calls in recognized runtime contexts. Use `whenNotDefault: 'parameter'` only when the restriction applies to values differing from that parameter's declared default, `whenProvided: 'parameter'` when it applies whenever the argument is passed, and `whenShared: true` when it applies only to a worker-shared receiver. Keep a concise docblock explaining the runtime harm. If an API is intended for runtime use, fix unsafe shared-state behavior through a peer second opinion rather than restricting it to boot or tests.
- **Assess static caching opportunities** — if a path repeatedly computes expensive stable metadata and worker-lifetime static caching would be a clear win, reach consensus with your peer agent through a second-opinion loop on what to cache, the expected benefit, bounded memory use, and correctness across requests before implementing.

Classes that use static caching need a `flushState()` method for test cleanup — see "Static state and test cleanup" under Writing Tests.
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,9 @@
"tests/PHPStan/Unit/data"
],
"exclude-from-classmap": [
"tests/PHPStan/**/*-fixed.php"
"tests/PHPStan/**/*-fixed.php",
"tests/PHPStan/Rules/data/request-dependent-bindings.php",
"tests/PHPStan/Rules/data/request-dependent-bindings-local-request.php"
],
"files": [
"tests/Database/Fixtures/MigrationCreatorFakeMigration.php"
Expand Down
Loading
Loading