Ctrl K
ComunidadGuías…

psalm.xml

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<?xml version="1.0"?>
<!--
    Psalm configuration for phlix-server (S146).

    HISTORY — why this file exists. The "Psalm Static Analysis" job in
    .github/workflows/coding-standards.yml has existed since the very first CI
    commit (b7c728ca, 2026-05-15) but `vimeo/psalm` was NEVER added to
    composer.json, so `vendor/bin/psalm` never existed, the job's
    `if [ -f vendor/bin/psalm ]` guard was always false, and the job went GREEN
    having analysed zero files. It was counted as real coverage in PR reviews.
    S146 finishes the abandoned rollout: the dependency, this config, the guard
    removal and the code fixes all land together, because adding the dependency
    on its own makes psalm abort with "Could not locate a config XML file" and
    turns master red instantly.

    errorLevel="5" is a deliberate, measured choice — NOT a baseline. Measured
    finding counts for src/ on 2026-07-27 with the analysis extensions loaded:

        level 1: 4343   level 2: 1484   level 3: 620   level 4: 484
        level 5:   89   level 6:   78   level 7:  30   level 8:   6

    Level 4 is the cliff: 348 of the 395 findings it adds over level 5 are
    RedundantCondition / TypeDoesNotContainType / RedundantCast, and in this
    codebase those are overwhelmingly deliberate is_array()/is_string() guards
    on database rows and decoded JSON. Deleting them to satisfy psalm would
    strip real runtime protection, so level 5 is where the tool stops arguing
    with defensive code and starts reporting defects. Raise the level if and
    when those guards are replaced by typed row objects; do NOT add a
    psalm-baseline.xml, which would reproduce the exact "gate that proves
    nothing" defect S146 exists to remove.

    phpVersion is pinned to the version CI and production analyse against, so
    the result does not drift with whatever PHP the runner happens to ship.

    S256-residual (2026-09-10) — scripts/ joined the production corpus, mirroring
    the hub's S248 shape. The level ladder above was measured over src/ only and
    is UNCHANGED by this step; the scripts/ addition was measured separately:
    Psalm 6.5.0 reported 10 level-5 findings across scripts/ (43 PHP files
    enumerated at the time of writing), and every one was fixed at the source.
    Five were live runtime defects: two boot-blocking constructor failures
    (backfill-chapters.php passed the raw Connection to MarkerCandidateRepository,
    run-media-asset-worker.php passed it to FfmpegRunner — whose review follow-up
    also gave it the ConnectionPool::init() every sibling script has), a wrong
    config key (backfill-streams.php read 'probe_path', so a custom ffprobe binary
    was silently ignored), a collect() name collision with the global crell/fp
    ships (add-headers.php), and a ParadoxicalCondition from a ternary that
    re-read an offset after narrowing (ci-browser-e2e-prereqs.php). The remaining
    findings were type honesty — chiefly 4 UndefinedClass reports for
    Swoole\\Coroutine\\WaitGroup resolved by the <stubs> entry below (the same
    drift-tested declaration the phpstan configs scanFiles) — and the add-headers
    rewrite. No baseline, no ignoreErrors, no IssueHandler, zero
    <file> exclusions here. tests/ is NOT part of this config; it keeps its own
    measured-L5 file, psalm-tests.xml (S306). Scope is asserted, with negative
    fuzz, by tests/Unit/Support/StaticAnalysisScopeTest.php.
-->
<psalm
    errorLevel="5"
    phpVersion="8.3"
    resolveFromConfigFile="true"
    findUnusedCode="false"
    findUnusedBaselineEntry="false"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="https://getpsalm.org/schema/config"
    xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
    <projectFiles>
        <directory name="src" />
        <directory name="scripts" />
        <ignoreFiles>
            <directory name="vendor" />
        </ignoreFiles>
    </projectFiles>

    <!-- S256-residual: same single-source-of-truth stub the tests config and
         phpstan-tests.neon load. scripts/bench/coroutine_bench.php constructs a
         Swoole\Coroutine\WaitGroup behind an extension_loaded('swoole') guard;
         it is a userland class the swoole binary compiles in, invisible to
         file-based analysis even when the extension is loaded (measured in
         S306). The declaration is drift-tested against the real extension by
         StaticAnalysisScopeTest::testTheWaitGroupDeclarationStillMatchesTheRealExtension. -->
    <stubs>
        <file name="phpstan-stubs/Swoole/Coroutine/WaitGroup.stub" />
    </stubs>
</psalm>