5073 Commits

Author SHA1 Message Date
DDL 3a6d9c6238 fix(git): scrub inherited GIT_DIR on worktree-local plumbing (#4082) 2026-09-14 00:33:13 -07:00
Maximilian Roos 7e43837527 Keep composite action pins current (#4101)
Dependabot only scanned workflow action references, so setup-uv in the
Tend composite setup action lagged behind. This aligns setup-uv at
v10.1.0 and extends the existing daily GitHub Actions update to every
composite action directory.

> _This was written by Codex on behalf of @max-sixty_
2026-09-13 23:28:35 -07:00
dependabot[bot] 705c7c6643 chore: bump the patch group with 5 updates (#4095)
Bumps the patch group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [askama](https://github.com/askama-rs/askama) | `0.16.0` | `0.16.1` |
| [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) |
`0.5.16` | `0.5.17` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.14.1` |
`2.14.2` |
| [termimad](https://github.com/Canop/termimad) | `0.35.3` | `0.35.4` |
| [open](https://github.com/Byron/open-rs) | `5.4.3` | `5.4.4` |

Updates `askama` from 0.16.0 to 0.16.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/askama-rs/askama/releases">askama's
releases</a>.</em></p>
<blockquote>
<h2>v0.16.1</h2>
<h2>What's Changed</h2>
<ul>
<li>docs: explain how to install by enabling feature specific for each
framework by <a
href="https://github.com/pinage404"><code>@​pinage404</code></a> in <a
href="https://redirect.github.com/askama-rs/askama/pull/742">askama-rs/askama#742</a></li>
<li>Fix new clippy lint by <a
href="https://github.com/GuillaumeGomez"><code>@​GuillaumeGomez</code></a>
in <a
href="https://redirect.github.com/askama-rs/askama/pull/743">askama-rs/askama#743</a></li>
<li>Fix CI by <a
href="https://github.com/GuillaumeGomez"><code>@​GuillaumeGomez</code></a>
in <a
href="https://redirect.github.com/askama-rs/askama/pull/747">askama-rs/askama#747</a></li>
<li>Upgrade to syn 3 by <a
href="https://github.com/paolobarbolini"><code>@​paolobarbolini</code></a>
in <a
href="https://redirect.github.com/askama-rs/askama/pull/745">askama-rs/askama#745</a></li>
<li>book: fix link by <a
href="https://github.com/antonmosich"><code>@​antonmosich</code></a> in
<a
href="https://redirect.github.com/askama-rs/askama/pull/754">askama-rs/askama#754</a></li>
<li>Fix new clippy lint by <a
href="https://github.com/GuillaumeGomez"><code>@​GuillaumeGomez</code></a>
in <a
href="https://redirect.github.com/askama-rs/askama/pull/755">askama-rs/askama#755</a></li>
<li>Add missing compount assignment in the book syntax overview by <a
href="https://github.com/GuillaumeGomez"><code>@​GuillaumeGomez</code></a>
in <a
href="https://redirect.github.com/askama-rs/askama/pull/757">askama-rs/askama#757</a></li>
<li>Fix wrong &quot;custom escaper example&quot; link in the book by <a
href="https://github.com/GuillaumeGomez"><code>@​GuillaumeGomez</code></a>
in <a
href="https://redirect.github.com/askama-rs/askama/pull/759">askama-rs/askama#759</a></li>
<li>Add possibility to specify <code>let</code>/<code>set</code> block
type by <a
href="https://github.com/GuillaumeGomez"><code>@​GuillaumeGomez</code></a>
in <a
href="https://redirect.github.com/askama-rs/askama/pull/760">askama-rs/askama#760</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/pinage404"><code>@​pinage404</code></a>
made their first contribution in <a
href="https://redirect.github.com/askama-rs/askama/pull/742">askama-rs/askama#742</a></li>
<li><a
href="https://github.com/antonmosich"><code>@​antonmosich</code></a>
made their first contribution in <a
href="https://redirect.github.com/askama-rs/askama/pull/754">askama-rs/askama#754</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/askama-rs/askama/compare/v0.16.0...v0.16.1">https://github.com/askama-rs/askama/compare/v0.16.0...v0.16.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/askama-rs/askama/commit/9ae4d5bdf4352b35e34106e38944c90d7a7ede3e"><code>9ae4d5b</code></a>
Merge pull request <a
href="https://redirect.github.com/askama-rs/askama/issues/761">#761</a>
from GuillaumeGomez/update</li>
<li><a
href="https://github.com/askama-rs/askama/commit/c788325d46efab3b59b7c3ba081b6a83f589afef"><code>c788325</code></a>
Update crates version to <code>0.16.1</code></li>
<li><a
href="https://github.com/askama-rs/askama/commit/aab8bc42436e9008cbf0cf10799177252f5503b8"><code>aab8bc4</code></a>
Merge pull request <a
href="https://redirect.github.com/askama-rs/askama/issues/760">#760</a>
from GuillaumeGomez/let-ty</li>
<li><a
href="https://github.com/askama-rs/askama/commit/1043eaef5d6be53be59d2e7d7028a050ad8e4a3d"><code>1043eae</code></a>
Update book to mention that we can specify the type of the variable</li>
<li><a
href="https://github.com/askama-rs/askama/commit/a2e3b49824c970404776f1d7403bea65019073e2"><code>a2e3b49</code></a>
Add possibility to specify <code>let</code>/<code>set</code> block
type</li>
<li><a
href="https://github.com/askama-rs/askama/commit/0c9c2ee617b05667eef4569c268df9efbd1f9139"><code>0c9c2ee</code></a>
Merge pull request <a
href="https://redirect.github.com/askama-rs/askama/issues/759">#759</a>
from askama-rs/GuillaumeGomez-patch-1</li>
<li><a
href="https://github.com/askama-rs/askama/commit/cc3bde8b86857350fb3c08e23dd41cc886014d08"><code>cc3bde8</code></a>
Fix wrong &quot;custom escaper example&quot; link in the book</li>
<li><a
href="https://github.com/askama-rs/askama/commit/e47575b12798f77638932fe7626285a1582f4a67"><code>e47575b</code></a>
Merge pull request <a
href="https://redirect.github.com/askama-rs/askama/issues/757">#757</a>
from GuillaumeGomez/book-compound</li>
<li><a
href="https://github.com/askama-rs/askama/commit/0bf45f2e71734bd9d57c4aaf39314faad6a5f8a5"><code>0bf45f2</code></a>
Add missing compount assignment in the book syntax overview</li>
<li><a
href="https://github.com/askama-rs/askama/commit/f98f8c5c1779c315977cac652cbcc12d6e1a147b"><code>f98f8c5</code></a>
Merge pull request <a
href="https://redirect.github.com/askama-rs/askama/issues/755">#755</a>
from GuillaumeGomez/fix-clippy</li>
<li>Additional commits viewable in <a
href="https://github.com/askama-rs/askama/compare/v0.16.0...v0.16.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `crossbeam-channel` from 0.5.16 to 0.5.17
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crossbeam-rs/crossbeam/releases">crossbeam-channel's
releases</a>.</em></p>
<blockquote>
<h2>crossbeam-channel 0.5.17</h2>
<ul>
<li>Fix UB in bounded channel when <code>SelectedOperation</code> is
leaked. (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1295">#1295</a>)</li>
<li>Fix behavior inconsistency on already received case in
<code>at()</code>. (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1296">#1296</a>)</li>
<li>Handle overflow in bounded channel initialization. (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1301">#1301</a>)</li>
<li>Use 64-bit index on 32-bit platforms if 64-bit atomic is available.
(<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1321">#1321</a>)</li>
<li>Update MSRV policy to support 1 year instead of 6 months to meet
rayon's MSRV policy. (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1284">#1284</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/2920c984290229ab4e0ca0452ef09e48a82063f3"><code>2920c98</code></a>
Prepare for the next release</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/808b75a4cbbb59eab83a92cf867a3c771795f959"><code>808b75a</code></a>
ci: Update codegen job</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/46774e09313d4601c23f77da0b078c914194c152"><code>46774e0</code></a>
channel: Document that send_timeout sends an available message even if
the ti...</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/89a3fe4025857397a1adfc954957687d4dce9c93"><code>89a3fe4</code></a>
epoch: Make Shared::null const</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/383d74adcda222f99d54b4e80b55cce6bf30f142"><code>383d74a</code></a>
Use *::MAX associated constants</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/a30b825e6de35ecc4762a55656f63b4dbf4ccb8a"><code>a30b825</code></a>
channel,deque,queue: Use AtomicU64/u64 in head/tail index if
available</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/a0e4d2929e4bf670bf05aad548880656e187a51e"><code>a0e4d29</code></a>
Replace iterative capacity growth with <code>next_power_of_two</code>
(<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1216">#1216</a>)</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/94f74d26240f5d49e61d56ac10111e6527dbcfe6"><code>94f74d2</code></a>
Recognize x86_64-unknown-linux-gnutsan in build script</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/30e5963e4c0a9fc6626bd6417528c4f621e3838e"><code>30e5963</code></a>
epoch: Add missing fence emulation for tsan</li>
<li><a
href="https://github.com/crossbeam-rs/crossbeam/commit/708a6bd582d1ee482183e186e98527b41bffe565"><code>708a6bd</code></a>
Handle overflow in bounded channel/queue initialization (<a
href="https://redirect.github.com/crossbeam-rs/crossbeam/issues/1301">#1301</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-channel-0.5.16...crossbeam-channel-0.5.17">compare
view</a></li>
</ul>
</details>
<br />

Updates `indexmap` from 2.14.1 to 2.14.2
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md">indexmap's
changelog</a>.</em></p>
<blockquote>
<h2>2.14.2 (2026-09-04)</h2>
<ul>
<li>Fix item hygiene in map and set macros. Previously, an internal
<code>const CAP</code>
could shadow the same name in the caller's namespace.</li>
<li>Allow <code>const</code> initialization of empty
<code>indexmap_with_default!</code> and
<code>indexset_with_default!</code>. The hasher may also be omitted if
it's inferrable.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/indexmap-rs/indexmap/commit/41a870887c4c77adf665886e63df08f406bfe37a"><code>41a8708</code></a>
Merge pull request <a
href="https://redirect.github.com/indexmap-rs/indexmap/issues/450">#450</a>
from cuviper/macros</li>
<li><a
href="https://github.com/indexmap-rs/indexmap/commit/0fb7b5c813c94dcb16f220d249e42a7b9e4ea44d"><code>0fb7b5c</code></a>
Release 2.14.2</li>
<li><a
href="https://github.com/indexmap-rs/indexmap/commit/55e6b28278f242b4d4190a14b6e86c09580dd75a"><code>55e6b28</code></a>
Improve the empty macro cases</li>
<li><a
href="https://github.com/indexmap-rs/indexmap/commit/c067355e1ca5ec39348f42dcee582d4f222c3295"><code>c067355</code></a>
Fix item hygiene in user macros</li>
<li>See full diff in <a
href="https://github.com/indexmap-rs/indexmap/compare/2.14.1...2.14.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `termimad` from 0.35.3 to 0.35.4
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Canop/termimad/blob/main/CHANGELOG.md">termimad's
changelog</a>.</em></p>
<blockquote>
<h3>v0.35.4 - 2026-09-05</h3>
<ul>
<li>fix <code>parse_color</code> returning the light variant for
<code>darkblue</code>, <code>darkcyan</code> and
<code>darkyellow</code>, and accepting strings merely containing a color
name</li>
</ul>
<p><!-- raw HTML omitted --><!-- raw HTML omitted --></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/Canop/termimad/commits">compare view</a></li>
</ul>
</details>
<br />

Updates `open` from 5.4.3 to 5.4.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/Byron/open-rs/releases">open's
releases</a>.</em></p>
<blockquote>
<h2>v5.4.4</h2>
<h3>Bug Fixes</h3>
<ul>
<li>
<p>open Windows paths without wildcard expansion</p>
<!-- raw HTML omitted -->
<p>Opening a child of a bracket-named directory fails because
Start-Process
resolves parent directories as PowerShell wildcard patterns. The
isolated
Windows regression test reproduced WildcardPatternException for a copied
executable under &quot;【Tiny Asa】 [77P7V-712MB]\child&quot; before this
change.</p>
<p>Use Test-Path and Invoke-Item with LiteralPath for existing items,
retaining
Start-Process for URLs and application names. These cmdlets also work
under
PowerShell Constrained Language Mode. Share the embedded script between
Windows and WSL, keep targets in environment data, and stop on launch
errors
to report a nonzero exit status. Preserve the security boundary
established
in fd29861: cmd /c start remains opt-in through the insecure feature. No
previously removed launcher options are restored.</p>
<p>The integration test launches only a copy of its own test binary,
which
records its executable path and exits. It checks absolute and relative
paths
with invalid and valid bracket patterns, Unicode, backticks, quotes,
shell
metacharacters, and leading dashes in normal and constrained PowerShell
sessions, plus failure for a missing executable. It requires neither
Explorer
nor registered document or URL handlers. Adjust the existing fallback
assertion to also allow the opt-in cmd launcher after Explorer with all
features enabled.</p>
<p>Validated locally on Windows with PowerShell 5.1.26100.33438 and
rustc 1.97.1:
cargo test and cargo test --all-features each passed all 19 tests,
including
the behavioral regression. git diff --check passed, and cargo
package --list includes the embedded script. Test-Path returned false
without
errors for representative https, mailto, and file URLs. Actual GUI
folder,
document, URL handling and WSL interop were not exercised locally.</p>
</li>
</ul>
<h3>Commit Statistics</h3>
<ul>
<li>2 commits contributed to the release.</li>
<li>8 days passed between releases.</li>
<li>1 commit was understood as <a
href="https://www.conventionalcommits.org">conventional</a>.</li>
<li>1 unique issue was worked on: <a
href="https://redirect.github.com/Byron/open-rs/issues/132">#132</a></li>
</ul>
<h3>Commit Details</h3>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<ul>
<li><strong><a
href="https://redirect.github.com/Byron/open-rs/issues/132">#132</a></strong>
<ul>
<li>Open Windows paths without wildcard expansion (ad95c40)</li>
</ul>
</li>
<li><strong>Uncategorized</strong></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Byron/open-rs/blob/main/changelog.md">open's
changelog</a>.</em></p>
<blockquote>
<h2>5.4.4 (2026-09-10)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>
<p><!-- raw HTML omitted --> open Windows paths without wildcard
expansion</p>
<!-- raw HTML omitted -->
<p>Opening a child of a bracket-named directory fails because
Start-Process
resolves parent directories as PowerShell wildcard patterns. The
isolated
Windows regression test reproduced WildcardPatternException for a copied
executable under &quot;【Tiny Asa】 [77P7V-712MB]\child&quot; before this
change.</p>
<p>Use Test-Path and Invoke-Item with LiteralPath for existing items,
retaining
Start-Process for URLs and application names. These cmdlets also work
under
PowerShell Constrained Language Mode. Share the embedded script between
Windows and WSL, keep targets in environment data, and stop on launch
errors
to report a nonzero exit status. Preserve the security boundary
established
in fd29861: cmd /c start remains opt-in through the insecure feature. No
previously removed launcher options are restored.</p>
<p>The integration test launches only a copy of its own test binary,
which
records its executable path and exits. It checks absolute and relative
paths
with invalid and valid bracket patterns, Unicode, backticks, quotes,
shell
metacharacters, and leading dashes in normal and constrained PowerShell
sessions, plus failure for a missing executable. It requires neither
Explorer
nor registered document or URL handlers. Adjust the existing fallback
assertion to also allow the opt-in cmd launcher after Explorer with all
features enabled.</p>
<p>Validated locally on Windows with PowerShell 5.1.26100.33438 and
rustc 1.97.1:
cargo test and cargo test --all-features each passed all 19 tests,
including
the behavioral regression. git diff --check passed, and cargo
package --list includes the embedded script. Test-Path returned false
without
errors for representative https, mailto, and file URLs. Actual GUI
folder,
document, URL handling and WSL interop were not exercised locally.</p>
</li>
</ul>
<h3>Commit Statistics</h3>
<!-- raw HTML omitted -->
<ul>
<li>2 commits contributed to the release.</li>
<li>8 days passed between releases.</li>
<li>1 commit was understood as <a
href="https://www.conventionalcommits.org">conventional</a>.</li>
<li>1 unique issue was worked on: <a
href="https://redirect.github.com/Byron/open-rs/issues/132">#132</a></li>
</ul>
<h3>Commit Details</h3>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/Byron/open-rs/commit/ba35e001028f03290eaae2cc1cad8411322507b2"><code>ba35e00</code></a>
Release open v5.4.4</li>
<li><a
href="https://github.com/Byron/open-rs/commit/45317f8a4fdc43218dcc3418156e677e35662dff"><code>45317f8</code></a>
Merge pull request <a
href="https://redirect.github.com/Byron/open-rs/issues/133">#133</a>
from Byron/fix-open-on-windows</li>
<li><a
href="https://github.com/Byron/open-rs/commit/ad95c40f98144b368ec759492edecd0b8b20b672"><code>ad95c40</code></a>
fix: open Windows paths without wildcard expansion (<a
href="https://redirect.github.com/Byron/open-rs/issues/132">#132</a>)</li>
<li>See full diff in <a
href="https://github.com/Byron/open-rs/compare/v5.4.3...v5.4.4">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-13 22:29:03 -07:00
dependabot[bot] 4f70286fb2 chore: bump jsonschema from 0.53.0 to 0.56.0 (#4096)
Bumps [jsonschema](https://github.com/Stranger6667/jsonschema) from
0.53.0 to 0.56.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/Stranger6667/jsonschema/releases">jsonschema's
releases</a>.</em></p>
<blockquote>
<h2>[Python] Release 0.56.0</h2>
<h3>Added</h3>
<ul>
<li><code>canonical.RawReason</code>, what stopped a run from modeling a
document, and <code>RawView.reason</code> and
<code>RawView.pointer</code>, carrying it beside the subschema the run
stopped on.</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Canonicalization of a <code>oneOf</code> whose branches share a
region too wide to expand, which spent the document's whole intersection
allowance on that choice and kept the document <code>Raw</code>.</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Preparing or building a schema that names no base URI parses the
default one once for the process instead of once per schema.</li>
<li>Canonicalization reads the facets no checker covers once per node
instead of once per containment query.</li>
</ul>
<h2>[Ruby] Release 0.56.0</h2>
<h3>Added</h3>
<ul>
<li><code>JSONSchema::Canonical::RawReason</code>, what stopped a run
from modeling a document, and <code>RawView#reason</code> and
<code>RawView#pointer</code>, carrying it beside the subschema the run
stopped on.</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Canonicalization of a <code>oneOf</code> whose branches share a
region too wide to expand, which spent the document's whole intersection
allowance on that choice and kept the document <code>Raw</code>.</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Preparing or building a schema that names no base URI parses the
default one once for the process instead of once per schema.</li>
<li>Canonicalization reads the facets no checker covers once per node
instead of once per containment query.</li>
</ul>
<h2>[Rust] Release 0.56.0</h2>
<h3>Added</h3>
<ul>
<li><code>canonical::RawReason</code>, what stopped a run from modeling
a document, and <code>canonical::RawView</code>, carrying it beside the
document and a pointer to the subschema the run stopped on.</li>
<li><code>ValidationOptions::is_known_format</code>, whether a
<code>format</code> of that name is checked under a draft.</li>
</ul>
<h3>Changed</h3>
<ul>
<li><strong>BREAKING</strong>:
<code>canonical::CanonicalView::Raw</code> carries a
<code>canonical::RawView</code> in place of the document alone.</li>
<li>Canonicalization of a <code>oneOf</code> whose branches share a
region too wide to expand, which spent the document's whole intersection
allowance on that choice and kept the document <code>Raw</code>.</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Preparing or building a schema that names no base URI parses the
default one once for the process instead of once per schema.</li>
<li>Canonicalizing several subschemas of one prepared document compiles
each pattern once for the document instead of once per call.</li>
<li>Canonicalization reads the facets no checker covers once per node
instead of once per containment query.</li>
</ul>
<h2>[Python] Release 0.55.1</h2>
<h3>Changed</h3>
<ul>
<li>Canonicalization of an <code>anyOf</code> over an <code>allOf</code>
through a <code>$ref</code> to a union, which left that union nested
inside the outer one.</li>
<li>Canonicalization of an <code>anyOf</code> whose branch narrowing
runs out of intersections, which left <code>true</code> as a branch
inside the union.</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Stranger6667/jsonschema/blob/master/CHANGELOG.md">jsonschema's
changelog</a>.</em></p>
<blockquote>
<h2>[0.56.0] - 2026-09-10</h2>
<h3>Added</h3>
<ul>
<li><code>canonical::RawReason</code>, what stopped a run from modeling
a document, and <code>canonical::RawView</code>, carrying it beside the
document and a pointer to the subschema the run stopped on.</li>
<li><code>ValidationOptions::is_known_format</code>, whether a
<code>format</code> of that name is checked under a draft.</li>
</ul>
<h3>Changed</h3>
<ul>
<li><strong>BREAKING</strong>:
<code>canonical::CanonicalView::Raw</code> carries a
<code>canonical::RawView</code> in place of the document alone.</li>
<li>Canonicalization of a <code>oneOf</code> whose branches share a
region too wide to expand, which spent the document's whole intersection
allowance on that choice and kept the document <code>Raw</code>.</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Preparing or building a schema that names no base URI parses the
default one once for the process instead of once per schema.</li>
<li>Canonicalizing several subschemas of one prepared document compiles
each pattern once for the document instead of once per call.</li>
<li>Canonicalization reads the facets no checker covers once per node
instead of once per containment query.</li>
</ul>
<h2>[0.55.1] - 2026-09-08</h2>
<h3>Changed</h3>
<ul>
<li>Canonicalization of an <code>anyOf</code> over an <code>allOf</code>
through a <code>$ref</code> to a union, which left that union nested
inside the outer one.</li>
<li>Canonicalization of an <code>anyOf</code> whose branch narrowing
runs out of intersections, which left <code>true</code> as a branch
inside the union.</li>
</ul>
<h2>[0.55.0] - 2026-09-06</h2>
<h3>Changed</h3>
<ul>
<li><strong>BREAKING</strong>:
<code>canonical::ObjectViolationView</code> gained the
<code>PatternValueFails</code> variant, which negation records for a
<code>patternProperties</code> entry.</li>
<li>Canonicalization of <code>not</code> over
<code>patternProperties</code>, which kept the entry under
<code>not</code> instead of recording the demand a key breaks.</li>
<li>Canonicalization of <code>unevaluated*</code> beside a conditional
reaching no key or index the node already evaluates, which spent a case
on it.</li>
<li>Canonicalization of a conditional split outgrowing its per-node case
budget, which kept documents like the Open API 3.2 meta-schema
<code>Raw</code>.</li>
<li>Canonicalization of an <code>anyOf</code> over objects sharing a
<code>properties</code> key under <code>patternProperties</code>, which
settled only on a second pass.</li>
<li>Canonicalization of <code>not</code> over an <code>allOf</code>
folded through a reference, which settled only on a second pass.</li>
<li>Canonicalization of a <code>multipleOf</code> divisor past
<code>f64</code> precision, which was not taken to divide itself.</li>
<li>Canonicalization of an <code>anyOf</code> over a value beside a
window pinned to it, which settled only on a second pass.</li>
<li>Canonicalization of <code>minProperties: 1</code> beside a
<code>not</code> that already demands a key, which settled only on a
second pass.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li><code>absolute_keyword_location</code> naming the sibling keyword
whose validator carries the check: <code>maxLength</code> beside
<code>minLength</code>, <code>minItems</code>, <code>maxItems</code> or
<code>type</code> beside <code>items</code>, and a two-name
<code>required</code> beside <code>properties</code>. <a
href="https://redirect.github.com/Stranger6667/jsonschema/issues/1579">#1579</a></li>
<li><code>schemaLocation</code> in <code>evaluate</code> output naming
<code>minLength</code> for a <code>maxLength</code> failure. <a
href="https://redirect.github.com/Stranger6667/jsonschema/issues/1579">#1579</a></li>
</ul>
<h2>[0.54.0] - 2026-09-06</h2>
<h3>Added</h3>
<ul>
<li><code>backend = SerdeJson</code> on
<code>#[jsonschema::validator]</code>, generating a validator that reads
<code>serde_json::Value</code>.</li>
<li><code>PreparedDocument::unsatisfiable_pointers</code>, listing every
subschema no value satisfies.</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/c5ce51d883f25bcd0b35ee245f88c19f9871bd9d"><code>c5ce51d</code></a>
chore(ruby): Release 0.56.0</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/1e244c994dd81a1feb7801556a813c6bf2d45dad"><code>1e244c9</code></a>
chore(rust): Release 0.56.0</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/507d66a153dcbde9c4956a27042308dfff71b295"><code>507d66a</code></a>
build: Switch to weekly dependabot</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/776294298fd9a280478fb905098cc0afa0432136"><code>7762942</code></a>
build: Increase timeout for s390x test job</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/7d4b40dbbdfb3c730f02f9ad6b761df5bd55d8b5"><code>7d4b40d</code></a>
test: Update hegeltest to 0.41</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/b2622e56c735ac4c6710346d3b0d3750aec5033e"><code>b2622e5</code></a>
build(deps): bump taiki-e/install-action from 2.87.3 to 2.87.8</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/c983788ed6e7eb8a4cd975bba82546b789fde2a1"><code>c983788</code></a>
build(deps): update wasm-bindgen requirement from =0.2.127 to
=0.2.128</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/6e7e8f6899567a1ef8f1a79da4f62c3536c2bfb6"><code>6e7e8f6</code></a>
build(deps): bump crates/jsonschema/tests/suite</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/3f2c0a05118cdf5a380d7c371b2c8395b45a582c"><code>3f2c0a0</code></a>
perf: Preparing or building a schema that names no base URI parses the
defaul...</li>
<li><a
href="https://github.com/Stranger6667/jsonschema/commit/2b4f25b2727c4ac08ccf2d64477bf203cf0e8252"><code>2b4f25b</code></a>
perf: More benchmarks</li>
<li>Additional commits viewable in <a
href="https://github.com/Stranger6667/jsonschema/compare/ruby-v0.53.0...ruby-v0.56.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=jsonschema&package-manager=cargo&previous-version=0.53.0&new-version=0.56.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-13 22:24:13 -07:00
dependabot[bot] 8d86e12cce chore: bump rstest from 0.26.1 to 0.27.0 (#4098)
Bumps [rstest](https://github.com/la10736/rstest) from 0.26.1 to 0.27.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/la10736/rstest/releases">rstest's
releases</a>.</em></p>
<blockquote>
<h2>v0.27.0</h2>
<h2>[0.27.0] 2026/9/6</h2>
<h3>Changed</h3>
<ul>
<li>Bump msrv to 1.85.0 both for <code>rstest</code> and
<code>rstest_reuse</code></li>
<li>Disabled default features of <code>futures-util</code></li>
</ul>
<h3>Added</h3>
<ul>
<li>Doc comments before <code>#[values(...)]</code> entries can be used
to override the generated matrix
test names (both for the legacy <code>arg =&gt; [..]</code> syntax and
the new attribute form).
See <a
href="https://redirect.github.com/la10736/rstest/pull/321">#321</a>
thanks to <a
href="https://github.com/orhun"><code>@​orhun</code></a>.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Use fully-qualified <code>core</code> import. See <a
href="https://redirect.github.com/la10736/rstest/pull/336">#336</a>.</li>
<li>Fix <code>mut</code> arguments failing to compile with
<code>#[trace]</code>. See <a
href="https://redirect.github.com/la10736/rstest/pull/345">#345</a>
thanks to <a
href="https://github.com/super-cooper"><code>@​super-cooper</code></a>.</li>
<li>Fix compilation under bazel by upgrading proc-macro-crate to
3.4.0.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/la10736/rstest/blob/master/CHANGELOG.md">rstest's
changelog</a>.</em></p>
<blockquote>
<h2>[0.27.0] 2026/9/6</h2>
<h3>Changed</h3>
<ul>
<li>Bump msrv to 1.85.0 both for <code>rstest</code> and
<code>rstest_reuse</code></li>
<li>Disabled default features of <code>futures-util</code></li>
</ul>
<h3>Added</h3>
<ul>
<li>Doc comments before <code>#[values(...)]</code> entries can be used
to override the generated matrix
test names (both for the legacy <code>arg =&gt; [..]</code> syntax and
the new attribute form).
See <a
href="https://redirect.github.com/la10736/rstest/pull/321">#321</a>
thanks to <a
href="https://github.com/orhun"><code>@​orhun</code></a>.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Use fully-qualified <code>core</code> import. See <a
href="https://redirect.github.com/la10736/rstest/pull/336">#336</a>.</li>
<li>Fix <code>mut</code> arguments failing to compile with
<code>#[trace]</code>. See <a
href="https://redirect.github.com/la10736/rstest/pull/345">#345</a>
thanks to <a
href="https://github.com/super-cooper"><code>@​super-cooper</code></a>.</li>
<li>Fix compilation under bazel by upgrading proc-macro-crate to
3.4.0.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/la10736/rstest/commit/59cd3d1919fc471922297606b8819af4e5bfd472"><code>59cd3d1</code></a>
Release 0.27.0</li>
<li><a
href="https://github.com/la10736/rstest/commit/0821ebc65d0c8434f0d9b7773a23043549313426"><code>0821ebc</code></a>
test: Add E2E test for mut arguments with #[trace]</li>
<li><a
href="https://github.com/la10736/rstest/commit/509ffef32538324bd75d0addf49ee7e0296bff81"><code>509ffef</code></a>
fix: <code>mut</code> arguments with <code>#[trace]</code></li>
<li><a
href="https://github.com/la10736/rstest/commit/043437d63956f1c9e3f6284c4463169cb484cd3b"><code>043437d</code></a>
fix: Resolve clippy warnings and truncate long test project names</li>
<li><a
href="https://github.com/la10736/rstest/commit/9aa8d1a3c51627ec87d0620abda9707488a6f8fe"><code>9aa8d1a</code></a>
fix: Suppress nightly cargo lints in test scaffolding</li>
<li><a
href="https://github.com/la10736/rstest/commit/3d3c76c4fb7215aae92008e390b7fb618ecd5522"><code>3d3c76c</code></a>
fix: Bump rstest_test MSRV to 1.85 and mark as unpublished</li>
<li><a
href="https://github.com/la10736/rstest/commit/d9ae990e323b6910d39364d94876a86b003b4729"><code>d9ae990</code></a>
chore: Add changelog entry</li>
<li><a
href="https://github.com/la10736/rstest/commit/05d4b1a817c1ee4684e1cff728d805f3a647fc0b"><code>05d4b1a</code></a>
fix: Use fully-qualified core import</li>
<li><a
href="https://github.com/la10736/rstest/commit/6da56a112e65b96685e06be41f8d98a84a6e7452"><code>6da56a1</code></a>
Bump msrv to 1.85 also for rstest_reuse (<a
href="https://redirect.github.com/la10736/rstest/issues/342">#342</a>)</li>
<li><a
href="https://github.com/la10736/rstest/commit/1e9963bbc1a0feff27afdd1c6cec25d00c96d607"><code>1e9963b</code></a>
Add CLAUDE.md for Claude Code guidance (<a
href="https://redirect.github.com/la10736/rstest/issues/340">#340</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/la10736/rstest/compare/v0.26.1...v0.27.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rstest&package-manager=cargo&previous-version=0.26.1&new-version=0.27.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-13 22:23:12 -07:00
dependabot[bot] ac23e56d61 chore: bump taiki-e/install-action from 2.87.8 to 2.87.11 (#4093)
Bumps
[taiki-e/install-action](https://github.com/taiki-e/install-action) from
2.87.8 to 2.87.11.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/taiki-e/install-action/releases">taiki-e/install-action's
releases</a>.</em></p>
<blockquote>
<h2>2.87.11</h2>
<ul>
<li>
<p>Update <code>biome@latest</code> to 2.5.13.</p>
</li>
<li>
<p>Update <code>uv@latest</code> to 0.12.12.</p>
</li>
<li>
<p>Update <code>mise@latest</code> to 2026.9.4.</p>
</li>
<li>
<p>Update <code>kache@latest</code> to 0.19.0.</p>
</li>
</ul>
<h2>2.87.10</h2>
<ul>
<li>
<p>Update <code>zizmor@latest</code> to 1.30.1.</p>
</li>
<li>
<p>Update <code>uv@latest</code> to 0.12.11.</p>
</li>
<li>
<p>Update <code>tombi@latest</code> to 1.5.4.</p>
</li>
<li>
<p>Update <code>release-plz@latest</code> to 0.3.164.</p>
</li>
<li>
<p>Update <code>mise@latest</code> to 2026.9.3.</p>
</li>
<li>
<p>Update <code>kingfisher@latest</code> to 2.2.0.</p>
</li>
</ul>
<h2>2.87.9</h2>
<ul>
<li>
<p>Update <code>oxfmt@latest</code> to 1.82.0.</p>
</li>
<li>
<p>Update <code>mise@latest</code> to 2026.9.2.</p>
</li>
<li>
<p>Update <code>kache@latest</code> to 0.18.0.</p>
</li>
<li>
<p>Update <code>d2@latest</code> to 0.9.0.</p>
</li>
<li>
<p>Update <code>bpf-linker@latest</code> to 0.11.1.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md">taiki-e/install-action's
changelog</a>.</em></p>
<blockquote>
<h2>[2.87.11] - 2026-09-11</h2>
<ul>
<li>
<p>Update <code>biome@latest</code> to 2.5.13.</p>
</li>
<li>
<p>Update <code>uv@latest</code> to 0.12.12.</p>
</li>
<li>
<p>Update <code>mise@latest</code> to 2026.9.4.</p>
</li>
<li>
<p>Update <code>kache@latest</code> to 0.19.0.</p>
</li>
</ul>
<h2>[2.87.10] - 2026-09-10</h2>
<ul>
<li>
<p>Update <code>zizmor@latest</code> to 1.30.1.</p>
</li>
<li>
<p>Update <code>uv@latest</code> to 0.12.11.</p>
</li>
<li>
<p>Update <code>tombi@latest</code> to 1.5.4.</p>
</li>
<li>
<p>Update <code>release-plz@latest</code> to 0.3.164.</p>
</li>
<li>
<p>Update <code>mise@latest</code> to 2026.9.3.</p>
</li>
<li>
<p>Update <code>kingfisher@latest</code> to 2.2.0.</p>
</li>
</ul>
<h2>[2.87.9] - 2026-09-09</h2>
<ul>
<li>
<p>Update <code>oxfmt@latest</code> to 1.82.0.</p>
</li>
<li>
<p>Update <code>mise@latest</code> to 2026.9.2.</p>
</li>
<li>
<p>Update <code>kache@latest</code> to 0.18.0.</p>
</li>
<li>
<p>Update <code>d2@latest</code> to 0.9.0.</p>
</li>
<li>
<p>Update <code>bpf-linker@latest</code> to 0.11.1.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/taiki-e/install-action/commit/9534c84618278caac52cb373bb164ed464dbd8af"><code>9534c84</code></a>
Release 2.87.11</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/2701cdeef0c2a8f95ae84cf27c4fc1b1249454bf"><code>2701cde</code></a>
Update <code>biome@latest</code> to 2.5.13</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/df5505b67e0cf84fe727ac89223416fc8e553f51"><code>df5505b</code></a>
Update wasmtime manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/9089cd985e82f247765f0eeb4a8df27d1e454ef1"><code>9089cd9</code></a>
Update wasm-tools manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/5378c77c111b08b3b8867846dff03255b3762c13"><code>5378c77</code></a>
Update <code>uv@latest</code> to 0.12.12</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/3ff7a2496b299d7788a422ac45811087202b9394"><code>3ff7a24</code></a>
Update release-plz manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/54143ac6750d7ddfc91eef5f1000b5a143fd2b6b"><code>54143ac</code></a>
Update protoc-gen-connect-openapi manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/6ed3b7ae42f62f8e63e0390295df7d04a24ecefc"><code>6ed3b7a</code></a>
Update <code>mise@latest</code> to 2026.9.4</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/b0276e8583c90e53f506ac446b34ef096fe6ea80"><code>b0276e8</code></a>
Update <code>kache@latest</code> to 0.19.0</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/a1fee385559929f1adcce1144a93c89afbf08815"><code>a1fee38</code></a>
Update grcov manifest</li>
<li>Additional commits viewable in <a
href="https://github.com/taiki-e/install-action/compare/v2.87.8...v2.87.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=taiki-e/install-action&package-manager=github_actions&previous-version=2.87.8&new-version=2.87.11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-13 22:06:33 -07:00
dependabot[bot] 3ef16e866d chore: bump signpath/github-action-submit-signing-request from 2 to 3 (#4092)
Bumps
[signpath/github-action-submit-signing-request](https://github.com/signpath/github-action-submit-signing-request)
from 2 to 3.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/SignPath/github-action-submit-signing-request/commit/f6d04783b4569d051e0c80105fe66e82819d0092"><code>f6d0478</code></a>
Build from - 7336bb524a08c99aa48ba5065b00095eb2b0e09e. Original commit
messag...</li>
<li><a
href="https://github.com/SignPath/github-action-submit-signing-request/commit/ef0ce19416782bc2e1b2deea3ca79c5446cc3b78"><code>ef0ce19</code></a>
Build from - 8ff04a5c1f8d21d18e1eb1fc41b698b425a83654. Original commit
messag...</li>
<li><a
href="https://github.com/SignPath/github-action-submit-signing-request/commit/a790881fc89970675894221b0be3bb12a87eb391"><code>a790881</code></a>
Build from - 9c89d7e4aa8c240d6deba49c8e4f52910fd41288. Original commit
messag...</li>
<li>See full diff in <a
href="https://github.com/signpath/github-action-submit-signing-request/compare/v2...v3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=signpath/github-action-submit-signing-request&package-manager=github_actions&previous-version=2&new-version=3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-13 22:06:16 -07:00
dependabot[bot] 85439e63c6 chore: bump astral-sh/setup-uv from 10.0.1 to 10.1.0 (#4094)
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from
10.0.1 to 10.1.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/setup-uv/releases">astral-sh/setup-uv's
releases</a>.</em></p>
<blockquote>
<h2>v10.1.0 🌈 New output <code>python-runtime-id</code>and respect
NO_PROXY</h2>
<h2>Changes</h2>
<p>This release adds more bheind the scene security improvements and
also 2 small improvements.</p>
<h3>NO_PROXY</h3>
<p>This action now respects <code>no_proxy/NO_PROXY</code> environment
variables which were previously ignored.</p>
<h3>New output <code>python-runtime-id</code></h3>
<p>The new output <code>python-runtime-id</code> can be used to know
which python version exactly was installed if you use
<code>activate-environment</code>. See <a
href="https://redirect.github.com/pyca/cryptography/pull/15572#discussion_r3913508686">pyca/cryptography#15572</a>
for details on why this can be useful.</p>
<h2>🐛 Bug fixes</h2>
<ul>
<li>fix: respect no proxy directive <a
href="https://github.com/mj0nez"><code>@​mj0nez</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1037">#1037</a>)</li>
<li>Use JSON + a typed wrapper instead of TS codegen <a
href="https://github.com/woodruffw"><code>@​woodruffw</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1025">#1025</a>)</li>
</ul>
<h2>🚀 Enhancements</h2>
<ul>
<li>Expose a Python &quot;identity&quot; output <a
href="https://github.com/woodruffw"><code>@​woodruffw</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1036">#1036</a>)</li>
<li>Verify downloads with astral-sh/versions checksums <a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1033">#1033</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>chore: update known checksums for 0.12.12 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1041">#1041</a>)</li>
<li>chore: update known checksums for 0.12.10/0.12.11 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1038">#1038</a>)</li>
<li>chore: update known checksums for 0.12.9 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1035">#1035</a>)</li>
<li>chore: update known checksums for 0.12.7/0.12.8 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1031">#1031</a>)</li>
<li>chore: update known checksums for 0.12.6 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1030">#1030</a>)</li>
<li>chore: update known checksums for 0.12.5 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1020">#1020</a>)</li>
<li>Use self-repo syntax for all in-repo actions/reusable workflows <a
href="https://github.com/woodruffw"><code>@​woodruffw</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1024">#1024</a>)</li>
<li>Pin one-shot tools <a
href="https://github.com/woodruffw"><code>@​woodruffw</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1022">#1022</a>)</li>
<li>ci: remove obsolete direct push attempts <a
href="https://github.com/eifinger"><code>@​eifinger</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1019">#1019</a>)</li>
</ul>
<h2>📚 Documentation</h2>
<ul>
<li>docs: update version references to v10.0.1 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1018">#1018</a>)</li>
</ul>
<h2>⬆️ Dependency updates</h2>
<ul>
<li>chore(deps-dev): roll up Dependabot updates <a
href="https://github.com/eifinger"><code>@​eifinger</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1043">#1043</a>)</li>
<li>Harden npm install defaults <a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1026">#1026</a>)</li>
<li>Add dependency cooldowns <a
href="https://github.com/woodruffw"><code>@​woodruffw</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1021">#1021</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/bec219d24cd3e171d82865faccec33120bb574f4"><code>bec219d</code></a>
chore(deps-dev): roll up Dependabot updates (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1043">#1043</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/b90ec40d15bfa44c33c6700196eb6efcdddb4373"><code>b90ec40</code></a>
fix: respect no proxy directive (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1037">#1037</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/421feb646df5262e7dd93bc54161edfa30372417"><code>421feb6</code></a>
chore: update known checksums for 0.12.12 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1041">#1041</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/f634bf473ad85bf3e23a613f52c5fa9f363874fc"><code>f634bf4</code></a>
Expose a Python &quot;identity&quot; output (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1036">#1036</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/a6772c8f0a09dc9e3582c70a994b0c55af921803"><code>a6772c8</code></a>
chore: update known checksums for 0.12.10/0.12.11 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1038">#1038</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/e105c8fb1d7b13074b851babdaef4185243c6a07"><code>e105c8f</code></a>
chore: update known checksums for 0.12.9 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1035">#1035</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/cd13f9217092d43a771cf9ba7b09bdd3da8d7c4d"><code>cd13f92</code></a>
Verify downloads with astral-sh/versions checksums (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1033">#1033</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/3aef7b92c52cec135792ea1e95f4c77683d39e61"><code>3aef7b9</code></a>
chore: update known checksums for 0.12.7/0.12.8 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1031">#1031</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/d08d816a1ea176d61a318eff45abd3dffef415b1"><code>d08d816</code></a>
chore: update known checksums for 0.12.6 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1030">#1030</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/19b4d1e990bec64818914c40230bde93a0de300b"><code>19b4d1e</code></a>
Harden npm install defaults (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1026">#1026</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/setup-uv/compare/v10.0.1...v10.1.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=astral-sh/setup-uv&package-manager=github_actions&previous-version=10.0.1&new-version=10.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-13 22:06:03 -07:00
dependabot[bot] 3132d4fd09 chore: bump the docs-site group in /docs with 3 updates (#4099)
Bumps the docs-site group in /docs with 3 updates:
[@astrojs/markdown-remark](https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark),
[astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) and
[playwright](https://github.com/microsoft/playwright).

Updates `@astrojs/markdown-remark` from 7.3.0 to 7.3.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/releases">@​astrojs/markdown-remark's
releases</a>.</em></p>
<blockquote>
<h2><code>@​astrojs/markdown-remark</code><a
href="https://github.com/7"><code>@​7</code></a>.3.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/withastro/astro/pull/17896">#17896</a>
<a
href="https://github.com/withastro/astro/commit/a548223607b9bb146d5d90ddda495343f9a2a739"><code>a548223</code></a>
Thanks <a
href="https://github.com/matthewp"><code>@​matthewp</code></a>! - Fixes
<code>&lt;script&gt;</code>/<code>&lt;style&gt;</code> rendering in MDX
so that only literal content (including content injected by
remark/rehype plugins) is treated as trusted markup. A dynamic value
passed as a <code>&lt;script&gt;</code>/<code>&lt;style&gt;</code> child
(e.g. <code>&lt;script&gt;{value}&lt;/script&gt;</code>) is now escaped
like any other element's content instead of being rendered raw. Use
<code>set:html</code> to explicitly opt a dynamic value back into raw
rendering.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/blob/main/packages/markdown/remark/CHANGELOG.md">@​astrojs/markdown-remark's
changelog</a>.</em></p>
<blockquote>
<h2>7.3.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/withastro/astro/pull/17896">#17896</a>
<a
href="https://github.com/withastro/astro/commit/a548223607b9bb146d5d90ddda495343f9a2a739"><code>a548223</code></a>
Thanks <a
href="https://github.com/matthewp"><code>@​matthewp</code></a>! - Fixes
<code>&lt;script&gt;</code>/<code>&lt;style&gt;</code> rendering in MDX
so that only literal content (including content injected by
remark/rehype plugins) is treated as trusted markup. A dynamic value
passed as a <code>&lt;script&gt;</code>/<code>&lt;style&gt;</code> child
(e.g. <code>&lt;script&gt;{value}&lt;/script&gt;</code>) is now escaped
like any other element's content instead of being rendered raw. Use
<code>set:html</code> to explicitly opt a dynamic value back into raw
rendering.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/withastro/astro/commit/aa4949e425144e0d276d2ff70f01209e90fdfbe8"><code>aa4949e</code></a>
[ci] release (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark/issues/17915">#17915</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/a548223607b9bb146d5d90ddda495343f9a2a739"><code>a548223</code></a>
Only treat literal script/style content as raw in MDX rendering (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark/issues/17896">#17896</a>)</li>
<li>See full diff in <a
href="https://github.com/withastro/astro/commits/@astrojs/markdown-remark@7.3.1/packages/markdown/remark">compare
view</a></li>
</ul>
</details>
<br />

Updates `astro` from 7.3.1 to 7.3.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/releases">astro's
releases</a>.</em></p>
<blockquote>
<h2>astro@7.3.2</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17896">#17896</a>
<a
href="https://github.com/withastro/astro/commit/a548223607b9bb146d5d90ddda495343f9a2a739"><code>a548223</code></a>
Thanks <a
href="https://github.com/matthewp"><code>@​matthewp</code></a>! - Fixes
<code>&lt;script&gt;</code>/<code>&lt;style&gt;</code> rendering in MDX
so that only literal content (including content injected by
remark/rehype plugins) is treated as trusted markup. A dynamic value
passed as a <code>&lt;script&gt;</code>/<code>&lt;style&gt;</code> child
(e.g. <code>&lt;script&gt;{value}&lt;/script&gt;</code>) is now escaped
like any other element's content instead of being rendered raw. Use
<code>set:html</code> to explicitly opt a dynamic value back into raw
rendering.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17931">#17931</a>
<a
href="https://github.com/withastro/astro/commit/c1a6a89efa577b8388f04c4b42d655913bb4b886"><code>c1a6a89</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Fixes the dev toolbar returning a 504 &quot;Outdated Optimize
Dep&quot; error when a workspace-linked package imports a dependency
that Vite's initial scan did not discover</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17908">#17908</a>
<a
href="https://github.com/withastro/astro/commit/42e9188c4ba7360e5ab8ea4cd7f13d6abcf31879"><code>42e9188</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Fixes i18n fallback routing replacing the first substring match
instead of the actual locale segment, which mangled paths like
<code>/energy/en/about</code> into <code>/esergy/en/about</code></p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17936">#17936</a>
<a
href="https://github.com/withastro/astro/commit/4b92ddc6ab0795ac78c30aedfe43b081dcf5b6b0"><code>4b92ddc</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Fixes sessions breaking in dev mode with the Cloudflare adapter when
middleware is present</p>
</li>
<li>
<p>Updated dependencies [<a
href="https://github.com/withastro/astro/commit/a548223607b9bb146d5d90ddda495343f9a2a739"><code>a548223</code></a>]:</p>
<ul>
<li><code>@​astrojs/markdown-satteri</code><a
href="https://github.com/0"><code>@​0</code></a>.4.1</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md">astro's
changelog</a>.</em></p>
<blockquote>
<h2>7.3.2</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17896">#17896</a>
<a
href="https://github.com/withastro/astro/commit/a548223607b9bb146d5d90ddda495343f9a2a739"><code>a548223</code></a>
Thanks <a
href="https://github.com/matthewp"><code>@​matthewp</code></a>! - Fixes
<code>&lt;script&gt;</code>/<code>&lt;style&gt;</code> rendering in MDX
so that only literal content (including content injected by
remark/rehype plugins) is treated as trusted markup. A dynamic value
passed as a <code>&lt;script&gt;</code>/<code>&lt;style&gt;</code> child
(e.g. <code>&lt;script&gt;{value}&lt;/script&gt;</code>) is now escaped
like any other element's content instead of being rendered raw. Use
<code>set:html</code> to explicitly opt a dynamic value back into raw
rendering.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17931">#17931</a>
<a
href="https://github.com/withastro/astro/commit/c1a6a89efa577b8388f04c4b42d655913bb4b886"><code>c1a6a89</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Fixes the dev toolbar returning a 504 &quot;Outdated Optimize
Dep&quot; error when a workspace-linked package imports a dependency
that Vite's initial scan did not discover</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17908">#17908</a>
<a
href="https://github.com/withastro/astro/commit/42e9188c4ba7360e5ab8ea4cd7f13d6abcf31879"><code>42e9188</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Fixes i18n fallback routing replacing the first substring match
instead of the actual locale segment, which mangled paths like
<code>/energy/en/about</code> into <code>/esergy/en/about</code></p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17936">#17936</a>
<a
href="https://github.com/withastro/astro/commit/4b92ddc6ab0795ac78c30aedfe43b081dcf5b6b0"><code>4b92ddc</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Fixes sessions breaking in dev mode with the Cloudflare adapter when
middleware is present</p>
</li>
<li>
<p>Updated dependencies [<a
href="https://github.com/withastro/astro/commit/a548223607b9bb146d5d90ddda495343f9a2a739"><code>a548223</code></a>]:</p>
<ul>
<li><code>@​astrojs/markdown-satteri</code><a
href="https://github.com/0"><code>@​0</code></a>.4.1</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/withastro/astro/commit/aa4949e425144e0d276d2ff70f01209e90fdfbe8"><code>aa4949e</code></a>
[ci] release (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17915">#17915</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/42e9188c4ba7360e5ab8ea4cd7f13d6abcf31879"><code>42e9188</code></a>
fix(i18n): replace locale segment by index in fallback routing (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17907">#17907</a>)
(<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17908">#17908</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/4b92ddc6ab0795ac78c30aedfe43b081dcf5b6b0"><code>4b92ddc</code></a>
Guard setFetchHandler call in non-runnable dev entrypoint to fix
sessions + m...</li>
<li><a
href="https://github.com/withastro/astro/commit/c1a6a89efa577b8388f04c4b42d655913bb4b886"><code>c1a6a89</code></a>
fix: include .astro files in client optimizeDeps entries to prevent 504
on la...</li>
<li><a
href="https://github.com/withastro/astro/commit/a548223607b9bb146d5d90ddda495343f9a2a739"><code>a548223</code></a>
Only treat literal script/style content as raw in MDX rendering (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17896">#17896</a>)</li>
<li>See full diff in <a
href="https://github.com/withastro/astro/commits/astro@7.3.2/packages/astro">compare
view</a></li>
</ul>
</details>
<br />

Updates `playwright` from 1.62.1 to 1.63.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/microsoft/playwright/releases">playwright's
releases</a>.</em></p>
<blockquote>
<h2>v1.63.0</h2>
<h2>🔒 Test locks</h2>
<p>Tests that access a shared resource — an external service, a global
account setting — can now declare a named <code>lock</code>.
Tests that share a lock name never run concurrently, across files,
workers and <a
href="https://playwright.dev/docs/test-projects">projects</a>, while
everything else keeps running in parallel:</p>
<pre lang="js"><code>test('update user settings', { lock:
'user-settings' }, async ({ page }) =&gt; {
  // never runs at the same time as other tests holding 'user-settings'
});
</code></pre>
<p>A test can hold multiple locks, and <a
href="https://playwright.dev/docs/api/class-test#test-describe">test.describe()</a>
accepts a <code>lock</code> for the whole group.
Learn more about <a
href="https://playwright.dev/docs/test-parallel#test-locks">test
locks</a>.</p>
<h2>🪟 Locate across frames</h2>
<p><a
href="https://playwright.dev/docs/api/class-page#page-frame-locator">page.frameLocator()</a>
and <a
href="https://playwright.dev/docs/api/class-frame#frame-frame-locator">frame.frameLocator()</a>
called without a selector search in any frame of the
subtree, so you no longer need to locate the iframe first:</p>
<pre lang="js"><code>// Finds the button in any frame on the page.
await page.frameLocator().getByRole('button').click();
</code></pre>
<p>The rest of the locator resolves inside a single frame, just like a
regular locator, and an error is thrown when it
matches elements in several frames.</p>
<h2>👁️ Visible-only locators</h2>
<p>New <a
href="https://playwright.dev/docs/api/class-locator#locator-visible">locator.visible()</a>
returns a locator that matches only visible elements. It is the
recommended
replacement for the <code>:visible</code> CSS pseudo-class:</p>
<pre lang="js"><code>await page.locator('button').visible().click();
</code></pre>
<h2>🧾 Step params and subtitles</h2>
<p>Steps now carry structured data for reporters. Playwright API steps
report the target locator and call arguments,
and <a
href="https://playwright.dev/docs/api/class-test#test-step">test.step()</a>
accepts <code>subtitle</code> and <code>params</code> options for your
own steps:</p>
<pre lang="js"><code>await test.step('Login', async () =&gt; {
  // ...
}, { subtitle: 'as admin', params: { user: 'admin' } });
</code></pre>
<p>Reporters receive them via <a
href="https://playwright.dev/docs/api/class-teststep#test-step-subtitle">testStep.subtitle</a>
and <a
href="https://playwright.dev/docs/api/class-teststep#test-step-params">testStep.params</a>.
For Playwright API</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/microsoft/playwright/commit/1b025d7e20a026371cd5f98ba0cdce48892737c8"><code>1b025d7</code></a>
chore: mark v1.63.0 (<a
href="https://redirect.github.com/microsoft/playwright/issues/42569">#42569</a>)</li>
<li><a
href="https://github.com/microsoft/playwright/commit/0b9956d2247ce88399c3c46a22c1cc0526acb340"><code>0b9956d</code></a>
cherry-pick(<a
href="https://redirect.github.com/microsoft/playwright/issues/42568">#42568</a>):
docs(test): mark test.step subtitle option as since v1.63</li>
<li><a
href="https://github.com/microsoft/playwright/commit/13dbf102b88305ed96b7791a7843246cd75d4dae"><code>13dbf10</code></a>
cherry-pick(<a
href="https://redirect.github.com/microsoft/playwright/issues/42552">#42552</a>):
docs: release notes for v1.63</li>
<li><a
href="https://github.com/microsoft/playwright/commit/e93b64ed6f9cf6ac2cc8cb13ad01514b406a7142"><code>e93b64e</code></a>
cherry-pick(<a
href="https://redirect.github.com/microsoft/playwright/issues/42566">#42566</a>):
feat(test): add subtitle option to test.step (<a
href="https://redirect.github.com/microsoft/playwright/issues/42567">#42567</a>)</li>
<li><a
href="https://github.com/microsoft/playwright/commit/2b7a5f2ea1cea04b549c5378498c1b16b6bc6a6f"><code>2b7a5f2</code></a>
test: response.body() for content-encoding:identity (<a
href="https://redirect.github.com/microsoft/playwright/issues/42537">#42537</a>)</li>
<li><a
href="https://github.com/microsoft/playwright/commit/648a67c7c1261eefe4113cba2d586417d5e3f2f2"><code>648a67c</code></a>
fix(mcp): create parent directories for explicitly named files (<a
href="https://redirect.github.com/microsoft/playwright/issues/42540">#42540</a>)</li>
<li><a
href="https://github.com/microsoft/playwright/commit/7894f5653e7f253c17aa1638c19f63e0d54d5e0e"><code>7894f56</code></a>
docs(mcp): clarify how tool file names are resolved (<a
href="https://redirect.github.com/microsoft/playwright/issues/42538">#42538</a>)</li>
<li><a
href="https://github.com/microsoft/playwright/commit/52900a1b99ca51011526afcaf8981970cc1a521a"><code>52900a1</code></a>
devops: restore npm publishing from GitHub Actions (<a
href="https://redirect.github.com/microsoft/playwright/issues/42550">#42550</a>)</li>
<li><a
href="https://github.com/microsoft/playwright/commit/8c47f596edebd2460895a5953f2ea67f8b884001"><code>8c47f59</code></a>
docs(csharp): fix nonexistent method names in guide examples (<a
href="https://redirect.github.com/microsoft/playwright/issues/42507">#42507</a>)</li>
<li><a
href="https://github.com/microsoft/playwright/commit/bd6e552a63f8cf9b0da0216f392b8e63a08bf1d2"><code>bd6e552</code></a>
chore(video): emit frames with real timestamps, drop frame number
quantizatio...</li>
<li>Additional commits viewable in <a
href="https://github.com/microsoft/playwright/compare/v1.62.1...v1.63.0">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-13 22:05:39 -07:00
Worktrunk Bot 6c263ed69e skills(running-tend): weigh the root-cause fix in every workflow, not just triage (#4086) 2026-09-13 17:15:12 -07:00
Maximilian Roos 5dec423110 docs: leave trailing shell comments out of copied commands (#4091)
Copy buttons copied shell commands with their trailing `#` comments,
e.g. `wt hook pre-merge user: # Run all user hooks`. In zsh without
`interactivecomments`, which is the default, a pasted trailing comment
isn't a comment: the command runs as `wt hook pre-merge user: '#' Run
all user hooks`.

`withoutTrailingShellComments` in
`docs/src/plugins/worktrunk-terminal.mjs` applies the shell's rule, that
a `#` beginning an unquoted word starts a comment, to what shell copy
buttons copy: each per-line button in multi-command `console` blocks,
the command lines of single-command `console` blocks, and whole `bash`
and `sh` blocks. A line that is only a comment stays, as
`docs/CLAUDE.md` already specifies for console blocks. 56 of the site's
339 copy payloads change (47 per-line buttons and 9 `bash` blocks).
TOML, PowerShell and other payloads are unchanged, and a quoted `#`
survives.

Tests: unit tests for the scanner (quotes, escapes, `$#`, operators,
quotes spanning lines) and for a single-command `console` block with a
trailing comment, plus a built-site test that no `bash` or `sh` payload
carries a trailing comment, which fails on the build before this change.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_013U96NY8qKtZhavBSwnfCYq

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-13 10:57:35 -07:00
Worktrunk Bot 397c3b2df4 ci: bump cargo-llvm-cov, cargo-nextest, and PowerShell pins (#4089)
Weekly CI pin bump for the three tool pins that drifted this week. All
three are patch-level.

- **cargo-llvm-cov** `=0.9.0` → `=0.9.1` — `coverage.yaml`
- **cargo-nextest** `=0.9.143` → `=0.9.144` — `coverage.yaml`,
`.github/actions/test-setup/action.yaml`,
`.github/actions/tend-setup/action.yaml`, and `.codex/cloud.sh`, which
the weekly checklist keeps level with `test-setup`
- **PowerShell** `7.6.5` → `7.6.6` — `.codex/cloud.sh` and `setup-web`
in `Taskfile.yaml`. Nothing under `.github/` pins PowerShell (CI uses
whatever the runner image ships), so this one answers only to these two
setup paths

Toolchain compatibility against the pinned `1.97.0`: `cargo-llvm-cov`
0.9.1 declares `rust-version = 1.87`, `cargo-nextest` 0.9.144 declares
`1.91`. Both build under `baptiste0928/cargo-install`.

The two download URLs still resolve at the new versions:
`powershell-7.6.6-linux-x64.tar.gz` and
`powershell_7.6.6-1.deb_amd64.deb` are both published on the `v7.6.6`
release, and `cargo-nextest-0.9.144-x86_64-unknown-linux-gnu.tar.gz` on
the `cargo-nextest-0.9.144` tag.

The `worktrunk` pin also drifted this week and is in #4088 instead — it
is the `wt` that drives `wt hook pre-merge` on all three platforms, so a
red matrix there shouldn't hold back these.

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-13 10:23:37 -07:00
Worktrunk Bot 8153649cea ci: bump pinned worktrunk to 0.77.0 (#4088)
Weekly CI pin bump for the `worktrunk` pin only.

- **worktrunk** `=0.76.0` → `=0.77.0` (3 sites: `ci.yaml` ×2,
`nightly.yaml`)

This is the `wt` that runs the suite (`wt hook pre-merge`) on all three
platforms, so it goes on its own PR — its own matrix is the only place
the bump gets tested. The rest of this week's drift (cargo-llvm-cov,
cargo-nextest, PowerShell) is in a separate PR.

Compatibility: worktrunk `0.77.0` declares `rust-version = 1.97`,
matching the pinned toolchain (`rust-toolchain.toml` channel `1.97.0`),
so it builds under `baptiste0928/cargo-install`.

CI calls `wt` only as `wt hook pre-merge --yes <filters>` (`insta` in
`ci.yaml` and `nightly.yaml`, `lockfile doctest doc` in `ci.yaml`). None
of 0.77.0's breaking changes reach that path: the `--format=json`
schema-2 default and the `wt config show` non-zero exit are other
commands, `wt config update --print` and the Codex plugin uninstall
changes are unused in CI, and the newly-erroring unguarded `{{ branch
}}` appears in `.config/wt.toml` only under `[[post-start]]` and `[list]
url` — every `[[pre-merge]]` entry there is a plain string with no
template variables, which matters because `actions/checkout` leaves a
detached HEAD.

<details><summary>Weekly checks that found no drift</summary>

- **MSRV/toolchain**: current stable is `1.98.1` (`1.98.0` released
2026-08-20, `1.98.1` on 2026-09-03), so latest−1 is `1.97` — already
what `Cargo.toml`, `tests/helpers/wt-perf/Cargo.toml`, and
`rust-toolchain.toml` pin. The `nightly-2026-08-01` pins in
`nightly.yaml` are ~6 weeks old, inside the three-month window. No
toolchain change, so no `flake.lock` refresh.
- **Other `cargo-install` pins**: `cargo-affected` 0.4.0, `cargo-insta`
1.48.0, `cargo-msrv` 0.19.3, `cargo-udeps` 0.1.61, `lychee` 0.24.2 all
match their current crates.io release.
- **`setup-nu`**: `0.115.1` is still the latest `nushell/nushell`
release, across all five call sites.
- **Runner images**: `ubuntu-24.04`, `macos-26`, and `windows-2025` each
still equal their `-latest` label in the `actions/runner-images`
availability table; `ubuntu-24.04-arm` and `macos-26-intel` follow those
rows. Ubuntu 26.04 and Xcode 27 are badged preview, so not bump targets.
- **`dependabot.yaml` typescript ignore**: `npm view @astrojs/check
peerDependencies.typescript` is still `^5.0.0 || ^6.0.0` while the
latest `typescript` is `7.0.2`, so the major-version ignore entry stays
(#3877).
- **LLM model pins**: `claude-haiku-4.5` is still the "fastest model"
row on Anthropic's models page, and `gpt-5.6-luna` is still the
fast/lowest-cost entry in the Codex recommended list. GPT-6 Astra joined
that list as the *most capable* model, which doesn't change the
commit-generation recommendation; `gpt-5.3-codex-spark` remains a
Pro-only research preview with no API access.
- **Statusline cache-check**: clean. `wt config state logs profile`
reports `same_context_duplicates: []` and 0 extra calls on a `wt list
statusline --format=claude-code` render.
- **Agent integration surfaces**: nothing to flag. Claude Code shipped
2.1.265–2.1.270 since the last weekly run with no statusline field
additions (every `Requires Claude Code v…` note in the field table is
2.1.260 or earlier) and no change to `WorktreeCreate`/`WorktreeRemove`;
2.1.265's switch to preferring marketplace-entry display metadata over
`plugin.json` is a no-op here, since `.claude-plugin/marketplace.json`
and `plugins/worktrunk/.claude-plugin/plugin.json` carry the same
description. Codex `rust-v0.154.0` only refreshes plugin skills/hooks
after external upgrades and reroutes approvals internally —
`UserPromptSubmit`, `PermissionRequest`, `Stop`, and `SessionEnd` are
unchanged, and the removed `codex mcp-server` entry point is unused
here. Gemini CLI `v0.59.0` and OpenCode `v1.18.26`–`v1.18.30` carry
nothing touching extension loading or the plugins API.
- **README date stamp**: the blockquote already reads September 2026.

</details>

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-13 10:23:31 -07:00
Worktrunk Bot 4ef5644b69 fix(opencode): read an empty OPENCODE_CONFIG_DIR as unset, not as a relative path (#4084)
`wt config plugins opencode install` writes the plugin to a **relative**
`plugins/worktrunk.ts` — i.e. into whatever directory `wt` was run from,
typically the user's repo — when `OPENCODE_CONFIG_DIR` is exported with
an empty value. `is_plugin_installed()` and `plugin_file_exists()` then
read that same relative path back, so the install reports success while
OpenCode never sees the plugin.

The cause is a one-branch gap in `opencode_plugins_dir`: the
`XDG_CONFIG_HOME` arm filtered empty values, the `OPENCODE_CONFIG_DIR`
arm above it did not, so `PathBuf::from("")` passed through as a valid
config directory. Every other agent-config override in the tree already
reads an empty value as unset — `CLAUDE_CONFIG_DIR` in
`commands::config::show`, `PI_CODING_AGENT_DIR` and `PI_CONFIG_DIR` in
`commands::config::pi` — so this arm was the odd one out rather than a
deliberate choice.

The documented precedence is unchanged: `$OPENCODE_CONFIG_DIR` >
`$XDG_CONFIG_HOME/opencode` > `~/.config/opencode`. Only the reading of
an empty value moves, from "a directory named `""`" to "unset".

The regression test runs the real install from a scratch directory with
`OPENCODE_CONFIG_DIR=""`, then asserts the plugin landed under
`$XDG_CONFIG_HOME/opencode/plugins/` and that nothing was written
relative to the invocation directory. It fails against the previous code
on the first assertion.

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-13 10:23:22 -07:00
Worktrunk Bot 8557af71b7 chore: update tend workflows (0.2.6 → 0.2.7) (#4083)
Regenerates the `tend-*.yaml` workflows for tend 0.2.7 (from 0.2.6). The
diff is the version comment and the `max-sixty/tend/claude@` action pin
in all eight workflows; no job, trigger, or permission changed.

What adopters get from the upgrade:

- **The sandbox can write zsh here-documents again.** Scratch files for
heredocs now go to the writable temp dir instead of a path the sandbox
denies, so a session that shells out through zsh no longer fails on them
(max-sixty/tend#1211). This run hit exactly that failure while composing
this description.
- **`review-runs` stops reporting paths that have since gone green.** It
re-queries the closure read before calling a path still red, so a run
fixed between the scan and the report is no longer written up as an
outstanding failure (max-sixty/tend#1210).
- **`review-runs` now checks open Dependabot alerts** as part of its
live repository scan, so unaddressed security advisories surface in the
daily sweep (max-sixty/tend#1214).
- **Sessions load less bundled guidance.** `running-in-ci` and `review`
keep the rules every session needs and move the rarer actions — opening
a PR, pushing, monitoring CI, posting, draft mode — into `references/`
files read on demand, dropping from 52 KB to 20 KB and 41 KB to 25 KB
respectively. That leaves more of each session's context for the actual
work (max-sixty/tend#1215).
- **PR review decides its pre-approval check in a script** rather than
re-deriving it from prose each session, which makes the
approve/don't-approve call consistent run to run (max-sixty/tend#1217).

Full comparison: https://github.com/max-sixty/tend/compare/0.2.6...0.2.7

`.config/tend.yaml` pins no model, so nothing there needed to move.

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-13 10:23:17 -07:00
dependabot[bot] 5b93f1b321 chore: bump the docs-site group in /docs with 5 updates (#4031)
Bumps the docs-site group in /docs with 5 updates:

| Package | From | To |
| --- | --- | --- |
|
[@astrojs/markdown-remark](https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark)
| `7.2.4` | `7.3.0` |
|
[@astrojs/sitemap](https://github.com/withastro/astro/tree/HEAD/packages/integrations/sitemap)
| `3.7.3` | `3.7.4` |
|
[@astrojs/starlight](https://github.com/withastro/starlight/tree/HEAD/packages/starlight)
| `0.41.9` | `0.42.0` |
|
[@expressive-code/core](https://github.com/expressive-code/expressive-code/tree/HEAD/packages/@expressive-code/core)
| `0.44.1` | `0.44.2` |
| [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) |
`7.2.9` | `7.3.1` |

Updates `@astrojs/markdown-remark` from 7.2.4 to 7.3.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/releases">@​astrojs/markdown-remark's
releases</a>.</em></p>
<blockquote>
<h2><code>@​astrojs/markdown-remark</code><a
href="https://github.com/7"><code>@​7</code></a>.3.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17262">#17262</a>
<a
href="https://github.com/withastro/astro/commit/f8e94585ab6c38e2702ee1e2e540858f72058a40"><code>f8e9458</code></a>
Thanks <a
href="https://github.com/Princesseuh"><code>@​Princesseuh</code></a>! -
Adds MDX rendering to the <code>unified()</code> and
<code>satteri()</code> processors.</p>
<p>Both processors now compile <code>.mdx</code> files themselves. You
still need to install <code>@astrojs/mdx</code> to add MDX support to
your project.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17262">#17262</a>
<a
href="https://github.com/withastro/astro/commit/f8e94585ab6c38e2702ee1e2e540858f72058a40"><code>f8e9458</code></a>
Thanks <a
href="https://github.com/Princesseuh"><code>@​Princesseuh</code></a>! -
Adds a <code>recmaPlugins</code> option to <code>unified()</code> for
adding recma (estree/JSX) plugins to the MDX compiler.</p>
</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [<a
href="https://github.com/withastro/astro/commit/f8e94585ab6c38e2702ee1e2e540858f72058a40"><code>f8e9458</code></a>]:
<ul>
<li><code>@​astrojs/internal-helpers</code><a
href="https://github.com/0"><code>@​0</code></a>.11.0</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/blob/main/packages/markdown/remark/CHANGELOG.md">@​astrojs/markdown-remark's
changelog</a>.</em></p>
<blockquote>
<h2>7.3.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17262">#17262</a>
<a
href="https://github.com/withastro/astro/commit/f8e94585ab6c38e2702ee1e2e540858f72058a40"><code>f8e9458</code></a>
Thanks <a
href="https://github.com/Princesseuh"><code>@​Princesseuh</code></a>! -
Adds MDX rendering to the <code>unified()</code> and
<code>satteri()</code> processors.</p>
<p>Both processors now compile <code>.mdx</code> files themselves. You
still need to install <code>@astrojs/mdx</code> to add MDX support to
your project.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17262">#17262</a>
<a
href="https://github.com/withastro/astro/commit/f8e94585ab6c38e2702ee1e2e540858f72058a40"><code>f8e9458</code></a>
Thanks <a
href="https://github.com/Princesseuh"><code>@​Princesseuh</code></a>! -
Adds a <code>recmaPlugins</code> option to <code>unified()</code> for
adding recma (estree/JSX) plugins to the MDX compiler.</p>
</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [<a
href="https://github.com/withastro/astro/commit/f8e94585ab6c38e2702ee1e2e540858f72058a40"><code>f8e9458</code></a>]:
<ul>
<li><code>@​astrojs/internal-helpers</code><a
href="https://github.com/0"><code>@​0</code></a>.11.0</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/withastro/astro/commit/2fdf731428aa738d5dcf3041b4e78eb9d036968c"><code>2fdf731</code></a>
[ci] release (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark/issues/17849">#17849</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/f8e94585ab6c38e2702ee1e2e540858f72058a40"><code>f8e9458</code></a>
feat: move MDX into the processors themselves (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark/issues/17262">#17262</a>)</li>
<li>See full diff in <a
href="https://github.com/withastro/astro/commits/@astrojs/markdown-remark@7.3.0/packages/markdown/remark">compare
view</a></li>
</ul>
</details>
<br />

Updates `@astrojs/sitemap` from 3.7.3 to 3.7.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/releases">@​astrojs/sitemap's
releases</a>.</em></p>
<blockquote>
<h2><code>@​astrojs/sitemap</code><a
href="https://github.com/3"><code>@​3</code></a>.7.4</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/withastro/astro/pull/17851">#17851</a>
<a
href="https://github.com/withastro/astro/commit/52d3f56999ecdf92510b2c16ed2a3a4785b9c73a"><code>52d3f56</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Fixes the sitemap outputting a URL with an empty path for the homepage
(e.g. <code>https://example.com</code> instead of
<code>https://example.com/</code>) when <code>trailingSlash</code> is
set to <code>&quot;never&quot;</code> or <code>build.format</code> is
set to <code>&quot;file&quot;</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/blob/main/packages/integrations/sitemap/CHANGELOG.md">@​astrojs/sitemap's
changelog</a>.</em></p>
<blockquote>
<h2>3.7.4</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/withastro/astro/pull/17851">#17851</a>
<a
href="https://github.com/withastro/astro/commit/52d3f56999ecdf92510b2c16ed2a3a4785b9c73a"><code>52d3f56</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Fixes the sitemap outputting a URL with an empty path for the homepage
(e.g. <code>https://example.com</code> instead of
<code>https://example.com/</code>) when <code>trailingSlash</code> is
set to <code>&quot;never&quot;</code> or <code>build.format</code> is
set to <code>&quot;file&quot;</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/withastro/astro/commit/2fdf731428aa738d5dcf3041b4e78eb9d036968c"><code>2fdf731</code></a>
[ci] release (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/integrations/sitemap/issues/17849">#17849</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/52d3f56999ecdf92510b2c16ed2a3a4785b9c73a"><code>52d3f56</code></a>
fix(<code>@​astrojs/sitemap</code>): preserve root path <code>/</code>
in sitemap URLs when trailingSl...</li>
<li><a
href="https://github.com/withastro/astro/commit/2bfb179545249786e9f395325c88a9dfef574acb"><code>2bfb179</code></a>
chore: simpler package.json types (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/integrations/sitemap/issues/17229">#17229</a>)</li>
<li>See full diff in <a
href="https://github.com/withastro/astro/commits/@astrojs/sitemap@3.7.4/packages/integrations/sitemap">compare
view</a></li>
</ul>
</details>
<br />

Updates `@astrojs/starlight` from 0.41.9 to 0.42.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/starlight/releases">@​astrojs/starlight's
releases</a>.</em></p>
<blockquote>
<h2><code>@​astrojs/starlight</code><a
href="https://github.com/0"><code>@​0</code></a>.42.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/3572">#3572</a>
<a
href="https://github.com/withastro/starlight/commit/292fb179cbf6e2cd970ced46359c520aa14a80b4"><code>292fb17</code></a>
Thanks <a href="https://github.com/HiDeoo"><code>@​HiDeoo</code></a>! -
Distributes package as JavaScript files with dedicated type declaration
files instead of TypeScript source files.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/4121">#4121</a>
<a
href="https://github.com/withastro/starlight/commit/2623ae60af0fdafc71938f96153b0427fcc2b5aa"><code>2623ae6</code></a>
Thanks <a href="https://github.com/delucis"><code>@​delucis</code></a>!
- Simplifies markup for Starlight’s mobile menu toggle</p>
<p><strong>⚠️ Potentially breaking change:</strong> If you use a theme
plugin, custom styles, or component overrides targeting the
<code>MobileMenuToggle</code> button or <code>PageFrame</code>
components, you may need to adjust these for the new markup. The button
is no longer wrapped in a <code>&lt;starlight-menu-button&gt;</code>
custom element and no longer uses the <code>aria-expanded</code>
attribute. Instead, you can use the <code>.sl-menu-button</code> class
name to target the button and the <code>:popover-open</code>
pseudo-class to style the menu open state specifically.</p>
<p>In the following example, custom styles for the menu button are
updated for the new approach:</p>
<pre lang="diff"><code>- starlight-menu-button button {
+ .sl-menu-button {
  color: var(--sl-color-text);
}
<ul>
<li>starlight-menu-button[aria-expanded='true'] button {</li>
</ul>
<ul>
<li>.sl-menu-button:has(~ :popover-open) {
color: var(--sl-color-text-accent-high);
}
</code></pre></li>
</ul>
<p>See <a
href="https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro"><code>MobileMenuToggle.astro</code></a>
and <a
href="https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro"><code>PageFrame.astro</code></a>
on GitHub for the full source code of the updated components.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/3572">#3572</a>
<a
href="https://github.com/withastro/starlight/commit/292fb179cbf6e2cd970ced46359c520aa14a80b4"><code>292fb17</code></a>
Thanks <a href="https://github.com/HiDeoo"><code>@​HiDeoo</code></a>! -
Removes the <code>tagline</code> configuration option, which was never
used.</p>
<p>If your configuration included a <code>tagline</code> option, you can
safely remove it without any replacement.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/4134">#4134</a>
<a
href="https://github.com/withastro/starlight/commit/6135f015b527453d7083ad01d2dc6c61d72fbefc"><code>6135f01</code></a>
Thanks <a href="https://github.com/HiDeoo"><code>@​HiDeoo</code></a>! -
Updates internal <code>@astrojs/mdx</code>,
<code>@astrojs/markdown-satteri</code>, and <code>satteri</code>
dependencies.</p>
<p>⚠️ <strong>BREAKING CHANGE:</strong> The following minimum versions
are now required:</p>
<ul>
<li><code>astro</code> v7.2.10 or later</li>
<li><code>@astrojs/markdown-satteri</code> 0.4.0 or later (if you use
it)</li>
<li><code>@astrojs/markdown-remark</code> 7.3.0 or later (if you use
it)</li>
</ul>
<p>Please update Starlight and Astro together:</p>
<pre lang="sh"><code>npx @astrojs/upgrade
</code></pre>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/4121">#4121</a>
<a
href="https://github.com/withastro/starlight/commit/2623ae60af0fdafc71938f96153b0427fcc2b5aa"><code>2623ae6</code></a>
Thanks <a href="https://github.com/delucis"><code>@​delucis</code></a>!
- Refactors Starlight’s mobile menu toggle to work when JavaScript fails
or is disabled</p>
<p>⚠️ <strong>BREAKING CHANGE:</strong> This release drops official
support for Chromium-based browsers prior to version 116 (released
August 2023), Safari-based browsers prior to version 17.0 (released
September 2023), and Firefox prior to version 125 (released April 2024).
You can find a list of currently supported browsers and their versions
using this <a
href="https://browsersl.ist/#q=%3E+0.5%25%2C+not+dead%2C+Chrome+%3E%3D+116%2C+Edge+%3E%3D+116%2C+Firefox+%3E%3D+125%2C+Safari+%3E%3D+17.0%2C+iOS+%3E%3D+17.0%2C+not+op_mini+all">browserslist
query</a>.</p>
<p>This change also removes the <code>data-mobile-menu-expanded</code>
attribute, which was previously added to <code>&lt;body&gt;</code> while
the mobile menu is open. If you have custom code that was depending on
this attribute, you will need to update it to use a new selector to
check if the mobile menu is open.</p>
<p>In the following example, a custom background colour for the site
header while the menu is open is updated for the new approach:</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md">@​astrojs/starlight's
changelog</a>.</em></p>
<blockquote>
<h2>0.42.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/3572">#3572</a>
<a
href="https://github.com/withastro/starlight/commit/292fb179cbf6e2cd970ced46359c520aa14a80b4"><code>292fb17</code></a>
Thanks <a href="https://github.com/HiDeoo"><code>@​HiDeoo</code></a>! -
Distributes package as JavaScript files with dedicated type declaration
files instead of TypeScript source files.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/4121">#4121</a>
<a
href="https://github.com/withastro/starlight/commit/2623ae60af0fdafc71938f96153b0427fcc2b5aa"><code>2623ae6</code></a>
Thanks <a href="https://github.com/delucis"><code>@​delucis</code></a>!
- Simplifies markup for Starlight’s mobile menu toggle</p>
<p><strong>⚠️ Potentially breaking change:</strong> If you use a theme
plugin, custom styles, or component overrides targeting the
<code>MobileMenuToggle</code> button or <code>PageFrame</code>
components, you may need to adjust these for the new markup. The button
is no longer wrapped in a <code>&lt;starlight-menu-button&gt;</code>
custom element and no longer uses the <code>aria-expanded</code>
attribute. Instead, you can use the <code>.sl-menu-button</code> class
name to target the button and the <code>:popover-open</code>
pseudo-class to style the menu open state specifically.</p>
<p>In the following example, custom styles for the menu button are
updated for the new approach:</p>
<pre lang="diff"><code>- starlight-menu-button button {
+ .sl-menu-button {
  color: var(--sl-color-text);
}
<ul>
<li>starlight-menu-button[aria-expanded='true'] button {</li>
</ul>
<ul>
<li>.sl-menu-button:has(~ :popover-open) {
color: var(--sl-color-text-accent-high);
}
</code></pre></li>
</ul>
<p>See <a
href="https://github.com/withastro/starlight/blob/main/packages/starlight/components/MobileMenuToggle.astro"><code>MobileMenuToggle.astro</code></a>
and <a
href="https://github.com/withastro/starlight/blob/main/packages/starlight/components/PageFrame.astro"><code>PageFrame.astro</code></a>
on GitHub for the full source code of the updated components.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/3572">#3572</a>
<a
href="https://github.com/withastro/starlight/commit/292fb179cbf6e2cd970ced46359c520aa14a80b4"><code>292fb17</code></a>
Thanks <a href="https://github.com/HiDeoo"><code>@​HiDeoo</code></a>! -
Removes the <code>tagline</code> configuration option, which was never
used.</p>
<p>If your configuration included a <code>tagline</code> option, you can
safely remove it without any replacement.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/4134">#4134</a>
<a
href="https://github.com/withastro/starlight/commit/6135f015b527453d7083ad01d2dc6c61d72fbefc"><code>6135f01</code></a>
Thanks <a href="https://github.com/HiDeoo"><code>@​HiDeoo</code></a>! -
Updates internal <code>@astrojs/mdx</code>,
<code>@astrojs/markdown-satteri</code>, and <code>satteri</code>
dependencies.</p>
<p>⚠️ <strong>BREAKING CHANGE:</strong> The following minimum versions
are now required:</p>
<ul>
<li><code>astro</code> v7.2.10 or later</li>
<li><code>@astrojs/markdown-satteri</code> 0.4.0 or later (if you use
it)</li>
<li><code>@astrojs/markdown-remark</code> 7.3.0 or later (if you use
it)</li>
</ul>
<p>Please update Starlight and Astro together:</p>
<pre lang="sh"><code>npx @astrojs/upgrade
</code></pre>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/starlight/pull/4121">#4121</a>
<a
href="https://github.com/withastro/starlight/commit/2623ae60af0fdafc71938f96153b0427fcc2b5aa"><code>2623ae6</code></a>
Thanks <a href="https://github.com/delucis"><code>@​delucis</code></a>!
- Refactors Starlight’s mobile menu toggle to work when JavaScript fails
or is disabled</p>
<p>⚠️ <strong>BREAKING CHANGE:</strong> This release drops official
support for Chromium-based browsers prior to version 116 (released
August 2023), Safari-based browsers prior to version 17.0 (released
September 2023), and Firefox prior to version 125 (released April 2024).
You can find a list of currently supported browsers and their versions
using this <a
href="https://browsersl.ist/#q=%3E+0.5%25%2C+not+dead%2C+Chrome+%3E%3D+116%2C+Edge+%3E%3D+116%2C+Firefox+%3E%3D+125%2C+Safari+%3E%3D+17.0%2C+iOS+%3E%3D+17.0%2C+not+op_mini+all">browserslist
query</a>.</p>
<p>This change also removes the <code>data-mobile-menu-expanded</code>
attribute, which was previously added to <code>&lt;body&gt;</code> while
the mobile menu is open. If you have custom code that was depending on
this attribute, you will need to update it to use a new selector to
check if the mobile menu is open.</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/withastro/starlight/commit/88ad3c2630487ba227a7b4ccbffc01a2bdf623a5"><code>88ad3c2</code></a>
[ci] release (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4172">#4172</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/74cb3f1a40985eed5f7974e2b1b994a2bdcfd8be"><code>74cb3f1</code></a>
Update dependencies (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4173">#4173</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/6135f015b527453d7083ad01d2dc6c61d72fbefc"><code>6135f01</code></a>
Use Sätteri 0.10 APIs (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4134">#4134</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/2623ae60af0fdafc71938f96153b0427fcc2b5aa"><code>2623ae6</code></a>
Refactor mobile menu to use Popover API (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4121">#4121</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/09af1c621e3bd48fa601d6ce47be181bb44d0e9b"><code>09af1c6</code></a>
chore(deps): update <code>magic-string</code> to v1 (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4082">#4082</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/292fb179cbf6e2cd970ced46359c520aa14a80b4"><code>292fb17</code></a>
[i18nIgnore] Transpile Starlight packages (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/3572">#3572</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/0138f22c04ab2a659b642526345ba53bef7e5033"><code>0138f22</code></a>
[ci] release (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4169">#4169</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/32a5e29127c13946ce746c36d7cb194f35d11952"><code>32a5e29</code></a>
Fix hidden heading anchor links (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4167">#4167</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/cdfafd8eedbbd6653cd6a1d3b1542b44ed1ba19e"><code>cdfafd8</code></a>
perf: optimize route and sidebar lookups (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4148">#4148</a>)</li>
<li><a
href="https://github.com/withastro/starlight/commit/dd7fb9721e117337195fdfdb92a081d7dd23701e"><code>dd7fb97</code></a>
chore: add benchmarks (<a
href="https://github.com/withastro/starlight/tree/HEAD/packages/starlight/issues/4157">#4157</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/withastro/starlight/commits/@astrojs/starlight@0.42.0/packages/starlight">compare
view</a></li>
</ul>
</details>
<br />

Updates `@expressive-code/core` from 0.44.1 to 0.44.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/expressive-code/expressive-code/releases">@​expressive-code/core's
releases</a>.</em></p>
<blockquote>
<h2><code>@​expressive-code/core</code><a
href="https://github.com/0"><code>@​0</code></a>.44.2</h2>
<p>No release notes provided.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/expressive-code/expressive-code/blob/main/packages/@expressive-code/core/CHANGELOG.md">@​expressive-code/core's
changelog</a>.</em></p>
<blockquote>
<h2>0.44.2</h2>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/expressive-code/expressive-code/commit/5c5b4522e0db357f453e2e6c9a46790e83ef6322"><code>5c5b452</code></a>
[CI] Release (<a
href="https://github.com/expressive-code/expressive-code/tree/HEAD/packages/@expressive-code/core/issues/469">#469</a>)</li>
<li>See full diff in <a
href="https://github.com/expressive-code/expressive-code/commits/@expressive-code/core@0.44.2/packages/@expressive-code/core">compare
view</a></li>
</ul>
</details>
<br />

Updates `astro` from 7.2.9 to 7.3.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/releases">astro's
releases</a>.</em></p>
<blockquote>
<h2>astro@7.3.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/withastro/astro/pull/17899">#17899</a>
<a
href="https://github.com/withastro/astro/commit/03896405717471f7d6ff54986ed6beaec0cac94f"><code>0389640</code></a>
Thanks <a
href="https://github.com/ematipico"><code>@​ematipico</code></a>! -
Fixes an error that prevented projects using <code>astro:assets</code>
from starting or building</li>
</ul>
<h2>astro@7.3.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17767">#17767</a>
<a
href="https://github.com/withastro/astro/commit/ce7c91f77dbd7be03c04bc13f87af9d01fef6cef"><code>ce7c91f</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Adds <code>--ignore-lock</code> flag to <code>astro preview</code>,
allowing multiple preview servers to run simultaneously on different
ports. This is useful for E2E testing workflows (e.g., Playwright) that
need to run several preview servers at once.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17818">#17818</a>
<a
href="https://github.com/withastro/astro/commit/c0b65811dfa0dafa1aa04b7d6d67fd09250ff8c1"><code>c0b6581</code></a>
Thanks <a
href="https://github.com/florian-lefebvre"><code>@​florian-lefebvre</code></a>!
- Adds a <code>logger</code> parameter to image services hooks</p>
<p>Custom image services now receive Astro's runtime logger as an extra
argument. Messages logged with it are routed through the destination
configured in <code>logger</code> and respect your log level, instead of
being written straight to the console:</p>
<pre lang="ts"><code>import type { LocalImageService } from 'astro';
<p>const service: LocalImageService = {
// ...
async transform(inputBuffer, transform, imageConfig, logger) {
logger.warn(<code>Could not optimize
&amp;quot;${transform.src}&amp;quot;. Passing it through
unchanged.</code>);
return { data: inputBuffer, format: 'png' };
},
};
</code></pre></p>
<p>Astro's built-in Sharp service now uses this logger for the warnings
it emits when it encounters an unexpected or unsupported source
format.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17818">#17818</a>
<a
href="https://github.com/withastro/astro/commit/c0b65811dfa0dafa1aa04b7d6d67fd09250ff8c1"><code>c0b6581</code></a>
Thanks <a
href="https://github.com/florian-lefebvre"><code>@​florian-lefebvre</code></a>!
- Adds <code>logger</code> to the context object passed to cache
providers</p>
<p>Custom cache providers now receive Astro's runtime logger on the
context passed to <code>onRequest()</code>. Messages logged with it are
routed through the destination configured in <code>logger</code> and
respect your log level, instead of being written straight to the
console:</p>
<pre lang="ts"><code>import type { CacheProvider } from 'astro';
<p>const provider: CacheProvider = {
name: 'my-cache',
async onRequest({ request, url, logger }, next) {
logger.warn(<code>Skipping cache for ${url.pathname} because the
response sets a cookie.</code>);
return next();
},
// ...
};
</code></pre></p>
<p>Astro's built-in <code>memoryCache()</code> provider now uses this
logger for the warnings it emits when it skips caching a response that
sets cookies, and when a background revalidation fails.</p>
</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/withastro/astro/pull/17818">#17818</a>
<a
href="https://github.com/withastro/astro/commit/c0b65811dfa0dafa1aa04b7d6d67fd09250ff8c1"><code>c0b6581</code></a>
Thanks <a
href="https://github.com/florian-lefebvre"><code>@​florian-lefebvre</code></a>!
- Updates Astro's remaining internal warnings and errors to be written
through the configured logger instead of directly to the console, when
possible</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md">astro's
changelog</a>.</em></p>
<blockquote>
<h2>7.3.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/withastro/astro/pull/17899">#17899</a>
<a
href="https://github.com/withastro/astro/commit/03896405717471f7d6ff54986ed6beaec0cac94f"><code>0389640</code></a>
Thanks <a
href="https://github.com/ematipico"><code>@​ematipico</code></a>! -
Fixes an error that prevented projects using <code>astro:assets</code>
from starting or building</li>
</ul>
<h2>7.3.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17767">#17767</a>
<a
href="https://github.com/withastro/astro/commit/ce7c91f77dbd7be03c04bc13f87af9d01fef6cef"><code>ce7c91f</code></a>
Thanks <a
href="https://github.com/apps/astro-factory"><code>@​astro-factory</code></a>!
- Adds <code>--ignore-lock</code> flag to <code>astro preview</code>,
allowing multiple preview servers to run simultaneously on different
ports. This is useful for E2E testing workflows (e.g., Playwright) that
need to run several preview servers at once.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17818">#17818</a>
<a
href="https://github.com/withastro/astro/commit/c0b65811dfa0dafa1aa04b7d6d67fd09250ff8c1"><code>c0b6581</code></a>
Thanks <a
href="https://github.com/florian-lefebvre"><code>@​florian-lefebvre</code></a>!
- Adds a <code>logger</code> parameter to image services hooks</p>
<p>Custom image services now receive Astro's runtime logger as an extra
argument. Messages logged with it are routed through the destination
configured in <code>logger</code> and respect your log level, instead of
being written straight to the console:</p>
<pre lang="ts"><code>import type { LocalImageService } from 'astro';
<p>const service: LocalImageService = {
// ...
async transform(inputBuffer, transform, imageConfig, logger) {
logger.warn(<code>Could not optimize
&amp;quot;${transform.src}&amp;quot;. Passing it through
unchanged.</code>);
return { data: inputBuffer, format: 'png' };
},
};
</code></pre></p>
<p>Astro's built-in Sharp service now uses this logger for the warnings
it emits when it encounters an unexpected or unsupported source
format.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/withastro/astro/pull/17818">#17818</a>
<a
href="https://github.com/withastro/astro/commit/c0b65811dfa0dafa1aa04b7d6d67fd09250ff8c1"><code>c0b6581</code></a>
Thanks <a
href="https://github.com/florian-lefebvre"><code>@​florian-lefebvre</code></a>!
- Adds <code>logger</code> to the context object passed to cache
providers</p>
<p>Custom cache providers now receive Astro's runtime logger on the
context passed to <code>onRequest()</code>. Messages logged with it are
routed through the destination configured in <code>logger</code> and
respect your log level, instead of being written straight to the
console:</p>
<pre lang="ts"><code>import type { CacheProvider } from 'astro';
<p>const provider: CacheProvider = {
name: 'my-cache',
async onRequest({ request, url, logger }, next) {
logger.warn(<code>Skipping cache for ${url.pathname} because the
response sets a cookie.</code>);
return next();
},
// ...
};
</code></pre></p>
<p>Astro's built-in <code>memoryCache()</code> provider now uses this
logger for the warnings it emits when it skips caching a response that
sets cookies, and when a background revalidation fails.</p>
</li>
</ul>
<h3>Patch Changes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/withastro/astro/commit/92f23cc121d3a1a03c6fb901a519309662b333de"><code>92f23cc</code></a>
[ci] release (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17900">#17900</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/03896405717471f7d6ff54986ed6beaec0cac94f"><code>0389640</code></a>
fix: dont use internal paths (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17899">#17899</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/f800de13ffab9542f8d1bd13a8f4481c5f5c083a"><code>f800de1</code></a>
[ci] release (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17881">#17881</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/1e0b7e6023128ad25a79ac125f6d33e5936a3def"><code>1e0b7e6</code></a>
[ci] format</li>
<li><a
href="https://github.com/withastro/astro/commit/4671a5c2d215545d8d7f763381ec1084dce9b7d1"><code>4671a5c</code></a>
chore(deps): update react to v19 in <code>0-css</code> fixture (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17888">#17888</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/31b886b75259e5a8d50dc750e587ee9bc97ee099"><code>31b886b</code></a>
Update bundled Zod to 4.5 (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17862">#17862</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/e747cba07fcd2b9e7fb03c02ed42abfe2079daa2"><code>e747cba</code></a>
Skip unsupported Vary responses in the memory cache (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17886">#17886</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/fb5b0d0a952b50c48908a262a702f43dcf42f9e7"><code>fb5b0d0</code></a>
[ci] format</li>
<li><a
href="https://github.com/withastro/astro/commit/ce7c91f77dbd7be03c04bc13f87af9d01fef6cef"><code>ce7c91f</code></a>
Add <code>--ignore-lock</code> flag support to <code>astro
preview</code> (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17767">#17767</a>)</li>
<li><a
href="https://github.com/withastro/astro/commit/c0b65811dfa0dafa1aa04b7d6d67fd09250ff8c1"><code>c0b6581</code></a>
feat: use logger instead of console where possible (<a
href="https://github.com/withastro/astro/tree/HEAD/packages/astro/issues/17818">#17818</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/withastro/astro/commits/astro@7.3.1/packages/astro">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-13 10:23:12 -07:00
Maximilian Roos cff085edf9 docs: fix misplaced copy buttons by dropping terminal frames (#4090)
On every shell code block the copy button sat 40px below the top of the
code: on the second line of multi-line blocks, and hanging below
one-line blocks such as `wt merge --no-ff` on /merge/. Shell blocks were
Expressive Code terminal frames, and the terminal plugin deleted their
title bar, but Expressive Code still offsets the copy button by that
bar's height.

## Changes

- `docs/astro.config.mjs` sets `defaultProps: { frame: 'code' }`, so no
block is a terminal frame and there is no title bar to remove. The
plugin's header-removal hook and its `props.frame = 'terminal'` go, and
so does the `wt-commands-only` class: mobile wrapping in `custom.css`
now keys on whether a block contains captured output
(`:has(.wt-output)`).
- Blocks with several commands had a whole-block copy button and
per-line buttons in the same corner, handed over on hover by opacity. A
hidden button still takes clicks, so clicking a line's button could copy
the whole block, and on touch screens one button covered another. Most
of these blocks are lists of alternatives, so they now get only per-line
buttons, and the hover rule is deleted.
- Those blocks wrap (Expressive Code's `wrap` prop) unless they carry
captured output, since a per-line button sits at the end of its line and
scrolled out of view on the long `jq` examples on /list/. A per-line
button is no taller than its line, so buttons on adjacent lines no
longer overlap.
- The two multi-command blocks that only work run in order, the FAQ's
stash recipe and the `Equivalent to:` block under `wt step diff`'s **How
it works** (in `src/cli/step.rs`), are now `bash` fences, the form
`docs/CLAUDE.md` prescribes for a copyable recipe, so they keep one copy
button for the whole recipe. Terminal `--help` renders `console` and
`bash` fences alike (it strips `$ `), and the help snapshots are
unchanged.

## Side effect

Expressive Code strips comment lines only from what terminal frames
copy. The eight `bash` and `powershell` blocks with comments on
/shell-integration/ now copy them, as console blocks already did. Pasted
into zsh without `interactivecomments`, each comment line prints
`command not found: #`; the commands still run.

## Tests

A browser test checks every copy button on every page, at 393px with
touch and at 1376px, for three things: it sits on the line it copies, it
is inside the visible code, and it doesn't overlap another button. These
checks fail against worktrunk.dev and against a build without the wrap
and the height cap. The built-site and plugin tests now expect per-line
payloads and no block payload on multi-command blocks, and a plugin test
pins that blocks carrying output never wrap.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_013U96NY8qKtZhavBSwnfCYq

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-13 10:00:25 -07:00
Worktrunk Bot 28399c2ae5 fix(recover): find the bare repository when a deleted CWD has no .git ancestor (#4067)
Recovering from a deleted current directory never worked in a bare
repository. `recover_from_path` walks up from `$PWD` looking for a
`.git` **directory**, and a bare repo has no `.git` entry at all —
neither at the bare directory itself nor at any ancestor — so the walk
ran to the filesystem root and returned nothing. Every caller then
degraded: `wt switch` and the picker surfaced git's raw "cannot resolve
CWD" error instead of recovering, and `cwd_removed_hint()` fell back to
the bare `Current directory was removed` line with no `wt switch ^`
suggestion. Bare repos are a first-class layout here — and their
worktrees usually sit *inside* the bare directory, so the walk has
nowhere else to land.

`try_repo_at` now also accepts a directory that is itself a bare
repository, using git's own `is_git_directory` heuristic (a `HEAD` file,
an `objects/` directory, a `refs/` directory). The probe is a filesystem
check rather than a `Repository::at()` call because `at()` discovers
*upward*: asking it whether an arbitrary ancestor is a repository
answers for some enclosing repository instead of reporting "not one
here". The existing `was_worktree_of` validation is unchanged, so a
repository found this way still has to list the deleted path among its
worktrees before recovery accepts it.

The probe lives in `git::is_bare_repo_dir`, shared with `holds_git_data`
in `src/git/repository/worktrees.rs`, which already ended in the same
three checks — one home for the shape, so a later correction to it lands
once.

Verified by temporarily reverting the one-line predicate with the tests
in place: `test_recover_from_path_bare_repo_worktree` and
`test_try_repo_at_accepts_bare_repo_dir` both fail without it and pass
with it.

<details><summary>Local test runs</summary>

`cargo test --lib git::recover` (23 passed), `cargo test --test
integration bare_repository` (37 passed), `cargo test --test integration
recover` (1 passed), `cargo fmt --check`, `cargo clippy --lib
--all-features` — all clean.

One unrelated unit test,
`copy::tests::test_copy_dir_recursive_does_not_count_a_non_regular_file`,
fails in the tend sandbox with `PermissionDenied` from
`UnixListener::bind` — the sandbox blocks `AF_UNIX` sockets. It is green
on `main` in CI and untouched here.

</details>

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-12 20:52:31 -07:00
DDL 48626f2df9 fix(merge): honor git worktree lock when cleaning up (#4073)
## Summary
- `wt merge` built a `RemovalPlan` by hand and skipped the lock check
`wt remove` already had, so a successful merge could rename a `git
worktree lock`'d feature worktree into trash and report success.
- After merge, a locked worktree is now kept (`Worktree preserved
(locked)`) the same way a primary worktree is kept. The shared staging
path also refuses a lock, including under `--force`, so every removal
caller is covered.

## Test plan
- [x] `cargo test --lib -- git::remove::tests` (includes
`stage_refuses_locked_worktree` and
`stage_refuses_locked_worktree_even_with_force`)
- [x] `cargo test --test integration
test_merge_preserves_locked_worktree`
- [x] `cargo test --test integration test_merge_fast_forward`
- [x] `cargo test --test integration test_remove_locked` (existing lock
tests still pass)
- [ ] `git worktree lock .` in a feature worktree, then `wt merge` —
merge succeeds, worktree stays, message names the lock reason


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-12 19:25:46 -07:00
Maximilian Roos 10315349f4 Scope docs heading anchors under each subcommand section (#4079)
Command pages on the site append every subcommand's help, so headings
such as "Examples", "Options", and "Command reference" repeat down
`/step/` and `/config/`. The heading-id plugin numbered the repeats by
position (`/step/#examples-3`, `/step/#hooks-1`,
`/step/#command-reference-7`), so an anchor pointed somewhere else once
a same-named heading was added above it.

`docs/src/plugins/stable-heading-ids.mjs` now scopes ids below each
subcommand's H2 (a heading starting `wt `) by that section's id:
"Examples" under `wt step push` is `/step/#wt-step-push--examples`.
Page-level headings and the subcommand headings keep their ids, so the
table of contents and links like `/step/#wt-step-copy-ignored` are
unchanged. A slug never contains `--`, so a scoped id can't equal
another heading's slug — a "Cache" heading under `wt config state` stays
distinct from the `wt config state cache` section.

With the site handling it, the CLI help keeps unqualified headings.
#4000 renamed six `wt config` subcommand headings to "Approval
examples", "Alias examples", and so on to avoid the numbering; they're
back to "Examples", in `--help` as well.

Every anchor inside a subcommand section changes once:
`/step/#min-age-guard` is now `/step/#wt-step-prune--min-age-guard`. The
two internal links that pointed at such anchors — the FAQ's
copy-on-write link and `wt config approvals`' "Reading approval state" —
are updated, and `test:site` checks every internal fragment. External
links to the old anchors land at the top of the page.

The search-index plugin (`pagefind-command-references.mjs`) now imports
the subcommand-heading check from the heading-id plugin rather than
keeping its own copy.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01HUmx2Jd5mTK5TznqGDmLGp

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 16:57:33 -07:00
Worktrunk Bot ee52834701 docs(demos): record demos with the site's current palette (#4069)
The demo recorder kept its own copies of the docs site's colors, and
they had drifted from `docs/src/styles/custom.css`:

- The VHS terminal's ANSI colors were still the Zola site's palette,
which #3866 deleted and #3936 replaced with `--wt-terminal-*`. Light
yellow had 2.65:1 contrast against the page background; the site's
browser test requires 4.5:1 for its own dim terminal text.
- `brightWhite`, the background of Worktrunk's gutter, used the ink
color, so dark GIFs drew the gutter as a near-white bar.
- Zellij, the starship prompt, and Claude Code were configured for light
in both themes, so dark GIFs showed a light Zellij tab bar and Claude
Code's light theme.

`docs/demos/shared/themes.py` now reads the hex `--wt-*` properties from
`custom.css` when the build runs. The VHS theme maps ANSI colors the way
the site renders snapshot output (`terminal_color_class` and
`terminal_background_class` in
`tests/integration_tests/readme_sync.rs`). `DemoEnv` carries the
recording's theme, so Zellij, the starship palette, and Claude Code
follow it. This replaces the `(pre-Starlight; site is #…)` comments the
PR first added.

Recording from inside a Claude Code session also leaked into the Claude
demos. The demo's Claude Code inherited that session's `CLAUDE*`
variables and warned that transcript saving was off, and it started
Remote Control, which printed a live claude.ai session URL into the GIF.
The recorder now drops inherited `CLAUDE*` variables except
`CLAUDE_CODE_OAUTH_TOKEN`, and the demo's `settings.json` sets
`remoteControlAtStartup` to false.

The GIFs are re-recorded locally (`./docs/demos/build docs` and
`./docs/demos/build social`) and published in
max-sixty/worktrunk-assets@bb3bfba.

## Verification

- `pytest docs/demos/tests`: 4 passed.
- OCR of every 20th frame of the Claude demos (354 frames) finds no
`remote-control`, `claude.ai/code`, `rc active`, or `Transcript saving`.
The same check matches on frames from the leaking recording.
- Frames checked by eye in both themes for the ANSI colors, the gutter,
and the Zellij chrome.
- TUI validation passes for all nine Claude demo GIFs. The `wt-switch`
and `wt-statusline` checkpoints named absolute frames past the end of
these faster recordings (274–318 frames, against 344–465 in the
previously published GIFs), so a negative checkpoint frame now counts
back from the last frame; the omnibus checkpoint on its closing `wt
list` uses the same anchoring. The previously published GIFs pass the
new checkpoints too. Those checkpoints also forbid `claude.ai/code` and
`Transcript saving`, and a GIF made from a leaking frame fails on them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01TQPDxs2csvGFGBr2j4MtrA

> _This was written by Claude Code on behalf of max-sixty_

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Maximilian Roos <m@maxroos.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 15:42:32 -07:00
Maximilian Roos f194d5a13c Age branches by reflog entry in wt step prune; fix four doc claims (#4077)
`wt step prune` could delete a branch created a minute earlier. Its
min-age guard ages a branch that has no worktree by its oldest reflog
entry — the help text and the function's docstring both say so — but the
code read `git reflog show --format=%ct`, which is the committer date of
the commit the entry points at. `git branch foo main` on a default
branch whose last commit is more than a day old therefore looked days
old, and the next `wt step prune` removed it.

From `test_prune_orphan_branch_min_age`, a branch made 30 minutes before
the run, pointing at a month-old commit, with the default
`--min-age=1d`:

```console
$ wt step prune --yes          # before
✓ Removed branch orphan-integrated (same commit as main, _)
✓ Pruned 1 branch

$ wt step prune --yes          # after
○ Skipped orphan-integrated (younger than 1d)
```

The age now comes from the entry's own timestamp: `git reflog show
--date=unix --format=%gd` renders each selector as `<name>@{<epoch>}`.
`test_prune_orphan_branch_min_age` couldn't tell the two apart, because
the test harness gives the commit and the branch creation the same date;
its commit is now a month older than the branch, and the old code fails
it.

A branch with no reflog at all still counts as old enough, as before.
That includes a branch created only from a bare repository's own
directory, since a bare repository defaults `core.logAllRefUpdates` to
false; the docstring now says so. A branch created from inside a linked
worktree has a reflog.

Found while reviewing #4000, along with four doc claims corrected in a
separate commit:

- The hook page said `{{ vars.thing | upper }}` previews as `{{
VARS.THING }}`; `wt hook show --expanded` prints `'{{ VARS.THING }}'`,
shell-quoted like any other value.
- The agent-integration table checked `/wt-switch-create` for Codex and
Gemini while its footnote said it does nothing there; the mark moves to
the row label.
- The skill's agent-handoff instruction, followed literally for
OpenCode, dropped `run`; it now points at the tips section's note on
where a subcommand goes.
- `take_global_options`' docstring counted 11 Global Options blocks on
`wt config`; there were 12.

Reviewable files: `src/commands/step/prune.rs`,
`tests/integration_tests/step_prune.rs`, `src/cli/mod.rs` (one
sentence), `docs/src/content/docs/claude-code.md`,
`skills/worktrunk/SKILL.md`, `src/help.rs`, `CHANGELOG.md`. The skill
and plugin mirrors and the agent-skills digest are regenerated.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01HUmx2Jd5mTK5TznqGDmLGp

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 15:07:02 -07:00
Maximilian Roos dd389339f0 docs: sit the file-name tab flush with its code block (#4078)
Code blocks titled with a file name (for example `.config/wt.toml` above
a TOML excerpt) showed an awkward gap to the left of the name tab.
Expressive Code's `.header::before` draws a 1px outline around the whole
strip above the code, which our overrides left in place, and the tab was
inset 0.6rem from the frame's left edge, so an empty outlined box sat
beside it. The outline is removed and the tab now sits flush with the
frame's left edge, keeping its own background and rounded corners; the
copper rule still starts where the code does.

The browser test that already checks the label sits directly on its code
now also checks the label and the code share a left edge; with the old
inset restored, it fails.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_016NGjseUKXkyL8qHLhaXsnt

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 15:06:02 -07:00
Maximilian Roos 4f26e9a1c1 docs: keep code frames in the content column and dev-server styling current (#4076)
## Code frames leave the content column on wide screens

#4000 stretched every terminal frame to the full content panel at 72rem
and up, to give `wt list --full` room. Once the panel is wider than the
62rem column, Starlight offsets the column inside it, so shell snippets
moved left of the prose they belong to and spanned past it on the right,
while TOML frames stayed in the column. On
https://worktrunk.dev/tips-patterns/ at 2560px, prose starts at x=760
and shell frames at x=248, 1504px wide.

#4039 had already made terminal output fit the column. With the stretch
disabled, no output-bearing frame on any of the 15 pages overflows;
three long one-line commands on `/config/`, `/list/` and `/step/`
scroll, as long TOML lines already do. So the rule is removed rather
than narrowed.

The desktop browser test ran only at 1152px and 1376px, where the panel
and the column are the same width and the rule changed nothing. It now
also runs at 1920px and asserts every code frame stays within the
column; with the old rule restored, it fails on the homepage.

## The dev server loses code styling after a merge

Astro caches rendered Markdown with the Expressive Code stylesheet URL
baked in. That URL's hash comes from the code-rendering config and
plugins, which Astro's content-cache key doesn't cover. A merge that
changes `astro.config.mjs` and the terminal plugin under a running dev
server makes Astro restart it in place: the server serves the new
stylesheet while content keeps rendering with the old renderer, so every
page links a stylesheet that returns 404. Restarting the process doesn't
recover, because the cache survives it.

- `docs/package.json`: `dev` passes `--force`, as `build` already does,
so a restart re-renders.
- `.config/wt.toml`: the docs hook sets `ASTRO_DEV_BACKGROUND=1`. When
`astro dev` detects an AI agent, it respawns itself detached, which
drops `--force` and escapes `wt step tether`; three worktrees currently
run their dev servers that way.
- `docs/CLAUDE.md`: explains the cache and says to restart with `wt hook
post-start docs` after `astro.config.mjs` changes, since the in-place
restart is Astro's to fix.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_016NGjseUKXkyL8qHLhaXsnt

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-12 14:14:09 -07:00
Worktrunk Bot 240fd0166e docs(demos): point the theme-variant section at the real asset paths and palette file (#4068)
Two references in `docs/demos/CLAUDE.md` point at files and directories
that do not exist, so anyone following them to change a demo's colors or
find a recorded GIF lands nowhere.

- The **Light/dark theme variants** section lists the outputs as
`docs/light/wt-core.gif` and friends. The build writes them to
`docs/public/assets/<target>/<theme>/<name>.gif` (`OUT_DIR` in
`docs/demos/build`), which is exactly what the directory-structure block
at the top of the same file already says — the two sections contradicted
each other.
- The same section points at `_variables.html` as the palette source.
That file was removed in #3866 when the site moved to Astro and
Starlight; the `--wt-*` custom properties now live in
`docs/src/styles/custom.css`, which is also what
`docs/demos/shared/themes.py` names in its own docstring.

Documentation-only, so there is no regression test to add; the claims
are verified against `docs/demos/build` and against the file's own
structure block.

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-12 13:07:52 -07:00
Maximilian Roos 89326f14af Publish shell integration, add a footer, dedupe global options (#4000)
Guides and site presentation: one home per topic, a shell-integration
page, a footer, and three rendering fixes.

**Global options were emitted once per command reference**

clap repeats the same ~20-line `Global Options:` block in every
reference it renders, so a page assembled from subdocs stacked 11 copies
on `/config/` and 13 on `/step/`. That padded the pages and gave site
search that many near-identical hits — "squash" returned both
`#command-reference` and `#command-reference-2`. `take_global_options`
cuts each reference at the heading as it is built, keeping only the
first; one `kept` flag threads through the subdoc expansion and the page
streams out rather than accumulating. Terminal `--help` renders through
clap directly and is unchanged.

The config page also carried colliding anchors — two "Hooks" (`#hooks`,
`#hooks-1`), two "Aliases", and seven "Examples" (`#examples` …
`#examples-6`) — now qualified at their source in `src/cli/config.rs`:
User/Project hooks, User/Project aliases, and
Approval/Alias/State/Cache/Log/Variable examples.

`/step/` still has its own set (eight "Examples", two "Options", two
"Arguments", plus "Staging" and "Dry run" pairs). Qualifying those moves
existing `/step/#examples-N` anchors, so it wants a pass of its own with
the inbound links audited; the deduplication above already removes 13
Global Options blocks from that page.

**Shell integration has a page**

Shell-integration debugging was skill-only: five named warning messages,
a PowerShell checklist, and the wrapper mechanism, with no site page —
while the FAQ's answer to "`wt switch` didn't cd" was to install the
Claude Code plugin. It is now `/shell-integration/`, offered first, with
the plugin as the second route. The `llms.txt` listing serves every page
as `/<slug>.md` from a hand-created symlink, so a new page was a 404 the
listing still advertised; the symlink is added and the sync now fails
when a listed page has none.

**Presentation**

- A site footer carries the version (read from `Cargo.toml` at build
time), releases, changelog and license. No page named any of them, and
`/code-signing/` was reachable only from inside a collapsed block on the
homepage. Starlight's `Footer` is wrapped rather than replaced.
- `wt list --full` renders 1157px inside an 800px content column, so 40%
of it sat behind a horizontal scrollbar with the pane beside the column
empty. A terminal frame now takes the whole pane where there is slack,
measured with a query container rather than recomputed from Starlight's
layout formula.
- The `wt-command-reference` frames offered a copy button for 3,877
characters of generated help text; they now expose no copy control. A
console block listing several commands is as often a menu of
alternatives as a recipe, and nothing in the markup tells them apart, so
every command line in such a block carries its own copy control
alongside the block's.
- The four command demos and the two hand-written figures get captions;
the 2.33 MB homepage GIF below the fold loads lazily.

**Sidebar order is pinned**

`site-navigation.mjs` told readers a
`test_sidebar_matches_frontmatter_order` would fail when the authored
sidebar and the pages' `sidebar.order` disagreed. No such test existed,
and the disagreement it describes is exactly what the survey found:
`remove` listed before `merge`, Agent integration ahead of
lower-numbered pages. The test is written, so the sidebar and the
`llms.txt` ordering derived from the frontmatter can't drift apart
again.

<details>
<summary>Guide corrections</summary>

- Tips & patterns was 26 flat H2 recipes in no order, all 26 in the
sidebar. They group under five H2s — setup and layout, aliases and
hooks, per-worktree services, working with agents, status/commits/logs —
with each recipe demoted to H3. Anchors are level-independent, so
existing `/tips-patterns/#…` fragments still resolve.
- `-x 'opencode run'` has been broken since 0.75.0 made `-x` a literal
program: it is `-x opencode -- run '<task>'`.
- The branch-summary preview moved from tab 5 to 6 when the unified-diff
tab landed; the recipe names the `summary` tab instead of a number.
- The Caddy recipe claimed `feature-auth` hashes to port 16460 — that is
`fix-auth`'s port. It is 18283.
- `_` in `wt list` is same-commit *and clean*; the
same-commit-with-changes glyph is `–`, which is not safe to delete.
- `wt step prune` removes branches with no worktree too, and the min-age
guard ages a worktree by its creation time and a bare branch by its
oldest reflog entry.
- `wt step eval -v` prints fifteen variables; the example showed two
under a lead calling them "the available template variables".
- A filter applied to `{{ vars.<key> }}` acts on the placeholder the
preview substitutes, so `{{ vars.port | default('8080') }}` previews as
`{{ vars.port }}`, filter gone.
- The `.git/wt/cache/` table was missing `picker-preview`, and `wt
config state clear` prompts unless `--yes`.
- `skills/worktrunk/reference/README.md` was a symlink to the repo
README that `SKILL.md` never referenced, and the plugin mirror
dereferenced it into a 262-line copy carrying the star-history token,
share links, and a logo path resolving nowhere. Nothing generated it, so
deleting the symlink is the whole fix.
- One home per topic: agent handoffs stay in tips-patterns, activity
markers in `claude-code.md`, alias-template deferral in `extending.md`,
and the `codename` filter's two `worktree-path` recipes give way to the
config page that owns path templates. The FAQ's "Running tests" and "How
can I contribute?" duplicated the README's Contributing block down to
the share URLs.
- The FAQ linked `/worktrunk/#install`, the `noindex` compatibility
route; the plugin hook shim's Windows Terminal hint pointed there too.
Both use `/#install`, where the new sidebar Install entry goes.
- Example names settle on `myproject` / `feature-auth`; "sibling to main
repo" becomes "sibling to the main worktree", and `wt remove`'s "target
worktree" becomes "the worktree being removed" per the project's own
terminology rule.

</details>

UX survey items: `#36`, `#37`, `#38`, `#39`, `#45`, `#47`, `#48`, `#49`,
`#50`, `#51`, `#52`, `#61`, `#94`, `#95`, `#96`, `#97`, `#99`, `#100`.

Reviewable files: the hand-written pages under `docs/src/content/docs/`
(notably the new `shell-integration.md`, `tips-patterns.md`, `faq.md`),
`docs/src/components/Footer.astro`,
`docs/src/plugins/worktrunk-terminal.mjs`,
`docs/src/site-navigation.mjs`, `docs/tests/*.mjs`, `src/help.rs`,
`plugins/worktrunk/hooks/wt.sh`. Generated mirrors and snapshots are
regenerated.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01XAUYWFN9d9oh6jyoQiouHb

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-12 12:44:47 -07:00
Worktrunk Bot f6b699a208 docs(hook): say post-merge runs in the destination worktree regardless of removal (#4071)
## Problem

`wt hook --help` lists the three cases where a hook's `cwd` differs from
`worktree_path`, and the `post-merge` entry qualifies itself with "with
removal":

> - `post-merge` with removal: the active worktree is gone, so the hook
runs in the target worktree

That condition does not exist. `post-merge` is anchored on the merge
destination unconditionally — `approve_merge_plan` adds it at
`destination_path` outside the `will_remove` branch, and
`finish_after_merge` registers it there whether or not the feature
worktree was removed. The stated reason is wrong too: the hook runs in
the destination because it is *about* the destination, not because the
source worktree happens to be gone.

The qualifier is also the only place on the page that says this. The
hook-type table ("Runs in the target branch worktree if it exists,
otherwise the primary worktree") and the merge-pipeline paragraph
("post-merge, post-switch and post-remove in the destination") both
state the unconditional behavior, so the page contradicts itself — and
the bullet is the version a reader lands on when they are specifically
asking which tree the hook sees.

The failure it invites is concrete: under `--no-remove` both worktrees
are on disk, and a hook written from this bullet — a deploy, a build, an
external freshness check — inspects the pre-merge feature worktree while
reporting on the integrated result. #4070 asks exactly this question.

## Solution

Replace the qualifier with the behavior the code implements, naming the
`--no-remove` case explicitly since that is the one the old wording got
wrong:

> - `post-merge`: the hook runs in the target branch's worktree (the
primary worktree if the target has none), including under `--no-remove`,
where the merged worktree `worktree_path` names is still on disk

Source is `after_long_help` in `src/cli/mod.rs`; the three generated
mirrors are regenerated by `test_docs_are_in_sync`. No `--help` snapshot
captures this text.

## Testing

`test_merge_post_merge_runs_in_destination_with_no_remove` merges a
feature worktree with `--no-remove` and a `post-merge` hook that writes
a marker relative to its cwd, then asserts the marker lands in the
destination worktree and *not* in the preserved feature worktree. It
passes against unchanged code — the behavior was already correct, and
the test pins it so the documented contract cannot drift back.

`integration_tests::merge::` (153 tests), `integration_tests::help::`
(59), `integration_tests::readme_sync::` (18), `cargo fmt --check`, and
`cargo clippy --all-targets` all pass locally.

Closes #4070 — automated triage

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-12 08:42:40 -07:00
Worktrunk Bot b611d86e8e chore: update tend workflows (0.2.5 → 0.2.6) (#4064)
Regenerates the `tend-*` workflows against tend 0.2.6 (from 0.2.5). The
workflow files themselves only move the `max-sixty/tend/claude@` pin and
the generated-by header; the adopter-visible changes ride in the action
and its bundled skills, plus one generated `tend-mention` condition.

**The agent sandbox gets a writable `TMPDIR`.** Root `/tmp` is read-only
for the agent, and until now bundled scripts and skill recipes wrote
there anyway — this repo carries a note in
`.claude/skills/running-tend/SKILL.md` telling sessions to route scratch
paths through `${TMPDIR:-/tmp}` for exactly that reason (#4063). 0.2.6
exports a standard writable `TMPDIR` under the sandbox user's home and
moves the bundled scripts onto it, so a recipe that reaches for a plain
`/tmp` path no longer dies on `Read-only file system`
([max-sixty/tend#1199](https://github.com/max-sixty/tend/pull/1199)).

**A review the bot leaves on its own PR no longer summons a second
session.** `tend-mention`'s dispatch filter now returns early when the
review author is the bot, and `tend-review` applies its own findings on
PRs with no human author instead — the same rule step 9 of the review
skill already used for Dependabot and renovate PRs. Previously each
self-review round cost a cold `tend-mention` boot that re-read the whole
PR to apply fixes the reviewer had just written, then pushed and fired
another review
([max-sixty/tend#1203](https://github.com/max-sixty/tend/pull/1203)).
This is the one change visible in the generated YAML — the
`tend-mention.yaml` diff below.

**The maintainer-tier check reads `authorAssociation` correctly.** The
shared skill block claimed `gh pr view --json` doesn't expose the field
at all; it does, nested on the comment and review objects, and only the
top-level key is rejected. Sessions deciding whether a requester may
direct a destructive action were being pushed to the REST API
unnecessarily
([max-sixty/tend#1178](https://github.com/max-sixty/tend/pull/1178)).

Full comparison:
<https://github.com/max-sixty/tend/compare/0.2.5...0.2.6>.

<details><summary>Generated <code>tend-mention.yaml</code> condition
change</summary>

The dispatch filter gains an early bail on a bot-authored review:

```python
# A review the bot wrote hands work to nobody: the review session
# applies the findings it raised. The mention checks run first, so
# naming the bot in a review still summons a session.
if review_author == bot:
    return verdict(False)
```

replacing the prior participation branch, which dispatched when the PR
author was also the bot and the review carried a body or fresh inline
comments. The prompt for a genuine `pull_request_review` dispatch drops
the clause that told the session to action a review it had authored
itself.

</details>

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-11 10:16:22 -07:00
Worktrunk Bot c6747857c0 refactor(list): drop WorktreeState's unused string serialization (#4065)
From tonight's rolling survey of `src/commands/list/model/state.rs`.

`WorktreeState` derives `strum::IntoStaticStr` and carries a
`#[strum(serialize = "")]` on its `None` variant, but nothing converts a
`WorktreeState` to a string through it. The JSON `worktree.state` field
is hand-written in
[`worktree_state_to_json`](https://github.com/max-sixty/worktrunk/blob/b3e60b817cabe731f1124a8f6ca5aedd83d7d287/src/commands/list/json_output.rs#L450-L484),
which matches on the variant and returns its own literal; the table cell
goes through `Display`. `cargo clippy --all-targets --all-features` is
clean with the derive removed, which is the whole demonstration — a
derive produces no dead-code warning, so nothing else would ever have
flagged it.

Worth removing rather than leaving inert, because the two enums in this
file disagree about what the derive means. `MainState` derives it with
`#[strum(serialize_all = "snake_case")]` and genuinely uses it —
`MainState::as_json_str` is how `main_state` reaches the JSON output.
`WorktreeState` has no such attribute, so its derive yields variant
names verbatim: a future `as_json_str`-shaped helper written by analogy
would emit `"BranchWorktreeMismatch"` beside `main_state`'s
`"would_conflict"`, in a documented JSON field. Deleting the derive
means that helper has to choose its strings explicitly, the way
`worktree_state_to_json` already does.

No regression test is possible for a no-op deletion — the change removes
generated code that had no caller, so there is no behavior a test could
have caught. What the diff does add is the case
`test_worktree_state_display` was missing: `Detached` is the one variant
the test never asserted, and it is the variant whose glyph the enum's
own doc comment goes out of its way to justify ("`Detached` gets a glyph
of its own because nothing else in the row says so"). All seven variants
are now pinned.

<details><summary>Why the derive is unreachable</summary>

`Into<&'static str>` for `WorktreeState` has no call site — the two
places the enum's identity is turned into text both bypass it:

- `src/commands/list/json_output.rs` → `worktree_state_to_json` returns
hand-written `"no_worktree"`, `"branch_worktree_mismatch"`,
`"duplicate_branch"`, `"prunable"`, `"locked"`, and deliberately returns
no string for `None` and `Detached` (the sibling `detached` field
carries the latter).
- `src/commands/list/model/state.rs` → `impl Display for WorktreeState`
emits the glyphs.

</details>

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-11 10:16:11 -07:00
dependabot[bot] b3e60b817c chore: bump taiki-e/install-action from 2.87.7 to 2.87.8 (#4060)
Bumps
[taiki-e/install-action](https://github.com/taiki-e/install-action) from
2.87.7 to 2.87.8.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/taiki-e/install-action/releases">taiki-e/install-action's
releases</a>.</em></p>
<blockquote>
<h2>2.87.8</h2>
<ul>
<li>
<p>Update <code>shfmt@latest</code> to 3.14.1.</p>
</li>
<li>
<p>Update <code>release-plz@latest</code> to 0.3.162.</p>
</li>
<li>
<p>Update <code>protoc-gen-connect-openapi@latest</code> to 0.26.0.</p>
</li>
<li>
<p>Update <code>dprint@latest</code> to 0.57.4.</p>
</li>
<li>
<p>Update <code>cargo-llvm-cov@latest</code> to 0.9.1.</p>
</li>
<li>
<p>Update <code>cargo-crap@latest</code> to 0.5.0.</p>
</li>
<li>
<p>Update <code>cargo-binstall@latest</code> to 1.23.0.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md">taiki-e/install-action's
changelog</a>.</em></p>
<blockquote>
<h2>[2.87.8] - 2026-09-07</h2>
<ul>
<li>
<p>Update <code>shfmt@latest</code> to 3.14.1.</p>
</li>
<li>
<p>Update <code>release-plz@latest</code> to 0.3.162.</p>
</li>
<li>
<p>Update <code>protoc-gen-connect-openapi@latest</code> to 0.26.0.</p>
</li>
<li>
<p>Update <code>dprint@latest</code> to 0.57.4.</p>
</li>
<li>
<p>Update <code>cargo-llvm-cov@latest</code> to 0.9.1.</p>
</li>
<li>
<p>Update <code>cargo-crap@latest</code> to 0.5.0.</p>
</li>
<li>
<p>Update <code>cargo-binstall@latest</code> to 1.23.0.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/taiki-e/install-action/commit/d438492cf8a250514fa2d34b30bc3c0dc37c65ff"><code>d438492</code></a>
Release 2.87.8</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/cf1fadefa81706888511de4b6dda5534a9810ce9"><code>cf1fade</code></a>
Update <code>shfmt@latest</code> to 3.14.1</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/716144916a3915dc9bcab576a4b42f6a73a7916c"><code>7161449</code></a>
Update <code>release-plz@latest</code> to 0.3.162</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/58df4bb0bb13dd31dec0368d34a84838ee17cc3f"><code>58df4bb</code></a>
Update <code>protoc-gen-connect-openapi@latest</code> to 0.26.0</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/33e9ffe8c37b89671bb5af911d757e2c8f6edb06"><code>33e9ffe</code></a>
Update oxfmt manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/60bf88260035dd852365b5be9ea4c5943f6f78b4"><code>60bf882</code></a>
Update kache manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/667469ac9d4299c56a06cc1254ce49d5fbbce0d4"><code>667469a</code></a>
Update <code>dprint@latest</code> to 0.57.4</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/aa52fd60cfec9c5d7b51a839a6c959b637e2fff4"><code>aa52fd6</code></a>
Update <code>cargo-llvm-cov@latest</code> to 0.9.1</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/834d344d8d8be0d9a673636b899f33f177f880a5"><code>834d344</code></a>
Update <code>cargo-crap@latest</code> to 0.5.0</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/097f1f0064569e498b3b1f6085a6bc5ff24c91f5"><code>097f1f0</code></a>
Update <code>cargo-binstall@latest</code> to 1.23.0</li>
<li>Additional commits viewable in <a
href="https://github.com/taiki-e/install-action/compare/v2.87.7...v2.87.8">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=taiki-e/install-action&package-manager=github_actions&previous-version=2.87.7&new-version=2.87.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-10 04:34:00 -07:00
Worktrunk Bot 3d1b5d58b1 fix(config): migrate [ci] platform into a [forge] table that lacks it (#4061)
`migrate_ci_doc` stood down whenever a `forge` key existed at all. But a
`[forge]` table that only sets `hostname` has the `platform` slot free —
there is nothing unsafe there to guard against, and the rule reports
nothing when it makes no change, so the deprecated `[ci] platform` was
left in place, no deprecation warning fired, and `wt config update`
didn't move it either.

That is the config a GitHub Enterprise or self-hosted GitLab user
arrives at by the obvious route: `[ci] platform` predates the `[forge]`
rename, and `[forge] hostname` gets added later when an SSH host alias
breaks `pr:` resolution. From then on the deprecated key is pinned
silently. Nothing is broken today — `ProjectConfig::forge_platform`
falls back to `ci.platform` — but the deprecation messaging is the only
thing standing between that user and a config that stops working when
`[ci]` is finally removed, and it never reached them.

The guard now keys on the destination *key* rather than on `forge`
existing: an occupied `platform`, or a `forge` that isn't a table
(`forge = "x"`, an inline table), still stands down and leaves the
document byte-identical. A free `platform` slot in an existing `[forge]`
takes the migrated entry, key decor and all.

One wrinkle worth flagging: when the migration empties `[ci]` and
creates `[forge]` itself, `[ci]`'s decor — the comment above its header
— moves to the new table. Inserting into an *existing* `[forge]` has
nowhere to put that comment, since `[forge]` is wherever the user wrote
it, possibly far away. So an emptied `[ci]` is removed only when its own
decor is blank; a commented one stays behind as an empty section. That
contributes no config and raises no warning, and it keeps the user's
prose where they put it.
`test_ci_migration_keeps_commented_ci_when_forge_exists` pins that
shape.

The framework invariant holds either way —
`test_warning_fires_iff_update_changes` gains the newly-migrating cases
in its `rewritten` list (with and without the comment) and the
inline-table suppression in `untouched`. All four new or extended tests
fail against the pre-fix guard.

<details><summary>Verification</summary>

```
cargo test --lib config::deprecation   # 165 passed
cargo fmt --check                      # clean
cargo clippy --lib --all-features      # clean
cargo test --lib                       # 1523 passed, 1 failed
```

The one `cargo test --lib` failure is
`copy::tests::test_copy_dir_recursive_does_not_count_a_non_regular_file`,
which binds a Unix domain socket; the CI agent sandbox blocks
`socket(AF_UNIX, …)`, so it fails there regardless of this change. `ci`
is green on `main` at 0683ad85.

</details>

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-10 04:33:57 -07:00
Worktrunk Bot c93b494bd0 test(configure_shell): pin the AUR PKGBUILD's fish completion to its generator (#4062)
The `worktrunk-bin` AUR package installs fish completions from a heredoc
in `.github/aur/PKGBUILD` that hand-copies what
`fish_completion_content("wt")` produces — makepkg runs no Rust, so
there is no way to call the generator from there. The PKGBUILD's own
`TODO` notes the duplication ("a bit hacky, but short enough that copy &
paste is OK for the moment"), but nothing checks it. The two copies are
identical today; if the generator changes, the next release ships a
stale completion to AUR users and the only symptom is someone's
tab-completion quietly producing nothing.

This adds a unit test next to the existing `fish_completion_content`
snapshots asserting the PKGBUILD still contains the generated string
verbatim, printing the replacement text on failure. It's a real surface:
the docs point at the official Arch package now, but `worktrunk-bin` was
deliberately kept publishing (#2052) and at least one user tracks it for
newer releases than the official package carries.

`.github/aur/PKGBUILD` is read at test time and so never appears in
coverage, which means a PKGBUILD-only edit maps to no test and would
slip through `cargo affected run`. It gets a
`workspace.metadata.affected.rule` for that — the same treatment
`readme_sync`'s runtime-read inputs already have.

`.gitattributes` pins the PKGBUILD to an LF checkout, because a byte
comparison against a `\n`-emitting generator is only meaningful if the
file on disk is LF everywhere. Git for Windows defaults to
`core.autocrlf=true` and the path carried no `text`/`eol` attribute, so
Windows checked it out CRLF and the assertion could never match — which
is how the first push went red on `affected tests (windows, advisory)`.
Pinning is right independently of the test (makepkg reads the file as a
shell script), it's the same mechanism `templates/* text eol=lf` already
uses, and unlike `readme_sync`'s `#![cfg(not(windows))]` it leaves
Windows actually running the drift check. The stored blob is already LF,
so nothing renormalizes; a Windows clone predating the attribute needs
the file re-checked out once (`git rm --cached .github/aur/PKGBUILD &&
git checkout -- .github/aur/PKGBUILD`), and CI checks out fresh.

**One thing I could not verify here:** `cargo-nextest` isn't reachable
from the CI agent sandbox (`tend: cargo-nextest came from the runner
home and is unavailable`), so I couldn't run `cargo nextest list -E
'test(/aur_pkgbuild/)'` to confirm the new filterset selects the test.
The expression mirrors the existing `test(/readme_sync/)` rule exactly,
and the repo's own nextest run will exercise it.

<details><summary>Verification</summary>

Run on Linux only — the sandbox has no Windows or macOS host, so the
cross-platform claim rests on CI (`test (windows)` and `full-tests
(windows-2025, windows)`), not on these:

```
cargo test --bin wt aur_pkgbuild        # passes
cargo test --bin wt configure_shell     # 33 passed
cargo fmt --check                       # clean
cargo clippy --bin wt --all-features    # clean
```

Drift is actually caught: with `--exclusive` deleted from the PKGBUILD's
`complete` line, the test fails and prints the correct replacement body.

The CRLF mechanism behind the Windows failure, reproduced on Linux
against a scratch repo with `core.autocrlf=true`:

```
without .gitattributes entry: CR count = 29
with    .gitattributes entry: CR count = 0
```

</details>

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-10 04:33:49 -07:00
Worktrunk Bot bdfee6a713 Write CI scratch files to $TMPDIR instead of the sandbox's read-only /tmp (#4063)
Two CI-facing recipes in this repo write scratch files to a path the
agent sandbox no longer allows, so each fails at its first redirect.
This points them at `${TMPDIR:-/tmp}` — writable inside the sandbox, and
still `/tmp` for a local run.

Since tend 0.2.3 the agent runs inside a sandbox with an allowlisted
write set, and root `/tmp` is not in it. This repo picked that up with
the 0.2.5 regeneration in #4057, merged yesterday at 10:37. Verified
from inside a tend session on this repo:

```
$ sh -c 'echo x > /tmp/codecov.json'
sh: 1: cannot create /tmp/codecov.json: Read-only file system
```

The affected recipes:

- **`tests/CLAUDE.md` → Coverage Investigation** — `curl … >
/tmp/codecov.json` plus the two `jq` reads of it. This block exists for
exactly the case that now breaks: it names "running in CI, where `task
coverage` isn't installed" as one of its two reasons to query Codecov
directly, and `.claude/skills/running-tend/SKILL.md` sends every CI
session investigating a `codecov/patch` failure here.
- **`.claude/skills/running-tend/SKILL.md`** — the
`code-coverage-report` artifact download (`/tmp/coverage.zip`, `unzip -d
/tmp/coverage`) and the weekly statusline cache-check's stdin fixture
(`/tmp/statusline-input.json`).

Both rewritten forms were run in this session before committing: the
codecov query against `#4058`'s base→head pair returns the real per-file
patch table, and `jq -n … > "${TMPDIR:-/tmp}/statusline-input.json"`
plus the `<` redirect back out both work.

**This is not the upstream bug.** The same `/tmp` assumption in tend's
own bundled scripts and skills is
[max-sixty/tend#1192](https://github.com/max-sixty/tend/issues/1192),
fixed by
[max-sixty/tend#1199](https://github.com/max-sixty/tend/pull/1199) and
merged 2026-09-09T08:23Z — about two hours after 0.2.5 tagged, so it
reaches this repo at the next release plus regeneration. That fix covers
bundled files only, and its own test asserts that root `/tmp` **stays**
read-only, so these repo-local recipes stay broken until they change
here.

One sentence was added next to the existing "don't `cargo install` in
the sandbox" note, so the next author editing these recipes knows why
the paths look like that.

<details><summary>Evidence and gate assessment</summary>

Found by the daily review-runs sweep, run
[34451797174](https://github.com/max-sixty/worktrunk/actions/runs/34451797174).

**Confidence** — structural, not stochastic: the write fails on the same
syscall every time, for every session, and it is reproduced above rather
than projected. Thirteen sessions in this window hit read-only `/tmp` on
other paths; the nightly
[34446121464](https://github.com/max-sixty/worktrunk/actions/runs/34446121464)
hit it eight times, including `tee: /tmp/tend-check.txt: Read-only file
system` and an `OSError: [Errno 30] Read-only file system` traceback out
of `nightly_workflow_update.py`. Neither of the two recipes changed here
was exercised in this window — no `tend-weekly` run, and no coverage
dispute — so the specific sites are unfired rather than observed
failing.

**Magnitude** — targeted fix: seven path substitutions and one sentence,
no new section and no new machinery.

**Cost** — waste-class, with a false-claim edge. A session whose codecov
recipe dies mid-investigation either improvises or, per
`running-in-ci`'s rule on unrun gates, has to report the gate as unrun;
the weekly statusline check is the one that could otherwise read as
clean. The remedy is a literal swap in existing lines, which clears the
bar a waste-class finding sets.

</details>

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-10 04:33:46 -07:00
Maximilian Roos f85230dc62 Tidy shell-integration output: prompt spacing, restart hint, one install hint (#4059)
Five things the shell-config surface got wrong, all found by running `wt
config shell install` and `wt config show` on a machine with five shells
configured.

**The prompt opened with a blank line.** `prompt_yes_no_preview` printed
one before every prompt, but most prompts are the first thing their
command prints — `wt config shell install`, `wt config plugins claude
install`, the commit-generation offer at the top of `wt merge` — so the
blank was the leading blank `/writing-user-outputs` forbids. Two PTY
snapshots covering the install prompt had a `trim_start_matches('\n')`
compensating for it, now removed. The separator belongs to the narration
it separates from, so the four callers that print first emit it
themselves.

**`wt config shell install` told an already-wrapped shell to restart.**
The hint says integration needs activating, and reinstalling from inside
a wrapped shell is exactly when it doesn't: a version bump, or the fish
`conf.d` to `functions` relocation, which writes a new file for a
wrapper the running shell already has. Gated on
`is_shell_integration_active()`.

**`wt config show` printed one remediation command per problem.** An
outdated wrapper, fish integration at the deprecated `conf.d` path, and
a missing fish completions file each carried their own `wt config shell
install <shell>`, so three problems printed three commands where the
bare `wt config shell install` fixes all of them. Each row now counts
toward the section's single trailing hint, and the fish
deprecated-location row names its destination inline the way the install
output's cleanup line does. `To verify wrapper loaded: type wt` stays
separate, since installing doesn't fix it.

**A deprecated fish wrapper wasn't a config location.** Consolidating
onto the bare command assumed it covers every state the section reports,
and it didn't: with a wrapper at `~/.config/fish/conf.d/wt.fish` and no
`~/.config/fish/functions` directory, fish has no config location, so
the scan skipped it and only `wt config shell install fish` — which sets
`allow_create` through its shell filter — migrated the wrapper. A
worktrunk wrapper at the deprecated path now counts as fish being
configured, just at the old path. That collapses `should_configure` into
`allow_create || has_config_location`, makes config show's skipped-shell
branch for legacy fish unreachable, and gets the wrapper into the report
for a user who doesn't have fish on `PATH` — where the skipped list,
gated on `is_installed`, showed nothing for fish at all.

**The zsh `compinit` snippet rendered plain.** It went through
`format_with_gutter` where the same snippet in the install output goes
through `format_bash_with_gutter`, so one was dim and highlighted and
the other wasn't.

> _This was written by Claude Code on behalf of max-sixty_

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 09:46:42 -07:00
Zexin Yuan da3707f008 fix(commands): name the configured alias instead of "unrecognized subcommand" outside a repository (#3982) 2026-09-09 08:14:40 -07:00
Worktrunk Bot d0fbe2c4aa fix(alias): let a template's own dry_run binding take --dry-run <value> (#4058)
An alias whose template references `{{ dry_run }}` can't be given
`--dry-run <value>` in the space-separated form. `AliasOptions::parse`
matches that exact token before any routing and bails with worktrunk's
retired-flag migration error, whatever the template binds:

```console
$ cat ~/.config/worktrunk/config.toml
[aliases]
deploy = "./deploy.sh {% if dry_run %}--dry-run{% endif %}"

$ wt deploy --dry-run 1
✗ --dry-run is no longer supported; use `wt config alias dry-run deploy` instead
```

The `=` spelling of the same flag already binds, because the bail
compares the whole token and `--dry-run=1` isn't equal to `--dry-run`.
So the two forms of one flag disagree, and the error names a subcommand
that previews the alias rather than passing the value the user was
trying to pass.

## Change

The bail yields to a template that references `dry_run` — one condition,
in the parser's existing routing loop — but only for the value-taking
spellings. This is the deference the parser already gives the two
comparable flags: `try_intercept_alias_help` intercepts `--help` "only
when the template doesn't reference [`help`]", and `--yes` — retired
from the post-alias position by
[#2290](https://github.com/max-sixty/worktrunk/pull/2290) — follows the
ordinary `--KEY` rule and binds when `yes` is referenced.

A **bare `--dry-run` with nothing to consume still bails**, in both the
referenced and unreferenced cases. The general `--KEY` end-of-args rule
forwards such a token into `{{ args }}`, which for a `{% if dry_run %}`
template means `dry_run` stays unset and the live command runs with exit
0 and nothing on stderr — the silent forward this bail exists to
prevent, on the flag whose purpose is not doing the thing. Failing there
is what [Data
Safety](https://github.com/max-sixty/worktrunk/blob/de4558fa29ce2273e6b3ce297b1c5d6c5408a220/CLAUDE.md)
asks for ("prefer failure over silent loss"), and it costs the user only
the `=`: the referenced case gets its own message naming `--dry-run=1`,
since `wt config alias dry-run <name>` previews the alias rather than
passing a value.

Everything else is untouched: an alias that doesn't reference `dry_run`
still gets the migration error, and `wt deploy -- --dry-run` still
forwards the token as a positional.

## Testing

Against a build of this branch, with `deploy = "echo ./deploy.sh {% if
dry_run %}--dry-run{% endif %}"`:

```console
$ wt deploy --dry-run
✗ --dry-run at the end of the command binds nothing, leaving `dry_run` unset in deploy; pass `--dry-run=1` instead

$ wt deploy --dry-run 1
./deploy.sh --dry-run

$ wt deploy --dry-run=1
./deploy.sh --dry-run

$ wt deploy
./deploy.sh
```

`test_parse_dry_run_binds_when_referenced` pins the two value-taking
spellings (both fail on `main` — the first assertion panics unwrapping
the bail). `test_parse_dry_run_bare_errors_when_referenced` pins the
bare form's error and the `--` literal forward beside it.
`test_parse_errors` keeps the unreferenced case on the migration error.

`cargo test --bins alias` (33) and `cargo test --test integration
step_alias` (81) pass; `cargo clippy --bin wt --all-targets` is clean.

Found by the nightly survey reading `src/commands/alias.rs`; no user
reported it.

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-09 03:37:59 -07:00
Worktrunk Bot c308b204cf chore: update tend workflows (0.2.0 → 0.2.5) (#4057)
Regenerates the eight `tend-*.yaml` workflows with tend 0.2.5, up from
0.2.0, and adapts this repo's setup to the sandbox boundary that comes
with it. The substantive upstream change is where the agent's code
lives: the action now builds its own disposable `/tmp` clone instead of
the workflow rewriting the runner's checkout, and the Anthropic Sandbox
Runtime fences the agent off from the runner's home and checkout for the
whole lifecycle.

That fence is why this PR is more than a regeneration. Three things this
repo does stopped working across it, all of them silently; each is
handled below.

## Upstream changes

**Agent sessions get an isolated workspace.** Each
`max-sixty/tend/claude` step now takes `checkout_mode` (`base`,
`review`, or `mention`) plus `base_branch`, and creates the tree it
works in itself
([max-sixty/tend#1173](https://github.com/max-sixty/tend/pull/1173)).
The runner's own checkout stays on the base branch, which is what
`.github/actions/tend-setup` and its POST cleanup run against. Three
hand-rolled steps disappear as a result: `tend-review`'s
`refs/pull/N/merge` probe and second `actions/checkout`,
`tend-mention`'s `gh pr checkout` (which also picks up the upstream fix
for a mention on an issue or a closed PR,
[max-sixty/tend#1175](https://github.com/max-sixty/tend/pull/1175)), and
both workflows' "Restore local setup actions for POST cleanup" step —
nothing overwrites `.github/actions/tend-setup` in the runner tree any
more.

**`tend-ci-fix` now fires on cancelled runs, not just failures.** The
job condition becomes `contains(fromJSON('["failure", "cancelled"]'),
…)` and the prompt carries `Conclusion:` so the session can tell the two
apart. A watched workflow that ends `cancelled` on `main` previously
produced no session at all.

**Bundled skills move with the pin.** `review-runs` no longer scopes its
live-work default-branch CI check to `ci-fix`'s watched workflows
([max-sixty/tend#1170](https://github.com/max-sixty/tend/pull/1170)),
outage-row enrichment reads the failing attempt so a rerun-green run
keeps its diagnosis
([max-sixty/tend#1166](https://github.com/max-sixty/tend/pull/1166)),
and the guidance text is now harness-portable
([max-sixty/tend#1188](https://github.com/max-sixty/tend/pull/1188)).
Codex-harness work in this range does not reach this repo, which runs
the `claude` harness.

Full comparison:
[0.2.0…0.2.5](https://github.com/max-sixty/tend/compare/0.2.0...0.2.5).

## What this repo had to change

**The cargo tools move to `/usr/local/bin`.** This was a merge blocker,
not a cleanup. `sandbox_runtime.mjs` configures `denyRead: [runnerHome,
runnerWorkspace]` and `sandbox_setup.py` runs the adopter block *inside*
that boundary under `bash -eo pipefail`, so the two `install -m755
/home/runner/.cargo-install/…` lines every workflow carried would have
aborted the lifecycle before the harness started — a red job and a
`tend-outage` issue on every trigger, in all eight workflows.
`tend-setup` now `sudo install`s both binaries into `/usr/local/bin`
after building them, which is the system-location route `nu` and `nix`
already take, and `.config/tend.yaml` keeps only the `pre-commit` line,
which installs into the sandbox's own home and reads nothing
runner-owned. The closing probe still asserts all five tools.

**The rust-cache restore is removed, along with the `CARGO*`/`RUST*` env
block that existed only to match its key.** With the agent in a `/tmp`
clone and the runner's tree under `denyRead`, a restored `~/.cargo` and
`<runner checkout>/target` are unreachable *and* at the wrong path — the
restore warmed nothing and cost the download in eight workflows. The
capability loss is real and is not caused by this removal: tend sessions
that compile now compile cold, where a 0.2.0 session inherited a 5.1 GB
warm `target/` (measured in a live session on the current pin). I've
asked upstream for a supported hand-off into the agent's own tree,
[max-sixty/tend#1198](https://github.com/max-sixty/tend/issues/1198);
this step comes back if that lands. Happy to restore it now instead if
you'd rather keep the machinery in place while that's open.

**`nix` can no longer reach its daemon, which breaks the weekly
`flake.lock` refresh.** SRT blocks `socket(AF_UNIX, …)` with `EPERM` by
default on Linux, and tend passes neither `allowUnixSockets` nor
`allowAllUnixSockets`. The multi-user Nix client connects to
`/nix/var/nix/daemon-socket/socket`, so `nix flake update rust-overlay`
and `nix eval` in `tend-weekly` fail. Nothing here can fix it — it needs
an upstream lever,
[max-sixty/tend#1197](https://github.com/max-sixty/tend/issues/1197).
The `Install Nix` step stays (it is the half of the route this repo
owns, and `nix` still works for anything running as `runner`), and the
weekly skill now tells that session to report the failure and carry the
rest of the toolchain bump rather than treat it as a broken bump. **This
is the one degradation this PR ships rather than fixes.**

**Three skill claims the bump falsifies are corrected here** rather than
deferred. `nightly-cleaner.md` said `tend-ci-fix` "does not fire on runs
that end `cancelled`", which is exactly what changes above.
`running-tend`'s session-log path can no longer name a literal now that
the artifact directory is slugified from a per-run `/tmp` path. And its
statusline cache-check justified a debug build by `tend-setup`'s
rust-cache step being `save-if: false` under a key no workflow writes —
the step this PR removes; the conclusion survives on the simpler reason
that `tend-weekly` restores no Rust cache at all. That last section is
also trimmed back to the fact local to this repo, since the `find`
recipe it had grown to restate is already in the bundled skills.

## Verification

The regeneration is reproducible: `uvx tend@0.2.5 init` against the
edited `.config/tend.yaml` produced the eight workflow files with no
diff beyond the two removed `install` lines.

Everything else was read out of the pinned sources rather than run,
because no check in this repo exercises a tend job's sandbox — green CI
here is not evidence either way. The first real test of the
`/usr/local/bin` route is the first tend job on the new pin.

<details><summary>What was read, and what it establishes</summary>

- `shared/steps/sandbox_runtime.mjs@0.2.5` — `denyRead: [runnerHome,
runnerWorkspace]`, with `runnerHome` set from
`pwd.getpwuid(os.getuid()).pw_dir` in `proxy/setup_sandbox.py` (i.e.
`/home/runner`). The file does not exist at 0.2.0 and first appears at
0.2.1, so the boundary genuinely arrives with this bump.
- `shared/steps/sandbox_setup.py@0.2.5` — refuses to run unless
`TEND_INSIDE_SANDBOX=1`, and execs the adopter block as `bash -eo
pipefail -c`.
- `shared/steps/prepare_agent_workspace.py@0.2.5` —
`mkdtemp(prefix="tend-agent-workspace-", dir="/tmp")`, "`RUNNER_TEMP`
and the runner checkout are never handed to the agent".
- `@anthropic-ai/sandbox-runtime@0.0.75` README (the version
`claude/action.yaml` pins) — reads are allowed everywhere except
`denyRead`, which puts `/usr/local/bin` in the clear; Unix sockets are
"blocked by default on both platforms", the Linux filter "blocks
creation of `AF_UNIX` sockets by returning `EPERM`", and on Linux
`allowUnixSockets` path allowlisting is ignored, so
`allowAllUnixSockets` is the only lever.
- Probed from a live 0.2.0 session: `/usr/local/bin` is on the sandbox
PATH and world-writable on the runner image; `CARGO_TERM_COLOR`,
`CARGO_INCREMENTAL` and `RUSTFLAGS` are all unset in the agent's
environment, confirming that env block served the cache key alone.

</details>

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-09 03:37:52 -07:00
dependabot[bot] b8510a5829 chore: bump svgo from 4.0.2 to 4.1.0 in /docs (#4045)
Bumps [svgo](https://github.com/svg/svgo) from 4.0.2 to 4.1.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/svg/svgo/releases">svgo's
releases</a>.</em></p>
<blockquote>
<h2>v4.1.0</h2>
<p>This minor release upgrades the SAX parser and introduces stricter
XML validation. It also includes important security hardening for
<code>removeScripts</code>, dependency updates, and improvements to the
test and regression infrastructure.</p>
<h3>Support SVGO</h3>
<p>If SVGO is valuable to you or your organization, please consider <a
href="https://opencollective.com/svgo">supporting the project on
OpenCollective</a>. Your sponsorship helps fund ongoing maintenance and
security work.</p>
<h3>Stricter XML validation</h3>
<p>SVGO now uses <a
href="https://www.npmjs.com/package/sax"><code>sax</code> 1.6.1</a>,
upgraded from 1.5.0 (<a
href="https://redirect.github.com/svg/svgo/pull/2257">#2257</a>).</p>
<p>The new parser version validates numeric character references against
the ranges permitted by XML. Invalid references are now rejected in both
text and attributes, including:</p>
<ul>
<li>disallowed control characters such as
<code>&amp;[#1](https://github.com/svg/svgo/issues/1);</code>,
<code>&amp;#xB;</code>, and <code>&amp;#x1F;</code>;</li>
<li>UTF-16 surrogate code points such as <code>&amp;#xD800;</code>;</li>
<li>invalid XML code points such as <code>&amp;#xFFFF;</code>.</li>
</ul>
<p>Valid boundary values—including <code>U+0020</code>,
<code>U+D7FF</code>, <code>U+E000</code>, <code>U+FFFD</code>, and
characters through <code>U+10FFFF</code>—remain supported.</p>
<p>Parser failures are consistently exposed as
<code>SvgoParserError</code> errors with an <code>Invalid character
entity</code> reason.</p>
<p>This is an intentional behavior change: malformed SVGs that were
previously accepted may now produce a parser error, while valid XML
documents are unaffected.</p>
<h3>Security</h3>
<p>The <a
href="https://svgo.dev/docs/plugins/removeScripts/"><code>removeScripts</code></a>
plugin has been hardened against several script-execution bypasses:</p>
<ul>
<li>Filters executable <code>data:</code> URLs containing HTML, XHTML,
or SVG documents while preserving inert data such as PNG images, and
filters legacy <code>vbscript:</code> URLs (<a
href="https://redirect.github.com/svg/svgo/pull/2263">#2263</a>).</li>
<li>Sanitizes content inside SVG <code>&lt;foreignObject&gt;</code>
elements by removing HTML event-handler attributes, <code>srcdoc</code>,
and executable URLs from <code>action</code>, <code>data</code>,
<code>formaction</code>, <code>href</code>, and <code>src</code>, while
preserving non-executable HTML and visual content (<a
href="https://redirect.github.com/svg/svgo/pull/2264">#2264</a>).</li>
<li>Recognizes namespace-prefixed SVG <code>&lt;a&gt;</code> elements
and removes ASCII tabs and newlines before checking URL schemes,
preventing values such as
<code>java&amp;[#9](https://github.com/svg/svgo/issues/9);script:</code>
from bypassing detection while preserving elements in unrelated custom
namespaces (<a
href="https://redirect.github.com/svg/svgo/pull/2268">#2268</a>).</li>
</ul>
<p>These changes address:</p>
<ul>
<li><a
href="https://github.com/svg/svgo/security/advisories/GHSA-4vpr-x523-8j87">GHSA-4vpr-x523-8j87</a></li>
<li><a
href="https://github.com/svg/svgo/security/advisories/GHSA-w27v-7q3p-w38r">GHSA-w27v-7q3p-w38r</a></li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>Upgraded <code>css-select</code> to v6 and <code>css-what</code> to
v7, and updated SVGO's custom selector adapter for
<code>css-select</code> v6 (<a
href="https://redirect.github.com/svg/svgo/pull/2244">#2244</a>).</li>
</ul>
<h3>Project maintenance</h3>
<p><a href="https://github.com/TrySound"><code>@​TrySound</code></a> is
back as an active SVGO maintainer.</p>
<p>Many thanks to <a
href="https://github.com/KTibow"><code>@​KTibow</code></a>, <a
href="https://github.com/SethFalco"><code>@​SethFalco</code></a>, and <a
href="https://github.com/XhmikosR"><code>@​XhmikosR</code></a> for
maintaining and improving SVGO over the past several years.</p>
<p><strong>Full Changelog:</strong> <a
href="https://github.com/svg/svgo/compare/v4.0.2...v4.1.0">https://github.com/svg/svgo/compare/v4.0.2...v4.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/svg/svgo/commit/5765cbe4e0a930dca648c6b81d335b1522cd7375"><code>5765cbe</code></a>
chore: prepare v4.1.0 release (<a
href="https://redirect.github.com/svg/svgo/issues/2275">#2275</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/3db3ef33e409a0bc0fdaf255e46c908b00e93bc2"><code>3db3ef3</code></a>
fix(removeScripts): handle anchor URL bypasses (<a
href="https://redirect.github.com/svg/svgo/issues/2268">#2268</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/4e9b9aed2a4607cf28025871151421d5bfe86484"><code>4e9b9ae</code></a>
chore: cache regression screenshots (<a
href="https://redirect.github.com/svg/svgo/issues/2267">#2267</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/d55270ce17b99ebfe16e4fad028bd162187205a1"><code>d55270c</code></a>
chore(regression): migrate comparison workers to Tinypool (<a
href="https://redirect.github.com/svg/svgo/issues/2266">#2266</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/fd51e474a300417d9361d9302d596b1763146327"><code>fd51e47</code></a>
fix(removeScripts): sanitize foreignObject content (<a
href="https://redirect.github.com/svg/svgo/issues/2264">#2264</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/dcaf957c6eb34832844de11ef2792e3e0e8db5dd"><code>dcaf957</code></a>
chore: optimize fixtures in a bounded worker pool (<a
href="https://redirect.github.com/svg/svgo/issues/2265">#2265</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/a3542937d9c85debab04b1ff75207768caf8a058"><code>a354293</code></a>
fix(removeScripts): filter executable data URLs (<a
href="https://redirect.github.com/svg/svgo/issues/2263">#2263</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/4e0d2ac5e7abd5f12d650d3e4b4d2500d4944cc5"><code>4e0d2ac</code></a>
ci(typecheck): return typechecking on CI</li>
<li><a
href="https://github.com/svg/svgo/commit/0b97fedd00a3001f1da616f61578c2c12e6cde1f"><code>0b97fed</code></a>
test(typescript): drop tsd for vitest type testing API</li>
<li><a
href="https://github.com/svg/svgo/commit/f6e8ae1afb012c2b47675622728d76b9bfd734f5"><code>f6e8ae1</code></a>
chore(pnpm): drop package.json#pnpm.onlyBuiltDependencies</li>
<li>Additional commits viewable in <a
href="https://github.com/svg/svgo/compare/v4.0.2...v4.1.0">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for svgo since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=svgo&package-manager=npm_and_yarn&previous-version=4.0.2&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/max-sixty/worktrunk/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-08 23:37:50 -07:00
dependabot[bot] 6ebe109b58 chore: bump js-yaml from 4.3.1 to 4.3.2 in /docs (#4046)
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.1 to 4.3.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/nodeca/js-yaml/blob/4.3.2/CHANGELOG.md">js-yaml's
changelog</a>.</em></p>
<blockquote>
<h2>4.3.2 - 2026-08-26</h2>
<h3>Changed</h3>
<ul>
<li>[backport] Hard-limit merge sequence size to 100.</li>
</ul>
<h3>Security</h3>
<ul>
<li>[backport] Count empty mappings in merge sequences toward
<code>maxTotalMergeKeys</code>
to limit CPU usage, <a
href="https://redirect.github.com/nodeca/js-yaml/issues/797">#797</a>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/nodeca/js-yaml/commit/79ca68d90f333fbe6d9e42827527e62636200191"><code>79ca68d</code></a>
4.3.2 released</li>
<li><a
href="https://github.com/nodeca/js-yaml/commit/d90b6612a5a84385bdcb556c44578eac76dc0f6b"><code>d90b661</code></a>
Backport merge limits from v5.4.1</li>
<li>See full diff in <a
href="https://github.com/nodeca/js-yaml/compare/4.3.1...4.3.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=js-yaml&package-manager=npm_and_yarn&previous-version=4.3.1&new-version=4.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/max-sixty/worktrunk/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-08 23:37:47 -07:00
dependabot[bot] 8d702118fd chore: bump taiki-e/install-action from 2.87.6 to 2.87.7 (#4055)
Bumps
[taiki-e/install-action](https://github.com/taiki-e/install-action) from
2.87.6 to 2.87.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/taiki-e/install-action/releases">taiki-e/install-action's
releases</a>.</em></p>
<blockquote>
<h2>2.87.7</h2>
<ul>
<li>
<p>Update <code>wasm-bindgen@latest</code> to 0.2.128.</p>
</li>
<li>
<p>Update <code>uv@latest</code> to 0.12.10.</p>
</li>
<li>
<p>Update <code>tombi@latest</code> to 1.5.2.</p>
</li>
<li>
<p>Update <code>rclone@latest</code> to 1.75.1.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md">taiki-e/install-action's
changelog</a>.</em></p>
<blockquote>
<h2>[2.87.7] - 2026-09-06</h2>
<ul>
<li>
<p>Update <code>wasm-bindgen@latest</code> to 0.2.128.</p>
</li>
<li>
<p>Update <code>uv@latest</code> to 0.12.10.</p>
</li>
<li>
<p>Update <code>tombi@latest</code> to 1.5.2.</p>
</li>
<li>
<p>Update <code>rclone@latest</code> to 1.75.1.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/taiki-e/install-action/commit/84f5ac3124727fb3d284d4d22ee9ab3654fd09a6"><code>84f5ac3</code></a>
Release 2.87.7</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/9387b0a701bf52ec87d0fab2bb9be442eb2d5d5a"><code>9387b0a</code></a>
Update <code>wasm-bindgen@latest</code> to 0.2.128</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/e78e42317f870ee65eecf610b1806e47a247d483"><code>e78e423</code></a>
Update <code>uv@latest</code> to 0.12.10</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/2a651e44c99da6e412156883bf77f6875ef10954"><code>2a651e4</code></a>
Update <code>tombi@latest</code> to 1.5.2</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/0b467d84e67f7d92f5ca881452597f458b89cea7"><code>0b467d8</code></a>
Update shfmt manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/7d5acd9c247d9a60de005f09476e45a48afba928"><code>7d5acd9</code></a>
Update release-plz manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/2405a4d813a372dde4907d5460f5a8d9dda80a39"><code>2405a4d</code></a>
Update <code>rclone@latest</code> to 1.75.1</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/f4416e2ad3467ae3dbf7b6480da275ce049b866c"><code>f4416e2</code></a>
Update protoc-gen-connect-openapi manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/b323c5fe780719037044305b5e5dd86de0d6953d"><code>b323c5f</code></a>
Update dprint manifest</li>
<li><a
href="https://github.com/taiki-e/install-action/commit/0f9e7db50df379bbdd9d03ad3d2d1fa0c9d677a6"><code>0f9e7db</code></a>
Update cargo-llvm-cov manifest</li>
<li>Additional commits viewable in <a
href="https://github.com/taiki-e/install-action/compare/v2.87.6...v2.87.7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=taiki-e/install-action&package-manager=github_actions&previous-version=2.87.6&new-version=2.87.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-08 23:37:44 -07:00
Maximilian Roos ebf8624dda Trade changelog-verification mechanics for the stakes behind them (#4056)
#4051 fixed the changelog-verification section by adding procedure. A
procedure gets run literally and thinly, so this trades some of it back
for why the pass matters, stated where each reader can see it.

**The subagent never reads SKILL.md.** Stakes stated there reach the
agent that spawns the verifier and nothing else, so the prompt template
gets its own opener: the entries publish with the tag, and by the time
anyone corrects a wrong line readers have acted on it — and reading an
entry and finding it plausible is not a check, because it was written
from the same commits the verifier is about to read.

**SKILL.md's line now says what a late correction costs.** It replaces
"This is non-negotiable — changelog mistakes are a recurring problem".
The workflow builds the release body with `--notes-file` at tag time
(`.github/workflows/release.yaml:381`), so a later `CHANGELOG.md` edit
isn't picked up: correcting a published entry takes a follow-up PR *and*
a hand-edit of the release page.

**Cut in exchange:** a sentence from the clean-run gate. Net +5 lines.

An earlier revision of this branch also cut step 2's guidance for claims
whose source is outside the commit. The review caught that, and it's
back — reworded, because the sentence I'd removed pointed at "the
rendered output and the docs" and the docs would not have settled the
OpenCode version floor that shipped wrong in v0.77.0. It now names the
upstream project's own releases. `evals/README.md` states that none of
its cases has a truthmaker outside the commit, so the suite could not
have scored that cut in either direction.

<details>
<summary>Eval runs</summary>

Scored against `.claude/skills/release/evals/` — four entries from the
v0.77.0 section, three of them wrong — run in a `v0.77.0` checkout with
the `Skill` tool withheld, per that README.

| | before-state | hooks `\|\| true` | five agents vs three rows |
guardrail |
|---|---|---|---|---|
| #4051's wording | 2/2 | 2/2 | 2/2 | held |
| first draft here | 1/2 | 2/2 | 2/2 | held |
| this branch | 2/3 | 3/3 | 3/3 | held |

The first draft had also dropped four words from step 2, "and confirming
the old behavior there". Its failing run read the *new* file, found
`json_output.rs` dropping `WorktreeState::Detached`, concluded "schema 1
only", and wrote a suggested fix that still claimed `state` no longer
reports `detached` — reproducing the original error while flagging the
entry. That clause is restored, and the one miss in the three runs after
it failed the same way.

So the before-state case is 2/2 for #4051's wording and 2/3 for this
one, which this design cannot separate: seven runs is far too few, and
the case was already the weakest of the three when #4051 shipped it (0/2
before that PR's own fix, 1/2 after). What the eval supports is that
relaxing the mechanics did not break the two solid cases, and that the
four-word clause is load-bearing enough to keep. The argument for the
stakes paragraphs is structural, not measured.

The guardrail entry was never called inaccurate in any of the seven
runs. The runs predate the stakes correction below, which changes no
instruction the cases exercise.

</details>

<details>
<summary>The stakes claim this PR opened with was wrong</summary>

The first version of this change claimed a post-tag correction reaches
`CHANGELOG.md` and never the published release body, citing v0.77.0 as
evidence. The review disputed it and was right: the published v0.77.0
body carries all 29 corrected entries, hand-edited after #4050. Diffed
both ways, zero differences.

I had grepped the published body for "Claude Code, Codex, OpenCode",
matched the Pi entry's legitimate "markers … like Claude Code, Codex,
OpenCode, and Gemini", and read it as the FAQ entry's uncorrected error
— a plausible-looking string taken for the source, which is the failure
this PR is about.

Fixed in 4800a7547; only the mechanism that actually holds is claimed
now.

</details>

> _This was written by Claude Code on behalf of max-sixty_

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 21:38:59 -07:00
Maximilian Roos 6ab31967ff Ask the harness what it holds, everywhere wt asks at all (#4054)
`wt config show` read Claude Code's `installed_plugins.json` and Gemini
CLI's `~/.gemini/extensions/` directory to report the plugin and
extension status. Both reads have the failure mode #4048 removed from
the marketplace reader sitting beside them: a store the tool relocated
is the same missing path as one it never wrote, so an installed plugin
reads as absent and the section prints `Plugin not installed` over a
plugin that is installed and enabled.

Both answers now come from the tool — `claude plugin list --json` and
`gemini extensions list -o json` — through one `harness_listing` helper
that the two marketplace readers share.

That leaves reading another tool's file with a single case, and a rule
rather than an exception behind it: wt reads `~/.claude/settings.json`
because wt writes it (`install-statusline` merges the `statusLine` key
in) and Claude Code has no command that reports the setting back.
OpenCode's and Pi's plugin files are wt's own writes too. Everything
else it asks.

## The uninstall simplification

`claude plugin uninstall` and `claude plugin marketplace remove` both
exit non-zero once their target is gone, so `wt config plugins claude
uninstall` now runs both through `run_plugin_removal`, each tolerating
only the absence Claude Code itself reports. That deletes the coupled
early return whose condition had to name both halves (`!plugin_installed
&& is_marketplace_configured() == Some(false)`), the conditional command
preview built to match it, and two tests that had become the same run.
The Claude Code and Codex uninstalls are now the same shape.

Behavior change: a repeat `claude uninstall` no longer prints `Plugin
not installed` and skips. It runs both removals and reports `Plugin &
marketplace removed`, which is what `codex uninstall` has always done.

## What was measured

Against `claude` 2.1.266 and `codex` 0.153.4, in throwaway
`CLAUDE_CONFIG_DIR` / `CODEX_HOME` directories:

| command | already in the target state |
|---|---|
| `claude plugin install` | exit 0, "is already installed" |
| `claude plugin marketplace add` | exit 0, "already on disk" |
| `claude plugin uninstall` | **exit 1**, "not found in installed
plugins" |
| `claude plugin marketplace remove` | **exit 1**, "Marketplace
'worktrunk' not found" |
| `codex plugin remove` | exit 0 |

So the install's short-circuit is a convenience over idempotent commands
— an answer wt cannot read costs a redundant run rather than a wrong one
— while the uninstall's tolerance is load-bearing. `codex plugin remove`
keeps `run_plugin_cli`, since it has nothing to tolerate.

End to end, with a shim forwarding to the real `claude` except forcing
the removals to exit 1: an uninstall over an installed plugin exits 1
carrying claude's own error, and a repeat uninstall over nothing exits
0. `wt config show` reports `Plugin installed` / `Plugin not installed`
correctly across an install and an uninstall of the real plugin.

## Cost

`wt config show` gains one spawn per section it renders: ~140 ms for
`claude`, ~630 ms for `gemini`, taking a run with both CLIs installed
from ~0.6 s to ~1.4 s. Neither query reaches the network. It is a
hand-run diagnostic rather than a hot path, so the two calls stay
sequential; running them concurrently would need the section renders
plumbed into threads.

## Tests

`is_plugin_installed` mutated to a confident `Some(false)` fails four
tests, including `test_plugins_claude_uninstall_command_fails`, which is
the one that would otherwise swallow a genuine failure.

The harness needed one change beyond the fixtures.
`configure_mock_commands` prepends mock-bin to the *caller's* `PATH`, so
a real `claude` or `gemini` on the developer's machine can answer in a
mock's place — which is why `setup_mock_claude_installed` and
`setup_mock_gemini_installed` now write a mock rather than only setting
the detection override.

## Review follow-up

`ConfigPluginsClaudeCommand::Uninstall`'s `after_long_help` still
described the early return this PR deletes ("skips gracefully only when
both are already gone"). It now names the current contract, and the
recovery note it carried is still true and stays:

> Requires `claude` CLI. Both removals run every time, tolerating only
the "already gone" error Claude Code itself reports. Running it again is
safe, and finishes an uninstall that removed the plugin and then failed
on the marketplace.

The Codex counterpart never described a skip, so it is unchanged.
`claude install`'s "Skips gracefully if already installed" still holds.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_015DzKvVGJbopPJan9YYpz4T

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 21:10:38 -07:00
Maximilian Roos 4c5a3f8293 Make merge_args_into_command's precondition its own extraction (#4047)
`merge_args_into_command` declines to merge `args` into `command` unless
every element is a string, and an inline comment justified that by
saying the alternative would drop user data "while `args` was removed".
Since #3994, `drop_unsupported_keys` removes every key the destination
struct has no field for, and `[commit.generation]` has no `args` field —
so an unmerged `args` is removed a few rules later regardless, and the
comment described a preservation the code no longer performs.

Declining still changes the outcome, just not the one the comment named.
With the precondition, `[commit-generation] command = "claude", args =
[1, "--ok"]` migrates to `command = "claude"`, and the removal is
reported both as `▲ User config: [commit-generation] args is no longer
supported and will be removed` and as `-args = [1, "--ok"]` in the `wt
config update` diff preview. Without it (checked by building the
variant), it migrates to `command = "claude --ok"`: the `1` disappears,
`command` gains a value the user never wrote, and nothing says so. So
the precondition stays and the docstring now states the live reason.

The body collects the strings with a `let`-else, which makes the
precondition the extraction itself. That removes the separate invariant
a comment had to carry — and the four `unwrap()`s it guaranteed.

Behavior is unchanged; existing tests pin every branch. A new test
covers `args = []`, which had none.

> _This was written by Claude Code on behalf of max-sixty_

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 20:28:48 -07:00
Maximilian Roos 2991dadd49 Confirm the write when wt config update --output names a file (#4053)
`wt config update --output <path>` writes the migration artifact to a
file and then says nothing — no warnings, no diff, no path, no
confirmation. The in-place form prints the deprecation warnings, a diff
preview, and `✓ Updated user config`, so the export path was the one
form of the command whose entire effect was invisible.

It now prints `✓ Wrote user config migration @ ~/migrated.toml` after
the write. `--output=-` stays silent: the artifact is already on the
terminal, and a confirmation on stderr would be noise next to it.

Naming the config in that line needs the single candidate bound, which
the old shape couldn't do — so the two destinations are now separate
paths rather than one path testing `-` at each of four steps. A file
takes exactly one migration, which a `let`-else states directly, and the
approvals-overwrite check drops its `filter().find()` over a slice that
could only ever hold one element. Every destination × emptiness
combination is unchanged apart from the new line, checked against the
binary.

`test_config_update_output_destinations_emit_same_config` had pinned the
old silence with `assert!(file_output.stderr.is_empty())`; it now
asserts the confirmation names the destination, and still checks that
both destinations emit identical bytes.

> _This was written by Claude Code on behalf of max-sixty_

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 19:55:04 -07:00
Maximilian Roos 4d88a39a16 Verify changelog claims against their own sources, and gate on a clean run (#4051)
The v0.77.0 changelog verification pass reported 16 accurate, 6 needing
revision, 0 incorrect. Eleven factual errors reached users anyway and
were corrected in #4050. This changes the verification section so the
pass covers the text that ships.

Two mechanisms produced the eleven, both visible in the pass's own
report.

**Five of the errors were sentences the verifier itself wrote.** The
template asks it to "quote a shorter rewrite", and the section's gate
read "do not finalize until the subagent confirms every entry" — a gate
you pass once. So the rewrites were applied and shipped with nothing
having read them. The gate is now a clean run over `CHANGELOG.md` as it
stands, and the text says why: a rewrite the verifier suggests is a new
draft with no more evidence behind it than one you wrote yourself.

**Four were non-headline clauses inside entries stamped accurate.** The
FAQ entry is the clearest: the verifier's evidence line says "three
paths" and its verdict says accurate, under an entry claiming five
agents. The template now verifies claim by claim rather than entry by
entry, and its report format asks for the source read per claim, so a
contradiction like that one lands on the page. The others were claims
the diff cannot settle — a prior behavior, an untouched file, rendered
output, a documented version floor — against a template whose one strong
instruction ("read the actual diff") installed the diff as the sole
source.

**The template also said "[paste drafted entries]" while the gate below
it said to re-run over `CHANGELOG.md` as it stands** — the same drift
channel one layer down, and how the failing pass came to verify a draft
the working tree had already moved past. It now names the extraction
one-liner the section already carries, so the rule is a mechanism rather
than an instruction, and the gate drops the clause the template
enforces. Found in review.

The six-step list that duplicated the prompt template below it is gone,
so the section's line count is flat.

<details>
<summary>Measurement: A/B over the shipped 29-entry section, two runs
per arm</summary>

Each arm ran the verification template as a subagent prompt over the
whole v0.77.0 section, with the earlier per-group notes offered as a map
— the load the failing pass had. Handed only the four scenario entries,
every wording found everything, so that design measured nothing;
attention spread across 29 entries is the variable.

| scenario | old | first draft | shipped |
|---|---|---|---|
| before-state claim, diff looks confirming | 0/2 | 0/2 | **1/2** |
| falsifying fact in an added comment | 1/2 | 2/2 | 1/2 |
| non-headline clause, settled in the diff | 0/2 | **1/2** | **2/2** |
| accurate entry stays clean (guardrail) | 2/2 | 2/2 | 1/2, one soft
scope flag |

The first draft of step 2 failed the before-state case in both runs, so
it was sharpened and retested rather than shipped on the strength of
reading well. The cases are kept in `evals/README.md`.

No case has its truthmaker wholly outside the commit, and that is hard
to arrange here: this repo's commits routinely restate the surrounding
facts in added comments and doc lines, so the falsifying text usually
arrives in the diff. The rows score how much of the diff the verifier
reads, not whether it goes looking beyond one. The second row was
labelled "truthmaker outside the diff" until review pointed out that
`29a611b7c` states the fact in a comment it adds beside the fix.

The arms were run with the section pasted into the prompt, so the
measurement covers the verification procedure rather than how the
entries arrive. Now that the template resolves its own input,
`evals/README.md` runs the arm in a checkout at `v0.77.0`, where the top
section is that same 29 entries — so the template runs unedited. Review
caught that the first version of this change left the harness scoring
`## Unreleased` and reporting a clean pass.

The clean-run gate is not in that table. It changes the loop rather than
the subagent prompt, so two arms of the prompt cannot separate it; it is
argued structurally.

</details>

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 19:23:36 -07:00
Maximilian Roos 89373ddea5 Correct overstated v0.77.0 changelog entries, and a docstring they exposed (#4050)
An audit of the published v0.77.0 notes against the actual diffs found
eleven claims that overstated a bug's severity or did not match the
code. The goal was accuracy in both directions — a bug described as
worse than it was misleads as much as one described as milder.

**The fork-PR entry (#3984) was the worst offender.** It said a failed
switch cost you the branch "and any commits only it held", which implies
unrecoverable loss. Tested in scratch repos, recoverability depends on
the case:

- git refuses to delete a branch checked out in any worktree, so the
deletion only lands on a branch not currently checked out anywhere
- a branch committed on and then switched away from stays in that
worktree's HEAD reflog, and `git reflog` recovers it
- a branch whose creating worktree is gone is in no reflog, and only
`git fsck --unreachable` finds it, until gc prunes

Rather than pick one, the entry now claims only what holds in every case
— the ref was deleted — and names the race required to reach the
deletion at all. At resolve time the chosen branch name is always free
(`resolve_fork_ref` reuses a tracking branch, or falls to a prefixed
name), so something has to claim it in the window after the forge
answers.

**The OpenCode version floor was wrong in a way users would act on.**
The entry said "below 1.14.19 no longer loads it". 1.14.19 is where the
object export shape first loads, but 1.16 is the documented floor,
because that is where OpenCode began filtering events per plugin
instance — on 1.14.19–1.15.x the marker follows the wrong worktree.
Someone on 1.15 would have read the old number and concluded they were
fine.

**The rest**, each verified against the diff:

- `state` never carried `detached`; a detached worktree previously
reported `branch_worktree_mismatch`
- plain `wt config show` never panicked — only `--format=json` and
`--full`, plus the four `wt step` commands
- `wt step squash` has no `--branch` flag
- the `APPROVALS` section counts commands and links `wt config approvals
list`; it never names them
- the FAQ's new table lists three files, not five harnesses; the Claude
and Codex plugin installs write nothing themselves
- #4019's break differs per harness: Codex uninstall previously left the
plugin, Claude uninstall now also removes the marketplace
- the marker fix's hooks end in `|| true`, so the session kept going;
`wt` exited 1 and printed a git error each turn
- #4043's entry linked only the issue, unlike every other entry
- one entry attributed the empty-section cleanup to the wrong code path
(it belongs to `remove_section_key_in`)
- the `wt step copy-ignored` entry claimed a `--dry-run` plan "no longer
reports `files`/`bytes`", wrong in both directions: an ordinary dry-run
plan never reported them, and the `source_path == dest_path` early
return still does. Clause dropped (caught by review — the first version
of this description claimed a correction that had not landed)

## One code comment, no behavior change

Chasing the `copy-ignored` claim turned up a docstring that misdescribed
its own call sites. `insert_empty_counts` said "A `--dry-run` payload
takes none of them" and named "the two early returns below"; there are
three call sites, and the claim holds for two.

`same_worktree` returns before any dry-run branching and emits no
`dry_run` key, so it is not a plan — it is a no-op exit in either mode,
which is what the function's first line already describes. Taking the
zeroed counts unconditionally there is correct. The docstring now scopes
its claim to `outcome: "planned"`, counts the call sites right, and says
why `same_worktree` differs.

Worth noting the review read this asymmetry as a defect leaking counts
into dry-run output. It isn't one: `same_worktree` was never a dry-run
payload.

The published GitHub release notes for v0.77.0 have been updated to
match (they are generated from the tree at the tag, so they do not pick
this up automatically).

The v0.76.0 notes turned out to need nothing: the misfiled `--output`
entry was added to `CHANGELOG.md` after v0.76.0 was tagged, so it never
reached that release's published notes. Only the repo file was wrong,
and moving the entry into 0.77.0 fixed it.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_0134XuJoGCzwoZ21XXbWujdY

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 18:34:33 -07:00
Maximilian Roos 28ebf24505 Drop post-commit when the merge removed the worktree it runs in (#4049)
## Problem

`wt merge` prints `◎ Running post-commit: …` and then spawns that
pipeline into a path the removal has already emptied. `post-commit` is
the only hook in the merge's background batch anchored on the feature
worktree, and `HookAnnouncer` flushes after `finish_after_merge` has
removed that worktree.

`run_pipeline` calls `Repository::at` on what's left, and git discovery
walks up from it:

- **Worktree outside the repository** (the default `../{{ repo }}.{{
branch }}`): nothing above it is a repository, so the runner logs
`failed to open repository for pipeline` to
`.git/wt/logs/<branch>/<source>/post-commit/runner.log`, which nothing
reads back. The hook doesn't run.
- **Worktree nested inside the repository** (`{{ repo_path
}}/.worktrees/{{ branch | sanitize }}`, one of the config page's own
examples): discovery resolves to the **primary** worktree, so the hook's
commands — arbitrary project code from `.config/wt.toml` — run against a
checkout the user never chose.

[#4026](https://github.com/max-sixty/worktrunk/pull/4026) documented
both outcomes rather than fixing them.

## Solution

The removal is the only thing that knows the anchor is gone, so it says
so: `spawn_hooks_after_remove` calls
`HookAnnouncer::mark_worktree_removed(ctx.worktree_path)`, and the flush
drops any pending pipeline anchored on a marked path. The survivors get
the usual `Running …` line; each dropped pipeline gets its own warning.

```
▲ Skipped post-commit: mark (user) — worktree removed @ ~/code/myproject/.worktrees/feature
↳ To run commands in a worktree before it is removed, use pre-remove
◎ Running post-remove: cleanup (user); post-switch: notify (user); post-merge: sync (user) @ ~/code/myproject
```

Reading the fact from the removal rather than probing the filesystem is
what makes the skip unconditional. The two removal paths leave the
anchor in different states: the fast path renames the worktree into
`.git/wt/trash/` before the flush, but where that rename fails —
cross-filesystem, permissions, Windows file locks —
`BackgroundFallbackMode::Detached` spawns `git worktree remove` and the
anchor is still on disk, intact, when the flush runs. A "does this path
still hold git data" probe answers `true` there and spawns the hook into
a worktree being deleted underneath it. The mark doesn't depend on which
path ran.

Deciding at the flush keeps every case where the removal doesn't happen:
`--no-remove`, merging on the target branch, merging from the primary
worktree, and a removal blocked by a dirty worktree all leave the anchor
in place, and post-commit runs there as before — as it does on `wt step
commit` and `wt step squash`. Only `wt merge` can reach the drop: every
other background hook anchors on a worktree its command keeps
(`post-merge`, `post-switch` and `post-remove` all render against the
destination).

There is no earlier moment to spawn it. Between the commit and the
removal the worktree is rebased and runs `pre-merge`, so a background
pipeline started there would race both.

## Testing

`test_merge_post_commit_runs_only_when_its_worktree_survives` in
`tests/integration_tests/user_hooks.rs` is parameterized over removal.
The worktree is nested inside the repository so that a regression
*executes* rather than merely fails: the hook writes `git rev-parse
--show-toplevel` to a marker in the primary worktree.

- `removed` — asserts the marker never appears, and reports the resolved
toplevel if it does. Dropping the partition writes the primary
worktree's path there.
- `kept` (`--no-remove`) — the control: same hook, same marker path,
worktree survives, and the marker names the feature worktree.

The mark is unconditional in `spawn_hooks_after_remove`, which every
removal path reaches after its removal, so there is no
fast-path/fallback branch left for a test to distinguish — the first
revision of this PR put a `holds_git_data` probe there instead, and
`test (windows)` caught the fallback taking the other answer.

The two merge announce snapshots now show the `Skipped` lines and a
`Running` line without `post-commit`; both tests are renamed to the
three hook types they still combine. `cargo run -- hook pre-merge --yes`
passes.

<details>
<summary>Manual repro</summary>

A scratch repo whose `post-commit` hook is `git rev-parse
--show-toplevel > {{ repo_path }}/toplevel.txt`, a feature worktree with
one commit and one uncommitted file, then `wt merge main --yes`.

Without the drop, the nested layout runs the hook and the marker names
the **primary** worktree, while the hook was anchored on
`.worktrees/feat`:

```
/private/var/folders/.../tmp.6MtN6Ufppv/repo
```

With it:

| Layout | Flags | Result |
|--------|-------|--------|
| nested (`{{ repo_path }}/.worktrees/{{ branch \| sanitize }}`) |
default (squash) | `▲ Skipped post-commit`, no marker |
| nested | `--no-squash` | `▲ Skipped post-commit`, no marker |
| external (`../{{ repo }}.{{ branch }}`) | default (squash) | `▲
Skipped post-commit`, no marker |
| external | `--no-remove` | `◎ Running post-commit`, marker names the
feature worktree |

</details>

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01QG3SjDDtiVkvmk3eZDc6vu

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 18:22:27 -07:00
Maximilian Roos f5cac67b77 fix(config): ask the harness whether the marketplace is gone (#4048)
`wt config plugins claude uninstall` and `codex uninstall` could print
`Plugin & marketplace removed` and exit 0 over a marketplace that was
still configured.

`plugin marketplace remove` exits non-zero when the marketplace is not
configured, which is the state uninstall is trying to reach, so a second
run would otherwise fail with nothing left to do
([#4033](https://github.com/max-sixty/worktrunk/pull/4033)). To tell
that from a removal that genuinely failed, `run_plugin_removal` asked
the harness's own config file. That reader could not fail loudly: a
record the harness renamed or moved is the same missing key or missing
file as a record it never wrote, so a confident absence was also the
answer for every genuine failure.

For Codex this isn't hypothetical. `codex plugin marketplace remove`
deletes the whole `marketplaces` key along with the last entry under it,
leaving an empty `config.toml`:

```console
$ codex plugin marketplace add max-sixty/worktrunk
$ cat $CODEX_HOME/config.toml
[marketplaces.worktrunk]
source_type = "git"
source = "https://github.com/max-sixty/worktrunk.git"
$ codex plugin marketplace remove worktrunk
$ cat $CODEX_HOME/config.toml
$
```

So an absent `marketplaces` key had to read as "already removed" for a
second uninstall to succeed, and that same reading swallowed every real
failure. Making the reader distinguish "no key at all" from "key
present, worktrunk absent" would just trade the false success back for
the failure it was introduced to fix.

Both harnesses publish their marketplaces as structured output, so this
asks them instead:

```console
$ claude plugin marketplace list --json
[{"name":"worktrunk","source":"github","repo":"max-sixty/worktrunk"}]
$ codex plugin marketplace list --json
{"marketplaces":[{"name":"worktrunk","root":"…"}]}
```

An empty list is the harness saying it holds nothing, which is a
different fact from a file that isn't where wt looked. A harness that
won't answer — the subcommand gone, output that isn't JSON, or entries
that aren't named marketplace objects — yields `None`, and the removal's
error stands. The shape check now fails closed rather than open. The
cost is that a repeat uninstall against a harness with no `--json` loses
its clean exit and shows the harness's own "not configured" message
instead.

Reading Codex's config also meant wt carried its own copy of the
`CODEX_HOME` resolution rule. The child reads the variable itself, so
`codex_config_dir` goes with the reader.

<details><summary>Verification and tests</summary>

Verified end-to-end against the real `claude` (2.1.265) and `codex`
(0.153.4), with a shim that fails only `plugin marketplace remove` and
forwards everything else. With the marketplace really configured both
uninstalls surface the error and exit 1; with nothing configured both
exit 0.

The mock-driven tests move from config-file fixtures to the mock's
`plugin marketplace list --json` stdout, which is now the whole variable
between the cases. Per harness: an empty list and a list naming only
another marketplace both tolerate the failed removal; a list naming
worktrunk surfaces it; and three unusable answers — the subcommand
rejecting `--json`, stdout that isn't JSON, and a list reshaped so it
parses and means something else — each leave the error standing. The
three unusable cases assert the exit status and stderr directly rather
than snapshotting, since they share one outcome that the single-case
tests either side already pin.

Both guards were checked by mutation: making `plugin_marketplace_list`
return an empty list on a non-zero exit fails `case_1_unsupported`, and
dropping the entry-shape `?` in `marketplace_listed` fails
`case_3_reshaped`.

Local gate: `cargo run -- hook pre-merge --yes` — 4832 tests passed,
`cargo fmt`, clippy, and `pre-commit run --all-files` clean.

</details>

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 17:18:03 -07:00
Maximilian Roos 0683ad85c7 Release v0.77.0 (#4044)
Version bump to 0.77.0 plus the changelog section for this release.

**Bump level**: minor. `cargo semver-checks` reports 8 breaking library
changes (removed `DeprecationInfo::has_deprecated_patterns`,
`Repository::recent_commit_subjects`, `Repository::diff_stats_summary`,
`config::detect_deprecations`; arity changes on
`compute_migrated_content` and `Progress::record`). Pre-1.0, so a
breaking change takes a minor bump. `wt list --format=json` defaulting
to schema 2 is a user-facing break on its own.

**Validation**

- `cargo run -- hook pre-merge --yes` — 4831 tests passed, 1 skipped;
clippy, fmt, doc-sync, snapshot and lockfile checks green
- Nightly dispatched on the cut-from tip
(https://github.com/max-sixty/worktrunk/actions/runs/34272636821):
full-tests on linux, macos, windows and git-2.43 all green, alongside
release-target ×3, nix-flake, minimal-versions, crate-build, unused-deps
and link-check

**Changelog**

29 entries. Each was verified against its commit's diff by a separate
pass, which caught two uncovered fixes (#4033/#4034 uninstall
idempotency), one entry in the wrong section (#4018 is a fix, not an
improvement), and three unmentioned machine-visible breaks (`wt list`
JSON `marker`/`state`, `copy-ignored --dry-run` dropping
`files`/`bytes`, the hidden-column footer wording).

One correction to the previous release's notes: the `wt config update
--output` entry was filed under `## 0.76.0` by #4021, which landed after
v0.76.0 was tagged. It moves to 0.77.0, where it actually ships.

**Data-loss surface review**

Four independent finders swept the cumulative diff. The destructive core
is untouched — no changes in `src/commands/process.rs`,
`src/git/remove.rs`, `src/utils.rs`, or `src/commands/remove.rs`. This
release removes a loss path: #3984 deletes the fork-PR `git branch -D`
rollback that force-deleted a pre-existing branch, and its reflog, when
the branch name was already taken.

Three follow-ups, none blocking: `run_plugin_removal` reporting success
over a failed marketplace removal; the documented-not-fixed
`post-commit` window in `wt merge`; and `merge_args_into_command`'s
`args` precondition, now dead code since `drop_unsupported_keys` removes
the key regardless.

> _This was written by Claude Code on behalf of max-sixty_

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_0134XuJoGCzwoZ21XXbWujdY

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
v0.77.0
2026-09-08 14:53:53 -07:00
Worktrunk Bot d41ba2b1e5 fix(switch): name the directory the --execute program runs in in its header (#4043)
## Problem

The `Executing (--execute) @ …` header rendered `hooks_display_path` —
the worktree the *background hooks* run in. The program runs wherever
the switch cd'd, which is that worktree only when the user was at the
source worktree's root. Two cases break the claim:

- `--no-cd` deliberately starts the program in the invoking directory,
so `output::execute` gets no `target_dir` at all. `wt switch --create
test --no-cd -x pwd` announced `Executing (--execute) @ ~/repo.test` and
then printed `~/repo`.
- A switch from a subdirectory keeps the user's position:
`handle_switch_output` passes `resolve_subdir_in_target(...)` to
`change_directory`, so the program starts in `<worktree>/<subdir>` while
the header named the worktree root — the same wrong-directory shape one
level out.

The header is the only signal a user gets about where the program runs,
so a wrong one sends them looking in the wrong place. In
[#4042](https://github.com/max-sixty/worktrunk/issues/4042) the reporter
concluded the `--execute` template variables were broken and enumerated
all of them, when the variables were correct and the directory was the
thing `--no-cd` had moved.

## Solution

`handle_switch_output` now returns both annotations as
`SwitchDisplayPaths` — `hooks`, the worktree root the hooks really do
run in, and `execute`, derived from the `cd_target` it hands
`change_directory`. The header therefore names the directory
`output::execute` will use, and cannot drift from it: there is one
value, computed where the `cd` is decided rather than reconstructed at
the call site.

The path is still annotated only when the user's shell won't be there.
Under `--no-cd` there is no `cd_target` and the header reads `Executing
(--execute):`; with shell integration active the shell follows the
program to the same directory, so nothing is annotated then either.

## Testing

Two integration tests in `tests/integration_tests/switch.rs`, both
failing on `main`:

- `test_switch_no_cd_execute_header_omits_worktree_path` — `wt switch
feature --no-cd --execute pwd` asserts the header names no path (fails
with `Executing (--execute) @ ~/repo.feature`).
- `test_switch_execute_header_names_preserved_subdirectory` — switches
from `apps/gateway/`, asserts `pwd` prints the target's `apps/gateway`
and the header names it (fails with `Executing (--execute) @
~/repo.feature`).

The existing `switch_no_cd_execute_does_not_emit_cd` snapshot pinned the
old header — its stdout was already `_REPO_` while its stderr claimed
`_REPO_.exec-test` — and is updated. The 336 tests matching `switch`,
`execute`, and `directives` pass, as do `cargo test --lib --bins`,
`cargo clippy --all-targets`, and `cargo fmt --check`.

Closes #4042 — automated triage

---------

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
2026-09-08 13:03:57 -07:00