Skip to content

Tests / Build Scripts: Configure PHPStan level 0#10419

Open
justlevine wants to merge 43 commits intoWordPress:trunkfrom
justlevine:tests/phpstan/level-0
Open

Tests / Build Scripts: Configure PHPStan level 0#10419
justlevine wants to merge 43 commits intoWordPress:trunkfrom
justlevine:tests/phpstan/level-0

Conversation

@justlevine
Copy link

Trac ticket: https://core.trac.wordpress.org/ticket/61175

This PR adds a PHPStan configuration for PHPStan level 0, along with tests and docs.

Based from #7619 - which remains in use to explore adopting future levels (alongside parallel remediation branches).

Proposal: https://make.wordpress.org/core/2025/07/11/proposal-phpstan-in-the-wordpress-core-development-workflow/


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

@github-actions
Copy link

github-actions bot commented Oct 25, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props justlevine, westonruter.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions
Copy link

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@justlevine justlevine force-pushed the tests/phpstan/level-0 branch from 86c9442 to 0308f9e Compare November 7, 2025 18:44
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces PHPStan level 0 static analysis configuration to WordPress Core, establishing a foundation for catching code errors without execution. The implementation includes PHPStan configuration files, bootstrap scripts, documentation, GitHub workflows for CI integration, and inline code annotations to suppress legitimate PHPStan warnings.

Changes:

  • Added PHPStan level 0 configuration with baseline support for legacy code
  • Added PHPStan annotations to source files to document legitimate suppressions
  • Integrated PHPStan into CI/CD via GitHub workflows and npm/composer scripts

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
phpstan.neon.dist Main PHPStan configuration with level 0 rules and baseline inclusion
tests/phpstan/base.neon Base configuration defining paths, exclusions, and codebase-specific settings
tests/phpstan/baseline.php Empty baseline file for future tech debt tracking
tests/phpstan/bootstrap.php Defines WordPress constants for PHPStan discovery
tests/phpstan/README.md Documentation for running and configuring PHPStan
src/wp-includes/template.php Added PHPStan annotations and removed obsolete comment
src/wp-includes/style-engine/class-wp-style-engine-css-rules-store.php Added @phpstan-consistent-constructor annotation
src/wp-includes/media.php Added annotation for PHP8+ GdImage class
src/wp-includes/functions.php Added enhanced return type documentation for wp_die()
src/wp-includes/customize/*.php Added @return documentation for overridden update() methods
src/wp-includes/class-wp-theme-json.php Added null return value to match documented return type
src/wp-includes/class-wp-scripts.php Removed obsolete PHPStan suppression comment
src/wp-admin/press-this.php Added PHPStan annotations for plugin file includes
src/wp-admin/includes/class-wp-filesystem-ssh2.php Added phpstan-ignore-next-line for unimplemented method
composer.json Added phpstan/phpstan dependency and analyse script
package.json Added test:php:stan npm script
phpcs.xml.dist Excluded PHPStan files from coding standards checks
.gitignore Added phpstan.neon to ignore list for local overrides
.github/workflows/php-static-analysis.yml Main workflow for running PHPStan on pushes and PRs
.github/workflows/reusable-php-static-analysis.yml Reusable workflow for PHPStan execution

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 81 to 82
- ../../src/wp-admin/js (?)
- ../../src/wp-includes/js (?)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

Unusual syntax: The "(?)" suffix on these exclude paths is not standard PHPStan configuration syntax. PHPStan uses standard glob patterns for path exclusion. If the intent is to conditionally exclude these paths, this should be documented or the syntax should be corrected. Consider using standard glob patterns like "../../src/wp-admin/js" or "../../src/wp-admin/js/**" instead

Suggested change
- ../../src/wp-admin/js (?)
- ../../src/wp-includes/js (?)
- ../../src/wp-admin/js
- ../../src/wp-includes/js

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

Invalid. this is modern phpstan, copilot's on a dumb model.

Copy link
Member

Choose a reason for hiding this comment

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

What does (?) mean?

Copy link
Author

Choose a reason for hiding this comment

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

It tells phpstan not to complain if the folder doesn't exist (e.g. because GB hasn't built)

"squizlabs/php_codesniffer": "3.13.5",
"wp-coding-standards/wpcs": "~3.3.0",
"phpcompatibility/phpcompatibility-wp": "~2.1.3",
"phpstan/phpstan": "~2.1.33",
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

The version constraint "~2.1.33" is very specific and may cause issues. The tilde operator (~) for a three-part version like 2.1.33 means ">=2.1.33 <2.2.0". This constraint locks to a specific patch version which may not exist or may prevent receiving important bug fixes. Consider using "^2.1" (which means ">=2.1.0 <3.0.0") or "~2.1.0" (which means ">=2.1.0 <2.2.0") instead to allow flexibility for patch updates while staying within the same minor version

Suggested change
"phpstan/phpstan": "~2.1.33",
"phpstan/phpstan": "~2.1.0",

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

@westonruter what are your thoughts on this one?

I definitely think we should pin at the version we commit, but I wouldn't want to Semver because contextually "nonbreaking enhancements" are breaking from an implementation POV if they create a new quality gate.

Copy link
Member

Choose a reason for hiding this comment

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

That makes sense to me. So switching to ~2.1.0 would keep it at 2.1.x. This seems necessary because there is no composer.lock, which actually is curious since we package-lock.json. If we had a composer.lock then we'd be free to use ^2.1. But I suppose can't use it because of the different versions of PHP which may end up getting used when doing composer install.

So yeah, I guess go with ~2.1.0 and not ^2.1. When PHPStan 2.2 comes out, we'll have to manually upgrade.

Copy link
Author

Choose a reason for hiding this comment

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

Depending on when we merge, there might be some value to pinning a minimum patch release too e.g. phpstan/phpstan#8438 (comment) . Leaving this for now, and might even bump it if this PR lingers. Keeping the issue open as a reminder to drop this as low as we think is worthwhile before we merge.

justlevine and others added 4 commits February 12, 2026 23:53
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@westonruter
Copy link
Member

westonruter commented Feb 12, 2026

In Gruntfile.js, there is a precommit task, which includes precommit:php as well as format:php. Curiously, it doesn't to lint:php (probably because there are still so many violations), but it should run PHPStan since it can run on the entire codebase without errors.

@westonruter
Copy link
Member

I tried running composer analyse and it seemed to finish but then it hung at 99%. Finally it errored:

image

@justlevine
Copy link
Author

justlevine commented Feb 12, 2026

I tried running composer analyse and it seemed to finish but then it hung at 99%. Finally it errored:

image

@westonruter can you run it with -- --vvv? I believe that should show us which file it's timing out on.

(Also confirming that you're using the vanilla phpstan.neon.dist and the CLI is just inaccurate - if not, please share any modifications there too)

@westonruter
Copy link
Member

Actually, I was using a local phpstan.neon which was overriding the one provided in this PR. When I try using the one in the PR, the result is actually worse. It never starts analyzing. This seems to be due to the paths config:

paths:
- ../../src

If I change it to:

	paths:
		- ../../src/wp-admin
		- ../../src/wp-includes

Then it works, aside from two errors being found:

 ------ ---------------------------------------------------------------------- 
  Line   wp-admin/load-scripts.php                                             
 ------ ---------------------------------------------------------------------- 
  68     Function get_file not found.                                          
         🪪  function.notFound                                                 
         💡  Learn more at https://phpstan.org/user-guide/discovering-symbols  
         at src/wp-admin/load-scripts.php:68                                   
 ------ ---------------------------------------------------------------------- 

 ------ ---------------------------------------------------------------------- 
  Line   wp-admin/load-styles.php                                              
 ------ ---------------------------------------------------------------------- 
  83     Function get_file not found.                                          
         🪪  function.notFound                                                 
         💡  Learn more at https://phpstan.org/user-guide/discovering-symbols  
         at src/wp-admin/load-styles.php:83                                    
 ------ ---------------------------------------------------------------------- 

What appears to be the issue is that I use my wordpress-develop clone for core and plugin development together. So my src/wp-content is very large. I know other contributors do this as well, so this is something which should be accounted for.

Nevertheless, the change I made is not ideal because then it doesn't check the PHP files in the root of src, like wp-login.php. I'm confused because from looking at the excludePaths config, it would seem that src/wp-content is supposed to be excluded, and yet PHPStan still seems to be scanning all the 16GB worth of files in the plugins dir.

Comment on lines 77 to 82
# JavaScript/CSS/Asset files.
- ../../src/wp-admin/css
- ../../src/wp-admin/images
# These are built from js/_enqueues.
- ../../src/wp-admin/js (?)
- ../../src/wp-includes/js (?)
Copy link
Member

Choose a reason for hiding this comment

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

Is this even necessary since these are JS files and not PHP files? According to the docs:

By default, PHPStan analyses only files with the .php extension.

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# JavaScript/CSS/Asset files.
- ../../src/wp-admin/css
- ../../src/wp-admin/images
# These are built from js/_enqueues.
- ../../src/wp-admin/js (?)
- ../../src/wp-includes/js (?)

Copy link
Member

Choose a reason for hiding this comment

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

I removed these in 522147a

Copy link
Author

Choose a reason for hiding this comment

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

IIRC (not by my desk to verify) the consideration was that Gutenberg was stealthing in some PHP during build, and I didn't want us to try and catch them all.

Not sure if/how things have changed, but if these are the only errors you're getting, then yeah no reason to keep em around.

Comment on lines +90 to +91
# These files are sourced by wordpress/gutenberg in `tools/release/sync-stable-blocks.js`.
- ../../src/wp-includes/blocks
Copy link
Member

Choose a reason for hiding this comment

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

I suppose then this would necessitate adding PHPStan to Gutenberg to do the necessary checks?

Copy link
Author

@justlevine justlevine Feb 16, 2026

Choose a reason for hiding this comment

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

WordPress/gutenberg#66598 but it's been gathering dust for a while.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 29 out of 30 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- 'composer.*'
# These files configure PHPStan. Changes could affect the outcome.
- 'phpstan.neon.dist'
- 'tests/phpstan/base.neon'
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

The workflow paths configuration should also include 'tests/phpstan/bootstrap.php' as changes to this file could affect PHPStan analysis by modifying constant definitions used during static analysis.

Suggested change
- 'tests/phpstan/base.neon'
- 'tests/phpstan/base.neon'
- 'tests/phpstan/bootstrap.php'

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

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

Well, I committed this but it actually isn't needed because **.php is already included.

@westonruter
Copy link
Member

Gemini's review

This is a comprehensive review of the changes proposed for integrating PHPStan into WordPress core. The review focuses on technical accuracy, adherence to WordPress coding standards, PHP 7.4 compatibility, and overall architectural consistency.

GitHub Workflows

  • .github/workflows/php-static-analysis.yml:
    • Logic: The on triggers correctly include trunk and stable branches ([7-9].[0-9]).
    • Nit: The concurrency group naming is consistent with other core workflows.
  • .github/workflows/reusable-php-static-analysis.yml:
    • Build Dependency: It correctly runs npm run build:dev before analysis. This is crucial because many core PHP files are generated or modified during the build process, and PHPStan needs the final state of the files.
    • Caching: The use of a weekly-rotated custom cache suffix (based on "last Monday") is a smart way to manage the composer update environment without a lockfile.
    • Missing @ticket: As this is a new file in the .github directory (part of the CI/CD "tests" infra), it would ideally mention the Trac ticket in a comment at the top, though it's not strictly required by core standards for YAML.

General Configuration

  • .gitignore: Added /phpstan.neon. This is correct to allow developers to create local overrides of the .dist file.
  • composer.json:
    • Nit: The phpstan script uses @php. This is good for cross-platform compatibility.
    • Dependency: phpstan/phpstan: ~2.1.33 is appropriate.
  • phpstan.neon.dist:
    • Level 0: A sensible starting point for a codebase of this size.
    • Inner Functions: The ignoreErrors for inner functions in wp-admin/includes/export.php etc., are necessary because PHPStan does not support them. This is a known architectural quirk of WordPress core.
  • tests/phpstan/base.neon:
    • Performance Fix: The change from a blanket ../../src path to explicit paths for wp-admin, wp-includes, and root PHP files is a vital fix for the "hanging" issue caused by wp-content traversal.
    • Missing Themes: While listing themes explicitly is a good workaround for the hang, it means any new default theme added to core will need to be manually added here. A comment should be added to remind future developers of this.
  • tests/phpstan/bootstrap.php:
    • Standards: This file uses tabs for indentation and follows core's define style.
    • Missing @ticket: This file should have a @ticket tag in its header docblock.

Core PHP Changes

  • src/wp-includes/functions.php (wp_die):
    • Type Hint: @phpstan-return ($args['exit'] is false ? void : never) is an excellent use of conditional types to accurately represent the behavior of wp_die().
  • src/wp-includes/class-wp-theme.php:
    • Conditional Type: The @phpstan-return for get() is technically correct but very complex.
    • Nit: It returns mixed for unknown headers. Given that the underlying headers property is array<string, string>, and sanitize_header returns string|array, it might be safer to narrow mixed to string|array|false.
  • src/wp-includes/html-api/class-wp-html-processor.php:
    • Return Never: Adding @return never to bail() is the correct fix for the "missing return statement" errors in calling methods.
  • src/wp-includes/customize/class-wp-customize-filter-setting.php:
    • Logic Change: You added return true; to an empty update() method. While this satisfies PHPStan's requirement for a bool return, ensure this doesn't conflict with any child classes that might expect a void return (though in this case, the base class defines it as returning true|WP_Error usually).

Theme Changes

  • src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-customize.php:
    • Bug Fix: The addition of the if ( $setting ) check is a genuine bug fix discovered by PHPStan. Previously, it would have caused a fatal error if blogname or blogdescription were missing (unlikely, but possible in some environments).
  • src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-svg-icons.php:
    • Cast: (string) preg_replace(...). Since preg_replace can return null on error (or an array if the input was an array), the cast ensures compatibility with the string return type of get_svg(). This is safe here as the input is a known string.

Documentation

  • tests/phpstan/README.md:
    • Accuracy: The paths have been corrected to src/wp-includes/....
    • Style: Uses US spelling ("analyze") consistently with the rest of the PR.

Summary of Nit-picks & Concerns:

  1. Indentation: Ensure tests/phpstan/base.neon and phpstan.neon.dist use tabs for indentation within the YAML/NEON structures where appropriate (though NEON usually accepts spaces, tabs are core's preference). Self-correction: Looking at the diff, it seems tabs are used.
  2. @since vs @ticket:
    • tests/phpstan/base.neon: New file. Should have a Trac ticket reference in a comment.
    • tests/phpstan/bootstrap.php: New file. Needs @ticket.
    • tests/phpstan/README.md: New file. No @since needed (it's a test asset), but Trac ticket reference is good practice.
  3. PHP 7.4 Compatibility: All changes use syntax compatible with PHP 7.4. The use of @phpstan-ignore for GdImage in media.php is the correct way to handle class existence that depends on the PHP version.
  4. WP_Theme::get(): The return type mixed at the end of the conditional might be too broad. Since the method is intended to return string|array|false, it would be better to use that instead of mixed.

Overall, this is a very high-quality integration that significantly improves the type safety of WordPress core without introducing unnecessary noise or performance regressions.

westonruter and others added 3 commits February 16, 2026 15:28
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Comment on lines 83 to 84
- name: Install npm dependencies
run: npm ci
Copy link
Member

@westonruter westonruter Feb 16, 2026

Choose a reason for hiding this comment

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

This step is very slow. Running npm ci stalls for a long time at:

🔨 Building Gutenberg for WordPress Core...

Can we cache it?

Copy link
Member

@westonruter westonruter Feb 16, 2026

Choose a reason for hiding this comment

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

Gemini CLI implemented cc01268 with the following reasoning:

To speed up the PHP Static Analysis workflow and prevent it from hanging during the Gutenberg build, I have implemented the following optimizations in .github/workflows/reusable-php-static-analysis.yml:

  1. Gutenberg Caching: Added a cache step for the gutenberg/ directory and the .gutenberg-hash file. The cache key is based on the specific Gutenberg reference defined in package.json and the content of the Gutenberg build tools. This ensures that Gutenberg is only built once per reference across all CI runs.
  2. Ignored Scripts during npm ci: Changed the dependency installation step to use npm ci --ignore-scripts. This prevents the automatic Gutenberg build from triggering during the npm ci phase, which was the primary cause of the slow runs.
  3. Refined Build Process: The subsequent npm run build:dev step still ensures all necessary files are present. Because Gutenberg is now cached and the .gutenberg-hash is restored, the gutenberg-sync task becomes a near-instant no-op, while still allowing the core build to complete.

These changes will significantly reduce the CI runtime, as the expensive Gutenberg checkout and build (which often takes 5-10 minutes) will be skipped on most runs.

Copy link
Member

Choose a reason for hiding this comment

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

Also, I was curious if the --ignore-scripts would result in the Gutenberg getting built the first time or after an update:

That is a great observation. You're right that we still need the script to run if the cache is empty or the version changes.

However, because the subsequent step in the workflow is npm run build:dev, the build is still guaranteed to happen. Here is how it works now:

  1. Cache Restored: If the cache is valid, gutenberg/ and .gutenberg-hash are restored. When npm run build:dev runs, it calls the gutenberg-sync task. That task checks .gutenberg-hash against package.json, sees they match, and returns immediately (taking 0 seconds).
  2. Cache Miss/Invalid: If the cache is empty or the reference changed, the gutenberg-sync task will see the mismatch and automatically trigger the full checkout and build process (node tools/gutenberg/sync-gutenberg.js), exactly as it did before.

By using --ignore-scripts during the root npm ci, we simply prevent the build from happening twice or happening at a stage where we haven't yet had a chance to restore the cache. This gives us the best of both worlds: speed when the cache is hot, and correctness when it's not.

Copy link
Member

Choose a reason for hiding this comment

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

Much better! Over ~2.34 times faster.

Before:

image

After:

image

Copy link
Author

Choose a reason for hiding this comment

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

This is 🥇

Copy link
Author

Choose a reason for hiding this comment

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

Leaving this open as a good use and disclosure example will resolve once I'm at a desk and can record it

westonruter and others added 2 commits February 16, 2026 15:58
To speed up the workflow and prevent 'npm ci' from hanging during the Gutenberg build:
- Added a cache step for the 'gutenberg/' directory and '.gutenberg-hash' file.
- Used '--ignore-scripts' during 'npm ci' to bypass the automatic Gutenberg build.
- The build remains part of 'npm run build:dev', but now benefits from the restored cache and hash, making it a no-op when the reference hasn't changed.

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@justlevine
Copy link
Author

Overall, this is a very high-quality integration that significantly improves the type safety of WordPress core without introducing unnecessary noise or performance regressions.

Thank you robot overlord 🦾🦾🦾

  • Missing @ticket: As this is a new file in the .github directory (part of the CI/CD "tests" infra), it would ideally mention the Trac ticket in a comment at the top, though it's not strictly required by core standards for YAML.
  • tests/phpstan/bootstrap.php:

    • Missing @ticket: This file should have a @ticket tag in its header docblock.

Is this a real concern?

  • Missing Themes: While listing themes explicitly is a good workaround for the hang, it means any new default theme added to core will need to be manually added here. A comment should be added to remind future developers of this.

This seems like a nonproblem themes are added to core manually anyway...

  • src/wp-includes/class-wp-theme.php:

    • Conditional Type: The @phpstan-return for get() is technically correct but very complex.
    • Nit: It returns mixed for unknown headers. Given that the underlying headers property is array<string, string>, and sanitize_header returns string|array, it might be safer to narrow mixed to string|array|false.
  • src/wp-includes/html-api/class-wp-html-processor.php:

I need to check this from a computer 📝

  • Logic Change: You added return true; to an empty update() method. While this satisfies PHPStan's requirement for a bool return, ensure this doesn't conflict with any child classes that might expect a void return (though in this case, the base class defines it as returning true|WP_Error usually).

There's an open thread on this already...

Theme Changes

  • src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-customize.php:

    • Bug Fix: The addition of the if ( $setting ) check is a genuine bug fix discovered by PHPStan. Previously, it would have caused a fatal error if blogname or blogdescription were missing (unlikely, but possible in some environments).
  • src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-svg-icons.php:

    • Cast: (string) preg_replace(...). Since preg_replace can return null on error (or an array if the input was an array), the cast ensures compatibility with the string return type of get_svg(). This is safe here as the input is a known string.

I don't remember introducing these changes, I have no indication whether this is legitimate or a hallucination.

{the next bunch of lines seemed like it was agreeing with me, thank you 🤖that's why I did it that way...}


PS:

Important

🚨 Disclaimer
For all y'all trolls on the internet, what follows is part of an ongoing and larger discussion on AI Contribution Guidelines and emerging best practices. Everything that follows is my own opinion at this particular moment in time. This is no dis sto @westonruter or anything like that. AI etiquette as a whole is something that's quickly evolving, and we're the folks collectively evolving it by having these discussions transparently. Thanks for coming to my TED talk.

(It's here because there's no answer as of yet as to where feedback re the new AI guidelines should be directed).

I feel like the above contribution was "workslop". You didn't use AI to make your job as a reviewer easier, you gave me some pointless busywork: a bunch of autogenerated text that I then had to sift through to try and derive meaning or see if there was any value there. Even the few points where it could have been helpful, aren't IRL because I don't know whether you @westonruter, trusted reviewer and committer, vetted the details, or if it's all just probabilistic garbage puked out by a mid-tier model (I don't even know which model was used, what harness...)

IMO a "good" use of AI here would have been

  1. You review the results of your own prompt, and evaluate the results yourself.

  2. If your model flagged something and you agree with the assessment - then I don't even care that you used AI and wouldn't noticed if you didnt disclose.

  3. If your model flagged something, and you weren't sure of the results, then that's a good opportunity to share and disclose. E.g:

    Hey, I prompted Gemini (CLI with 3.0-auto ), and it flagged {e.g. such and such concern about adding a ticket number to any new file headers }. I think that make sense but don't feel too strongly about it.

  4. I'm hesitant to recommend the value in disclosure if the model approves of a pr. That's also not an actionable quality signal - at least not from current gen models.

Tl;dr proposing the principle of "you own your ai":

It's only "helpful" to disclose your LLM usage as a quality signal regarding the level of intentionality in the "work product" (code, code review, human opinion, etc)

Everything else is slop.

If you contribute it, you "own" it, and if you can't own it yourself, then disclaim it so other folks know the level of signal to give it.

@westonruter
Copy link
Member

I cited Gemini's review clearly labeled as Gemini's so we could take it as face value. Bottom line is it didn't find any red flags. I used it as a sanity check and I included it here for transparency.

@westonruter
Copy link
Member

I don't remember introducing these changes, I have no indication whether this is legitimate or a hallucination.

I made these changes, referenced in #10419 (comment)

@westonruter
Copy link
Member

@justlevine I also got to the bottom of the issue with wp_insert_user() causing PHPStan to hang. Or at least, I think I did. The issue is that PHPStan couldn't figure out what $userdata's type was. So in 77d9403...512e368 I've ensured that $userdata always is a string, and I went the extra mile to ensure back-compat for passing in unexpected values to that function.

Co-authored-by: Weston Ruter <westonruter@gmail.com>
@westonruter
Copy link
Member

westonruter commented Feb 17, 2026

As part of that, it is also now analyzing the core themes. I fixed the issues it newly identified.

Copy link
Member

Choose a reason for hiding this comment

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

@dmsnell FYI the two lines added to this file.

@westonruter
Copy link
Member

westonruter commented Feb 17, 2026

@westonruter
Copy link
Member

westonruter commented Feb 17, 2026

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.

2 participants