Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions .changelog/source-analysis-boundaries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
category: changed
type: patch
---

Documents the legacy PHPDoc rule activation and future analyzer boundaries,
including native whole-project PHPStan scope, without enabling new policies.
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ for the exact local base/head before publication; do not claim remote CI evidenc

- [README.md](README.md): library/CLI adoption, explicit fix and tool scope.
- [Policy comparison](docs/policy.md): evidence, rule differences and extraction gates.
- [PHPDoc comparison](docs/phpdoc-comparison.md): actual custom-rule registration, source contracts and remaining golden decisions.
- [Static-analysis evaluation](docs/static-analysis-evaluation.md): candidate engines, whole-project analysis and unresolved domain ownership.
- [Architecture decision](docs/architecture.md): library/tool dependencies, CPX/autoload limits and bootstrap without circular prerequisites.
- [Automation](docs/automation.md): trust, ref/bootstrap contracts and consumer adoption.
- [Instruction map](docs/instruction-map.md): single root scope and skill ownership.
Expand Down
55 changes: 55 additions & 0 deletions docs/phpdoc-comparison.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Source PHPDoc: legacy rules and extraction boundary

Fixed DevTools source `35b5f78ac63813ec07aa3fb3eda08751541e28e1`; source inventory
for extraction planning. These observations do not establish runtime parity.
Potential edge cases below are future fixture requirements, not reproduced bugs
or an adopted rule profile.

## Registration matters

There are three custom classes, but they are not all enabled by the inspected
default. `Config/RectorConfig::DEFAULT_RULES` registers
AddMissingMethodPhpDocRector and RemoveEmptyDocBlockRector, plus external Faker
GeneratorPropertyFetchToMethodCallRector. AddMissingClassPhpDocRector exists but
is absent from that default list. Do not equate class presence with activation.

The config also enables broad DEAD_CODE/CODE_QUALITY/CODING_STYLE/
TYPE_DECLARATION/PRIVATIZATION/INSTANCEOF/EARLY_RETURN sets, derives PHP migration
sets from consumer Composer, enables name import/removal, and conditionally loads
Safe migrations. These effects must not come along implicitly with a PHPDoc
extraction. Customization runs last in the native Rector callback.

## Observed class contracts

| Class | Inspected behavior | Required future goldens before selecting policy |
| --- | --- | --- |
| AddMissingClassPhpDocRector | Targets Class_ only, skips any existing Doc; generates class-name summary and namespace @package when available | Named/anonymous/namespaced classes; preserve useful existing prose/tags; choose whether generated boilerplate adds useful human information |
| AddMissingMethodPhpDocRector | Targets ClassMethod; skips the entire method when any Doc exists; creates @param from native types or mixed, @return except constructors, and @throws from literal new named exceptions found recursively | Existing partial docs vs absent docs, typed/untyped/nullable/union/intersection/DNF, variadic/reference parameters, constructors, abstract methods, nested closures and exception-name imports |
| RemoveEmptyDocBlockRector | Targets Class_/ClassMethod only; removes whitespace/star-only Doc; preserves other comment objects and clears Rector/AST doc attributes | Empty vs meaningful prose/tags, other comments, declaration docs on interfaces/traits/enums and docs on properties/functions outside this target set, methods inside interfaces/traits/enums still targeted as ClassMethod, repeated passes and native Rector cache/API compatibility |

These observations derive from the exact source, not generated example output.
In particular, the method rule does not fill missing tags in an existing partial
docblock, despite a broad reading of its description. Recursive throw traversal
and type rendering require dedicated fixture decisions; no unsupported claim of
precise escaping-exception inference or all-syntax correctness is made here.

## Extraction boundary

The initial Code Standards preset preserves existing PHPDoc and does not promise
useful documentation generation by restating syntax. Select human-useful policy
before copying any algorithm. Keep any later semantic operation explicit,
opt-in and target-PHP aware, separate from default check/fix. Reuse native APIs
and focused services rather than importing legacy broad configuration or a DSL.

Future comparative goldens must isolate each selected rule first, then test the
selected combined ordering against ECS. Assert source-readonly check, explicit
write/second-pass idempotence, exact exits, comments/attribute spacing and config
override precedence. Do not execute automatic Safe/Faker/PHP migrations as part
of that PHPDoc comparison. Detailed engine compatibility and behavior remain
unverified; this inventory does not close issue5 or issue4.

Immutable source links:
- https://github.com/php-fast-forward/dev-tools/blob/35b5f78ac63813ec07aa3fb3eda08751541e28e1/src/Config/RectorConfig.php
- https://github.com/php-fast-forward/dev-tools/blob/35b5f78ac63813ec07aa3fb3eda08751541e28e1/src/Rector/AddMissingClassPhpDocRector.php
- https://github.com/php-fast-forward/dev-tools/blob/35b5f78ac63813ec07aa3fb3eda08751541e28e1/src/Rector/AddMissingMethodPhpDocRector.php
- https://github.com/php-fast-forward/dev-tools/blob/35b5f78ac63813ec07aa3fb3eda08751541e28e1/src/Rector/RemoveEmptyDocBlockRector.php
5 changes: 5 additions & 0 deletions docs/policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,8 @@ Composer metadata normalization and existing public DevTools APIs stay untouched
Static quality in this first increment means parseable PHP and formatting
conformance. Type analysis, dead-code analysis and semantic refactors are not
claimed. Application tests, coverage and complete reports remain outside this domain.

The [PHPDoc comparison](phpdoc-comparison.md) records actual custom Rector
activation and the fixtures required before adopting a documentation policy.
The [static-analysis evaluation](static-analysis-evaluation.md) distinguishes
candidate engines and their analysis scopes without deciding domain ownership.
80 changes: 80 additions & 0 deletions docs/static-analysis-evaluation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Static analysis: candidates and ownership boundary

This source comparison records candidates without deciding ownership or
implementing an analyzer. DevTools issues
[#14](https://github.com/php-fast-forward/dev-tools/issues/14),
[#265](https://github.com/php-fast-forward/dev-tools/issues/265),
[#266](https://github.com/php-fast-forward/dev-tools/issues/266) and
[#267](https://github.com/php-fast-forward/dev-tools/issues/267) remain open.
These decisions are not prerequisites for the initial 0.1.0 style/syntax profile.

## Existing source

Inspected DevTools `35b5f78ac63813ec07aa3fb3eda08751541e28e1`. Bounded searches of
composer.json, src/, resources/, .github/ and README found no declarations of
PHPStan/Psalm/PHPat/php-assumptions/TypePerfect/security-audit engines or a
dedicated command for these candidate source analyzers. Existing Dependencies
and Metrics commands serve other contracts. PHPStan/Psalm filenames occur in
GitAttributes CandidateProvider only.
This is evidence of the searched surfaces, not a proof about every historical
branch or generated dependency. No source file was changed or scan executed.

## Actual candidate engines

Moving upstream default-branch manifests read via the authorized GitHub connector
on 2026-10-21 at 21:12 UTC, with exact file blob hashes below. These are not selected published
package versions or verified runtime compatibility claims.

| Source issue | Candidate and real upstream | Observed contract | Consequence |
| --- | --- | --- | --- |
| DevTools14 | phpstan/phpstan | Dedicated analyzer/PHAR; native analyse/configuration/level/error-format/memory-limit | Prefer native settings and exits; no generic multi-engine abstraction before a second real requirement |
| DevTools265 | rskuipers/php-assumptions | Standalone bin/phpa; php-parser4/5 + league/climate; README calls it a proof of concept | Not a PHPStan extension or runtime assertion framework on this evidence; identify intended package/version and test actual exits/target syntax before integration |
| DevTools266 | carlosas/phpat, package phpat/phpat | type phpstan-extension; PHP^8.1, PHPStan^2.1; extension.neon registered in extra | Real PHPStan extension; its development Psalm dependency is not a consumer runtime engine |
| DevTools267 | FloeDesignTechnologies/phpcs-security-audit, package pheromone/phpcs-security-audit | type phpcodesniffer-standard; PHP_CodeSniffer^3.1.0 + DealerDirect installer plugin; manifest declares GPL-3.0-or-later | Premise that this is a PHPStan security extension is incorrect; assess separately, without automatic plugin activation, mandatory adoption or inferred compatibility with modern PHPCS |

Manifest blob hashes: PHPStan `a267d4c50d8cd59cd63866d4c8b04a25f0a24627`;
assumptions `6037a1c9b39737581f74577f513d18333295354f`;
PHPat `055245974b55aa70c3a59954d373dc95c938b8e9`;
security-audit `a2a72a7b98d94d0e65e151f470dcc5715d9306a0`.
Security-audit README blob `63be29bacf78614110c556dfad68eafda4b140c4`
explicitly describes PHPCS invocation and significant noise; no scanner was run.

Primary manifests:
[PHPStan](https://github.com/phpstan/phpstan/blob/2.3.x/composer.json),
[assumptions](https://github.com/rskuipers/php-assumptions/blob/master/composer.json),
[PHPat](https://github.com/carlosas/phpat/blob/main/composer.json),
[security-audit](https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/composer.json).

## Changed-file semantics need a distinct decision

PHPStan explicitly recommends a stable whole-project analysed path set and uses
its native result cache/dependency tree to revisit dependents of changed symbols.
Therefore the ECS changed-file list must not be presented as equivalent type
analysis. A changed method signature can invalidate unchanged callers; checking
only the changed source would not establish those callers' validity. This last
example is an architectural inference, not an executed regression result.
If a restricted mode is retained later, name its limits explicitly and require
cross-file dependency regressions; native whole-project analysis is the proposed
default for an eventual PHPStan slice. No new CLI option was implemented.
[Official result-cache contract](https://phpstan.org/user-guide/result-cache).

PHPStan resolves symbols from analysed paths and the consumer Composer graph;
custom bootstrap/autoload PHP actually executes. A separately installed tool
does not remove that execution or namespace boundary. Preserve consumer NEON,
imports and baselines; use explicit target-PHP/config selection, unprivileged
processes, isolated tool cache and no incidental Composer scripts/plugins or
baseline writes. Test that checkout symbols win over an installed library with
the same namespace before adoption.
[Symbol discovery](https://phpstan.org/user-guide/discovering-symbols),
[native CLI](https://phpstan.org/user-guide/command-line-usage).

## Remaining gates

- Decide Code Standards ownership versus another tool before closing or moving
the four DevTools candidates. Do not implement every optional engine at once.
- Select actual published versions, inspect licenses/compatibility and prove
execution/format/exit/read-only behavior with synthetic cross-file fixtures.
- Keep TypePerfect semantic changes opt-in and independently scoped; its actual
package/groups remain to verify rather than copying an issue's assumption.
- Preserve current first-release boundary: syntax + non-risky ECS style only;
tests/coverage/full reporting remain other domains. No consumer migration.
Loading