Skip to content

Fatal error in wp_insert_term() when the term name is not a string - #13521

Open
josephscott wants to merge 21 commits into
WordPress:trunkfrom
josephscott:66108/avoid-fatal-on-term-name
Open

josephscott wants to merge 21 commits into
WordPress:trunkfrom
josephscott:66108/avoid-fatal-on-term-name

Conversation

@josephscott

Copy link
Copy Markdown
Contributor

https://core.trac.wordpress.org/ticket/66108

AI assistance: Yes
Tool(s): Claude Code
Model(s): Fable 5.1
Used for: Research and experimentation. Guided directions on writing the code changes. It wrote the tests.


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

github-actions Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs.

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

Props josephscott, westonruter, therssoftware.

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


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

@github-actions

Copy link
Copy Markdown

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

  • 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.

@robelsust

Copy link
Copy Markdown

Tested and Verified ✅

Environment:

  • WordPress: 7.2-alpha (trunk)
  • PHP: 8.3

Verification:

  1. Before Patch (trunk):

    • wp_insert_term( array( 'foo' ), 'post_tag' ) throws a fatal TypeError: trim(): Argument #1 ($string) must be of type string, array given.
    • XML-RPC wp.newPost with array in terms_names triggers HTTP 500 instead of a structured XML-RPC fault.
  2. After PR Fatal error in wp_insert_term() when the term name is not a string #13521:

    • wp_insert_term() safely returns WP_Error( 'empty_term_name' ) for non-scalar $term values without fatals.
    • Numeric term names (2024, 1.5) continue to work properly as strings.
    • XML-RPC _insert_post() cleanly returns IXR_Error( 403, 'Invalid term name.' ).
    • PHPUnit:
      • tests/phpunit/tests/term/wpInsertTerm.php: Pass (43 tests, 166 assertions)
      • tests/phpunit/tests/xmlrpc/wp/newPost.php: Pass (32 tests, 78 assertions)
      • Full --group taxonomy: Pass (913 tests, 2383 assertions)
      • Full --group xmlrpc: Pass (356 tests, 1339 assertions)
    • PHPCS: 0 errors, 0 warnings on changed lines.

Regarding the discussion on JSON Schema adoption for XML-RPC: while a future schema-driven sanitization layer for XML-RPC is a worthy initiative, this PR addresses a real PHP 8+ fatal error in wp_insert_term() and _insert_post() cleanly and without breaking changes. Recommending approval.


$term_names = $post_data['terms_names'][ $taxonomy ];
foreach ( $term_names as $term_name ) {
if ( ! is_string( $term_name ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Good. This addresses an existing PHPStan error on code below:

Image

Comment thread src/wp-includes/taxonomy.php Outdated
Comment on lines +2561 to +2562
if ( '' === trim( $term ) ) {
if ( ! is_scalar( $term ) || '' === trim( $term ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this just a hardening? Is it needed for the above fix. PHPStan isn't complaining here because $term comes from the return value of the pre_insert_term filter which is typed as string|WP_Error. It is first checked to see if it is a WP_Error in which it returns, so then the type narrows to string.

I think this is a case where the callers should be fixing the types that they pass into the wp_insert_term() function.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For the XML-RPC case it is not strictly needed.

It is first checked to see if it is a WP_Error in which it returns, so then the type narrows to string.

I don't think that is accurate, which is why we have an is_int() call as well - https://github.com/WordPress/wordpress-develop/blame/trunk/src/wp-includes/taxonomy.php#L2595

Anything that calls wp_insert_term() directly can cause a problem. Here is an example without this fix:

$ npm run env:cli --silent -- eval 'var_dump( wp_insert_term( array( "foo" ), "post_tag" ) );'
Fatal error: Uncaught TypeError: trim(): Argument #1 ($string) must be of type string, array given in /var/www/src/wp-includes/taxonomy.php:2599
Stack trace:
#0 /var/www/src/wp-includes/taxonomy.php(2599): trim(Array)
#1 phar:///usr/local/bin/wp/vendor/wp-cli/eval-command/src/Eval_Command.php(39) : eval()'d code(1): wp_insert_term(Array, 'post_tag')
#2 phar:///usr/local/bin/wp/vendor/wp-cli/eval-command/src/Eval_Command.php(39): eval()
#3 [internal function]: Eval_Command->__invoke(Array, Array)
#4 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/CommandFactory.php(100): call_user_func(Array, Array, Array)
#5 [internal function]: WP_CLI\Dispatcher\CommandFactory::WP_CLI\Dispatcher\{closure}(Array, Array)
#6 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Dispatcher/Subcommand.php(497): call_user_func(Object(Closure), Array, Array)
#7 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(470): WP_CLI\Dispatcher\Subcommand->invoke(Array, Array, Array)
#8 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(493): WP_CLI\Runner->run_command(Array, Array)
#9 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(136): WP_CLI\Runner->run_command_and_exit()
#10 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Runner.php(1228): WP_CLI\Runner->do_early_invoke('before_wp_load')
#11 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/WP_CLI/Bootstrap/LaunchRunner.php(28): WP_CLI\Runner->start()
#12 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/bootstrap.php(84): WP_CLI\Bootstrap\LaunchRunner->process(Object(WP_CLI\Bootstrap\BootstrapState))
#13 phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/wp-cli.php(35): WP_CLI\bootstrap()
#14 phar:///usr/local/bin/wp/php/boot-phar.php(20): include('phar:///usr/loc...')
#15 /usr/local/bin/wp(4): include('phar:///usr/loc...')
#16 {main}
  thrown in /var/www/src/wp-includes/taxonomy.php on line 2599
Error: There has been a critical error on this website.Learn more about troubleshooting WordPress. There has been a critical error on this website.

And here is the same call with this fix:

$ npm run env:cli --silent -- eval 'var_dump( wp_insert_term( array( "foo" ), "post_tag" ) );'
object(WP_Error)#2540 (3) {
  ["errors"]=>
  array(1) {
    ["empty_term_name"]=>
    array(1) {
      [0]=>
      string(33) "A name is required for this term."
    }
  }
  ["error_data"]=>
  array(0) {
  }
  ["additional_data":protected]=>
  array(0) {
  }
}

@westonruter westonruter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Code review findings are left inline. The first two (in _insert_post()) are regressions introduced by this change and are the most important; the rest are API consistency, scope, and test-docs points.


$term_names = $post_data['terms_names'][ $taxonomy ];
foreach ( $term_names as $term_name ) {
if ( ! is_string( $term_name ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

The is_string() guard rejects integer term names that previously worked. An XML-RPC client sending a numeric tag name as <int> (e.g. Python's xmlrpc.client with 2024) used to get a working lookup via get_term_by( 'name', 2024 ) and, failing that, wp_insert_term( 2024 ). Now the post fails with 403 "Invalid term name." This also disagrees with wp_insert_term(), which this same PR explicitly accepts ints and floats for, and the 'integer' case in the new newPost test locks the regression in.

Allowing is_int() (and possibly is_float()) and casting to string would keep numeric names working while still rejecting arrays and objects.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Addressed in f216122. Ints and floats are now cast to strings, and only other types (such as arrays and booleans) return the 403 "Invalid term name." error. The 'integer' invalid case was replaced with 'boolean', and test_terms_names_numeric_term_name asserts that 2024 and 1.5 are assigned as the tags "2024" and "1.5".

return new IXR_Error( 403, __( 'Invalid term name.' ) );
}

if ( in_array( $term_name, $ambiguous_terms, true ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Ambiguous numeric term names cannot be detected here. $ambiguous_terms comes from array_keys( array_count_values( ... ) ), which converts numeric-string names like "2024" into int keys. Since $term_name is now guaranteed to be a string, the strict in_array( '2024', array( 2024 ), true ) is always false, so a hierarchical taxonomy with two terms named "2024" silently resolves to whichever get_term_by() returns first. (The string case predates this PR, but an int input used to match, and now no input can trigger the check.) Mapping $ambiguous_terms through strval would fix it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Addressed in 5f65187. $ambiguous_terms is now mapped through strval, so numeric names match the (string) term name in the strict in_array() check. test_terms_names_ambiguous_numeric_term_name covers a hierarchy with two categories named "2024", sent both as '2024' and 2024; both cases failed before the fix.

@@ -1710,6 +1710,10 @@ protected function _insert_post( $user, $content_struct ) {

$term_names = $post_data['terms_names'][ $taxonomy ];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

$term_names itself is not checked to be an array. Sending terms_names => array( 'post_tag' => 'foo' ) makes the foreach emit a "foreach() argument must be of type array|object" warning, and the terms are silently ignored instead of returning an error. The $term_ids branch has the same gap. Possibly out of scope, but it sits right next to the new per-item guard.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Addressed in cb770c2. Both the terms and terms_names branches now check that the per-taxonomy value is an array, returning the existing "Invalid term ID." (403) or "Invalid term name." (401) error respectively, instead of emitting a foreach warning and silently dropping the terms. test_terms_not_array covers a string and an int for terms and a string for terms_names; all three cases hit the warning before the fix. Since wp.editPost shares _insert_post(), it is covered too.

$term_names = $post_data['terms_names'][ $taxonomy ];
foreach ( $term_names as $term_name ) {
if ( ! is_string( $term_name ) ) {
return new IXR_Error( 403, __( 'Invalid term name.' ) );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Minor: every other validation error in this terms_names block uses code 401 (e.g. "Ambiguous term name…"), while this one uses 403. There is precedent for 403 with "Invalid term ID." in the IDs branch, so this is a judgment call, but it is worth a deliberate choice.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Addressed in f406733. The invalid term name error now uses 401, consistent with the other validation errors in the terms_names block. The term ID block keeps 403, matching its existing "Invalid term ID." error.

Comment thread src/wp-includes/taxonomy.php Outdated
}

if ( '' === trim( $term ) ) {
if ( ! is_scalar( $term ) || '' === trim( $term ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

The same trim()-on-non-string TypeError remains in other term sinks: wp_update_term() (the trim( $args['name'] ) handling), wp_set_object_terms(), wp_remove_object_terms(), and term_exists(). For example, wp_update_term( $id, 'post_tag', array( 'name' => array( 'x' ) ) ) or wp_set_object_terms( $post_id, array( array( 'x' ) ), 'post_tag' ) still fatals. These could be addressed here or in a follow-up ticket.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

The XML-RPC paths that still reached this trim() fatal were checked, and five were confirmed to crash with an array name (each requires an authenticated user with the relevant capability):

Method Input Crash site
metaWeblog.newPost nested array in mt_keywords wp_set_object_terms() (via tags_input)
metaWeblog.editPost same same
wp.newTerm array name the server's own trim(), before wp_insert_term()
wp.editTerm array name the server's own trim(), before wp_update_term()
wp.newCategory array name wp_insert_category()

These are now fixed:

  • 7ac3e7e: wp.newTerm and wp.editTerm return a 403 "Invalid term name." error for a name that is not a string or number.
  • 7f728ca: wp.newCategory does the same. It had no tests, so a test class was added.
  • 7a115d9: wp_set_object_terms() validates every term up front and returns an invalid_term_name error before any terms or relationships change. null and false are still skipped, as before, and are now cast to string before trim(), which avoids a PHP 8.1 deprecation notice. The metaWeblog methods ignore the tag-setting result, so such a post is saved without the requested tags rather than crashing.
  • 88f20e1: escape() now declares a template type for its by-reference parameter, so $args keeps its docblock-derived shape after escaping. This was needed for the new wp.newTerm guard to pass PHPStan, and drops the file's level 10 error count from 659 to 448.

The remaining sinks, wp_update_term(), wp_remove_object_terms(), and term_exists(), are not reachable over XML-RPC with a malformed name (wp.editTerm now rejects it before calling wp_update_term()), so they are left for a follow-up ticket.

Comment thread src/wp-includes/taxonomy.php Outdated
}

if ( '' === trim( $term ) ) {
if ( ! is_scalar( $term ) || '' === trim( $term ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Two points about the guard itself:

  • A non-scalar $term returns empty_term_name ("A name is required for this term."), which misdescribes the problem: the name was provided, just with the wrong type. The function already has an invalid_term_name code a few lines below, which would let callers distinguish "missing" from "malformed".
  • is_scalar() accepts booleans, so true is silently inserted (or matched) as a term named "1". is_string( $term ) || is_int( $term ) || is_float( $term ) would reject it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Both points are addressed:

  • 4188078 replaces is_scalar() with is_string() || is_int() || is_float(), so true is rejected rather than inserted as "1".
  • 19ef32b returns invalid_term_name ("Invalid term name.") for arrays, objects, and true. null and false still return empty_term_name, as they did before this PR (they reduced to an empty string under trim()), so no existing error code changes for them.

test_wp_insert_term_invalid_term_name_type now covers all five types with their expected error codes.

Comment thread src/wp-includes/taxonomy.php Outdated
* @since 2.3.0
* @since 7.2.0 A non-scalar `$term` now returns a WP_Error instead of causing a fatal error.
*
* @param string $term The term name to add.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

The docblock still declares @param string $term, while the new tests assert that ints and floats are supported (stored as their string form). That mismatch is why the tests need @phpstan-ignore argument.type. Widening the type to string|int|float would make the contract explicit in the developer docs and remove the ignores in the numeric test.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Addressed in 1f8bcc4. The $term type is now string|int|float, noting that a number is stored as its string form, and the @phpstan-ignore in the numeric test was removed. The pre_insert_term filter docblock still says string|WP_Error and was left unchanged.

* @param mixed $name The term name to insert.
*/
public function test_wp_insert_term_non_scalar_term_name( $name ): void {
$found = wp_insert_term( $name, 'post_tag' ); // @phpstan-ignore argument.type (Intentionally passing scalars.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

The ignore justification says "Intentionally passing scalars.", but this test passes non-scalars (an array and an object). It appears to have been copied from the numeric test below, where it is accurate.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Addressed in 4188078. The test was renamed to test_wp_insert_term_invalid_term_name_type (it now also covers true, false, and null, which are scalars), and the ignore comment now reads "Intentionally passing invalid types."

}

/**
* Data provider.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Nit: this provider docblock could follow the same conventions as the providers in wpInsertTerm.php: a {@see} reference to the test method it feeds, and a narrowed key type (e.g. array<non-falsy-string, array{ mixed }>).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Comment by Claude Opus 5.5

Addressed in 51ab927. All three data providers in this file now reference their test with {@see} and use truthy-string keys.

westonruter and others added 12 commits October 29, 2026 18:24
The is_string() guard rejected term names sent as <int> or <double>,
such as a tag named 2024, which previously worked via get_term_by()
and wp_insert_term(). Cast ints and floats to strings instead, and
reject only other types such as arrays and booleans.

Replace the 'integer' invalid case with 'boolean', and add a test
asserting numeric names are assigned using their string form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ambiguous names list comes from array_keys(), which turns numeric
names like "2024" into integer keys. Since term names are now always
strings by the time they are checked, the strict in_array() never
matched them, so a hierarchical taxonomy with two terms named "2024"
silently resolved to whichever term get_term_by() returned first.
Cast the keys back to strings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The is_scalar() guard let booleans through, so true was inserted or
matched as a term named "1". Accept only strings, ints, and floats.

Rename the test to reflect that it covers invalid types rather than
just non-scalars, add true, false, and null cases, and correct the
ignore comment, which said scalars were being passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The function accepts ints and floats and stores them as strings, which
the tests now assert, but the docblock declared only string. Widen
the $term type to string|int|float so the contract is explicit, which
also makes the PHPStan ignore in the numeric test unnecessary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A term name of the wrong type, such as an array, an object, or true,
returned empty_term_name ("A name is required for this term."), which
misdescribes the problem: a name was given, just not a usable one.
Return the existing invalid_term_name code instead, so callers can
tell a missing name from a malformed one.

Null and false still return empty_term_name, as they did before this
change, since they reduced to an empty string under trim().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reference the test each provider feeds with {@see}, and narrow the
key type to truthy-string, as done for the wp_insert_term() providers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every other validation error in the terms_names block, such as the
ambiguous term name error, uses fault code 401. Use the same code for
an invalid term name, so clients see consistent codes for this input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A per-taxonomy value sent as a single string or int, rather than a
list, reached foreach unvalidated. That emitted a "foreach() argument
must be of type array|object" warning, and the terms were silently
ignored instead of an error being returned. Return the existing
"Invalid term ID." (403) or "Invalid term name." (401) error instead,
matching the codes already used for invalid items in each list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
escape() takes its argument by reference with a string|array type, so
after every `$this->escape( $args )` call PHPStan widened `$args` to
string|array, and each `$args[N]` read became mixed. That discarded
the argument shapes derived from the method docblocks and produced
hundreds of errors across the class.

Declare escape() with a template type for both the parameter and its
by-reference output, so callers keep their argument shapes. This
drops the file's level 10 error count from 659 to 448. PHPStan cannot
prove that the by-reference loop preserves the shape, so that one
error is ignored with a justification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both methods passed the name straight to trim(), so an array name
caused a fatal TypeError before wp_insert_term() or wp_update_term()
was ever reached, and true was trimmed to "1". Return a 403 "Invalid
term name." error unless the name is a string or number, matching the
code these methods already use for an empty name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The category name was passed to wp_insert_category(), whose trim()
caused a fatal TypeError for an array name. Return a 403 "Invalid term
name." error unless the name is a string or number, matching the term
methods.

There were no tests for wp.newCategory, so add a test class covering
both a valid name and invalid name types.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A term that was not a string or number, such as a nested array in a
metaWeblog.newPost or metaWeblog.editPost mt_keywords list, reached
trim() and caused a fatal TypeError. Validate every term up front and
return an invalid_term_name error before any terms or relationships
are changed, so a bad item cannot leave the object half updated.

Null and false are still skipped, as before. Cast to string before
the existing trim() so skipping null no longer emits a PHP 8.1
deprecation notice.

The metaWeblog methods ignore the result of setting tags, so the post
is still saved, without the requested tags, rather than crashing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@westonruter

Copy link
Copy Markdown
Member

@josephscott Pushed up some commits that were made to apply feedback from some rounds of Claude reviews.

@josephscott

Copy link
Copy Markdown
Contributor Author

@westonruter thank you - I've updated it with a few more small adjustments to try and keep the behavior mostly consistent with trunk.

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.

3 participants