Skip to content

Publish shell integration, add a footer, dedupe global options - #4000

Open
max-sixty wants to merge 19 commits into
mainfrom
land/docs-site
Open

Publish shell integration, add a footer, dedupe global options#4000
max-sixty wants to merge 19 commits into
mainfrom
land/docs-site

Conversation

@max-sixty

@max-sixty max-sixty commented Sep 3, 2026

Copy link
Copy Markdown
Owner

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.

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

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.ai/code/session_01XAUYWFN9d9oh6jyoQiouHb

max-sixty and others added 18 commits September 1, 2026 20:39
#36 — 26 flat H2 recipes in no order, all 26 in the sidebar (the ToC caps at
H2). Group them under five H2s — setup and layout, aliases and hooks,
per-worktree services, working with agents, status/commits/logs — and demote
each recipe to H3. Anchors are level-independent, so every existing
`/tips-patterns/#…` fragment still resolves.

#49 — `-x 'opencode run'` has been broken since 0.75.0 made `-x` a literal
program. `-x` names the program and arguments after `--` are passed to it:
`-x opencode -- run '<task>'`.

#50 — the unified-diff tab moved branch summaries from preview tab 5 to 6.
Drop the number and name the `summary` tab, linking the picker's tab list.

#52 — the Caddy recipe claimed `feature-auth` hashes to port 16460; that is
`fix-auth`'s port. `feature-auth` is 18283.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#37 — 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.
Promote it to /shell-integration/ (a category-2 page, so the skill copy is now
generated) and point the FAQ at it, keeping the plugin as a second option.
Correct troubleshooting.md's `wt list` timeout quote to the real text,
`Listing worktrees timed out after 120s (N results received); blocked tasks:`.

#38 — 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
that resolves nowhere under the mirror. Nothing generated it, so deleting the
symlink is the whole fix; the mirror drops its copy on the next sync, and the
lychee exclusion loses the rationale it was written for.

#39, #48 — one home per topic. Agent handoffs stay in tips-patterns and the
skill points there; activity markers stay in claude-code.md and tips-patterns
points there; alias-template deferral stays in extending.md, with the FAQ and
troubleshooting reduced to links; shell-install file paths move to the new
page. SKILL.md also drops the hook-type list sitting three lines below its
pointer to reference/hook.md, and stops using this repo's own name in the
sub-agent example.

#45, #94 — the sidebar listed `remove` before `merge` and put Agent
integration ahead of pages numbered lower, while each page's `sidebar.order`
said otherwise. `sidebar.order` is load-bearing (it orders llms.txt), so
reconcile the frontmatter to the authored sidebar rather than dropping it.
`code-signing.md`'s `hidden: true` was dead config under an explicit sidebar
array; the page keeps its order for llms.txt. Add an Install entry linking
/#install.

#47 — the FAQ linked /worktrunk/#install, the noindex compatibility route.
Its "Running tests" and "How can I contribute?" sections duplicated the
README's Contributing block down to the share URLs; the test commands move to
the README and the FAQ links to it.

#51, #61 — `_` is same-commit *and clean*; the same-commit-with-changes glyph
is `–`, which is not safe to delete. `/wt-switch-create` is a skill that ships
to Codex and Gemini too, inert there. The `.git/wt/cache/` table was missing
`picker-preview`, and `wt config state clear` prompts unless `--yes`. 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". Skill-only headings move to sentence case.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dings

#95 — clap repeats the same ~20-line `Global Options:` block in every command
reference it renders, so a page built from subdocs stacked 11 copies on
/config/ and 13 on /step/. That padded the pages and gave the site search that
many near-identical hits ("squash" returned both /step/#command-reference and
#command-reference-2). `handle_help_page` now assembles the page as one string
and keeps only the first global-options section; later references end at their
own options. Terminal `--help` renders through clap directly and is unchanged.

The same page carried colliding anchors: two "Hooks" (#hooks, #hooks-1), two
"Aliases", and seven "Examples" (#examples … #examples-6). Qualify them at
their source in src/cli/mod.rs and src/cli/config.rs — User/Project hooks,
User/Project aliases, and Approval/Alias/State/Cache/Log/Variable examples —
and repoint the links that named the old anchors.

`SITE_LINK_PATTERN` gained an optional page segment so a homepage-anchor link
like `[installation](/#install)` expands to a full URL on the skill and README
surfaces instead of tripping the untransformed-link guardrail.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#96 — `wt list --full` renders 1157px inside the 800px content column on
/list/, so 40% of it sits behind a horizontal scrollbar while the pane beside
the column is empty. A terminal frame now takes the whole pane on viewports
that have slack there. `.content-panel` becomes the query container so the
room available is measured rather than recomputed from Starlight's main-pane
formula.

#99 — the 2.33 MB `wt-zellij-omnibus.gif` sits well below the fold on the
homepage and loaded eagerly; it is now `loading="lazy"`. The `/switch/` demo
opened on a bare prompt with nothing saying what it shows, so demo
placeholders take an optional `| caption` that becomes a `<figcaption>`, and
all four command demos get one. Caption styling, which was scoped to the
homepage, now covers every `figure.demo`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#97 — no page named the version, linked the changelog or releases, or said
what the license is, and /code-signing/ was reachable only from inside a
collapsed block on the homepage. Wrap Starlight's Footer rather than replacing
it, keeping the upstream merge surface to the one element added. The version
is read from Cargo.toml at build time, so a release doesn't leave a second
copy to update.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#100 — the `wt-command-reference` frames carried a copy button offering 3,877
characters of generated help text, which nobody pastes anywhere; those frames
now expose no copy control.

/switch/'s first Examples block copies six alternatives as one payload. A
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 now carries its own copy control alongside the block's. The block
control still copies the whole recipe; hovering a line hands the corner to
that line instead, so the two never overlap.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#37 — llms.txt links every page as `https://worktrunk.dev/<slug>.md`, served
from a hand-created symlink in `docs/public/` into the skill reference. A new
page reaches llms.txt from its frontmatter alone, so /shell-integration.md was
a 404 the listing still advertised. Add the symlink, and have the sync fail
when a listed page has none.

#95 — `wt config create --help` prints the generated config example, so it
carries the renamed User/Project headings too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#95 — the first pass assembled the whole page as one string and then swept
it for repeated `Global Options:` sections, ending each at the next closing
fence. The fence is a property of the surrounding page, not of the block
being cut, so the sweep only worked while the page was one buffer.

`take_global_options` cuts each reference as it is built instead, at the
heading itself: `help_reference_inner` already ends `after_long_help` at the
first non-indented line, so the section runs to the end of the block. One
`kept` flag threads through the page's subdoc expansion, and the page streams
out again rather than accumulating.

Also repoint two link-rewrite test cases at `/config/#project-hooks`; the
`#hooks` anchor they named was split into User/Project hooks.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#37 — the section now offers the shell-integration checklist first and the
Claude Code plugin second, so "If Claude can't fix it" named only the second.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#61 — four stale claims, all in help text.

`wt step prune` removes branches that have no worktree as well, so its
one-liner says so; the min-age guard now says what each kind of candidate is
aged by (a worktree by its creation time, a bare branch by its oldest reflog
entry).

`wt step eval -v` prints fifteen variables; the example showed two, under a
lead that called them "the available template variables". Show the first few
and elide the rest, and settle the names on myproject / feature-auth.

A filter applied to `{{ vars.<key> }}` acts on the placeholder the preview
substitutes, not a value, so `{{ vars.port | default('8080') }}` previews as
`{{ vars.port }}` with the filter gone. The hook page said only that the
reference renders as itself.

The `StepCommand` ordering comment called eval, for-each and prune
experimental; only promote, relocate and tether carry the badge.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#39 — the `codename` filter's entry on the hook page carried two
`worktree-path` recipes byte-identical to the config page's worktree-path
examples. The config page owns path templates, so the filter entry keeps the
explanation and points there.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#36 — tips-patterns' description advertised shell integration, which now has
its own page, and Zellij layouts, which the page never carried. Name the five
groups the recipes now sit under; the description is also the page's llms.txt
entry.

#37 — the repo's own guidance used `shell-integration.md` as its example of a
skill-only page, which it stopped being when it was promoted to the site.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#99 — the caption support added for `<!-- demo: -->` placeholders covered the
four command demos; the statusline and LLM-commit figures are written directly
in their pages and still opened unlabeled.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#38 — both copies of the Codex copier rationale used
`reference/README.md` as their example of a nested symlink, which is the file
that deletion removed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#45, #94 — `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 what the survey found: `remove` listed before
`merge`, Agent integration ahead of lower-numbered pages. Write it, so the
sidebar and the llms.txt ordering derived from the frontmatter can't drift
apart again.

A page may carry an order without a sidebar entry — `code-signing.md` does, so
llms.txt still places it — so only pages the sidebar names are checked.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… anchor

#47 — the hook shim's message sent users to
https://worktrunk.dev/worktrunk/#install, the noindex compatibility route the
FAQ stopped linking. The homepage carries the anchor at /#install, which is
also where the sidebar's Install entry points.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAUYWFN9d9oh6jyoQiouHb
`src/help.rs` had no tests. The two functions this branch adds or changes carry
four branches between them, and three were unexercised: a reference with no
`Global Options:` heading, and a demo placeholder with no caption (which is the
documented optional form, so it has to keep rendering a figure without an empty
`<figcaption>`).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAUYWFN9d9oh6jyoQiouHb

@worktrunk-bot worktrunk-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Checked the generator change by auditing what actually left the generated pages: across config.md, step.md, list.md, switch.md, merge.md and remove.md the only removed lines are Global Options blocks (12 on /step/, 10 on /config/, 1 on /list/) — nothing else is cut, and wt config show's Output: group survives, so the "section is last" assumption holds where it's exercised. Two things below.

/step/ still carries the anchor collisions /config/ just lost. The qualified headings landed in src/cli/config.rs only, so on the current head /config/ is down to the structural #command-reference repeats while /step/ is unchanged from the base: eight Examples (#examples#examples-7, at the page top plus rebase, push, eval, for-each, prune, relocate, tether), two Options (commit, squash), two Arguments (for-each, tether), and pairs for Staging and Dry run. That's the same near-identical-search-hit problem the description opens with, on the page it names as the worse of the two, and the description reads as though both were covered. The fix is the same shape as the config.rs one — qualify at the after_long_help source in src/cli/step.rs.

Not approving. src/cli/mod.rs and src/cli/step.rs hold the wt remove --force-delete and wt step prune definitions, which this repo's Data-Loss Surface: Hold for Human Review puts outside what I approve even when the diff is help text. For what it's worth the edits there run the safe direction and check out against the code: _ really is same-commit and clean (MainState::Empty vs SameCommit in src/commands/list/model/state.rs), prune really does age a bare branch by its oldest reflog entry (orphan_branch_age takes .lines().last()), and feature-auth really does hash to 18283, not fix-auth's 16460.

Comment thread skills/worktrunk/SKILL.md
```bash
zellij run -- wt switch --create <branch-name> -x <agent-cli> -- '<task description>'
```
When the user requests spawning a worktree with an agent in a background session ("spawn a worktree for...", "hand off to another agent"), use the tmux or Zellij command from [Agent handoffs](https://worktrunk.dev/tips-patterns/#agent-handoffs), substituting the CLI you are running as for `claude`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is the file's only pointer that leaves the skill: every other one is a bundled path (reference/config.md#user-hooks, reference/step.md#wt-step-for-each), and this content ships beside it at reference/tips-patterns.md#agent-handoffs — the section the inlined tmux/Zellij commands moved to. An agent reading the skill without network access loses the handoff commands entirely, which is the one place they were guaranteed to have them.

Suggested change
When the user requests spawning a worktree with an agent in a background session ("spawn a worktree for...", "hand off to another agent"), use the tmux or Zellij command from [Agent handoffs](https://worktrunk.dev/tips-patterns/#agent-handoffs), substituting the CLI you are running as for `claude`.
When the user requests spawning a worktree with an agent in a background session ("spawn a worktree for...", "hand off to another agent"), use the tmux or Zellij command from `reference/tips-patterns.md#agent-handoffs`, substituting the CLI you are running as for `claude`.

Seven conflicts, all from #3997 editing the same hook and step help text.

Took main's for six: the `vars`-preview paragraph (main's is the corrected one
— a filter that transforms its input still runs against the placeholder, which
this branch's wording denied), the `codename` recipe pointer, the
`StepCommand` ordering comment, the `wt step eval -v` lead and sample block
(main's names it abridged and uses the settled myproject / feature-auth names),
and the `--min-age` flag description, which is read standalone in `--help`
where "candidates" has no antecedent.

Kept this branch's min-age prose, which carries both facts main's does plus
where each kind of candidate gets its age from.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAUYWFN9d9oh6jyoQiouHb
@max-sixty

Copy link
Copy Markdown
Owner Author

Right on both counts.

The description did read as though /step/ was covered; it wasn't — the qualified headings landed in src/cli/config.rs only. Corrected it to say so, and to note why /step/ wants a pass of its own rather than a line in this one: qualifying those headings moves existing /step/#examples-N anchors, so the inbound links need auditing the way config.rs's did. What this branch does give that page is the 13 Global Options blocks it no longer repeats.

The data-loss hold is understood and correct — src/cli/mod.rs and src/cli/step.rs carry the wt remove --force-delete and wt step prune definitions, so this needs a human on it regardless of the diff being help text. Leaving it for the repo owner. Thanks for verifying the three factual claims (_ as same-commit-and-clean, orphan_branch_age's .lines().last(), and 18283) even while holding.

This was written by Claude Code on behalf of max-sixty

@worktrunk-bot

Copy link
Copy Markdown
Collaborator

One item from the review sits outside "both counts": the inline suggestion on skills/worktrunk/SKILL.md (thread) is still open at bf6475d1. Line 140 sends agent handoffs to https://worktrunk.dev/tips-patterns/#agent-handoffs — the file's only content pointer that leaves the skill, with every other one a bundled path — while skills/worktrunk/reference/tips-patterns.md ships in the same directory carrying that exact ### Agent handoffs section. Flagging only because it's the one point the reply doesn't touch; whether it belongs on this branch is your call.

@worktrunk-bot

Copy link
Copy Markdown
Collaborator

#4001 (mine, opened this morning) re-derived the /worktrunk/#install/#install fix this PR already makes — same four non-test edits, same widening of SITE_LINK_PATTERN. I've closed it as a duplicate; nothing here needs changing.

One piece of it may be worth carrying over, in a weaker form than my review of #4001 claimed. That review said this PR leaves the widened regex untested. It doesn't: reverting (?:([^)/#]+)/)? back to ([^)/]+)/ on this branch fails test_docs_are_in_sync, because the FAQ's ](/#install) then falls through to assert_no_untransformed_site_links. What's actually uncovered is narrower — the pin is coupled to that one FAQ line, so rewording it silently unpins the widening, and the bare ](/) form has no coverage at all (grep -rn '](/)' docs/src/content/docs/ src/cli/ returns nothing).

This test closes both gaps. It passes on this branch at bf6475d1 as written, dropped in after test_legacy_zola_link_fails_the_guardrail:

/// A link naming the site root carries no page segment. Both generated
/// surfaces have to rewrite it, or the only spelling the docs can use is
/// `/worktrunk/` — the route the home page itself marks `noindex` with a
/// canonical pointing back at `/`.
///
/// `](/page)` (a page segment without its trailing slash) stays unmatched, so
/// the guardrail keeps catching it instead of the widened pattern quietly
/// absorbing it.
#[test]
fn test_site_root_links_rewrite_to_the_canonical_url() {
    let rewrite = |content: &str| {
        SITE_LINK_PATTERN
            .replace_all(content, expand_site_link)
            .into_owned()
    };
    assert_eq!(
        rewrite("See [installation](/#install) and [hooks](/hook/#types)."),
        "See [installation](https://worktrunk.dev/#install) and \
         [hooks](https://worktrunk.dev/hook/#types)."
    );
    assert_eq!(
        rewrite("[Worktrunk](/) is a CLI."),
        "[Worktrunk](https://worktrunk.dev/) is a CLI."
    );
    // Both surfaces, since each applies the rewrite on its own path.
    assert!(
        transform_docs_to_github("[install](/#install)").contains("https://worktrunk.dev/#install")
    );
    assert!(
        finalize_skill_content("[install](/#install)").contains("https://worktrunk.dev/#install")
    );
    // Unchanged: a slash-less page segment is still not a site link.
    assert_eq!(rewrite("[hooks](/hook)"), "[hooks](/hook)");
}

Take it or leave it — the fix itself is complete here either way.

What I ran

In a worktree at bf6475d1, with only the test above added:

  • cargo test --test integration test_site_root_links_rewrite_to_the_canonical_url — passes.
  • Same test with SITE_LINK_PATTERN reverted to ([^)/]+)/ — fails on the first assertion ([installation](/#install) left unrewritten).
  • Whole suite with the regex reverted and the new test removed, to check what the existing tests already catch — test_docs_are_in_sync fails on the FAQ line, 18 others pass. That is the coupling described above.

max-sixty pushed a commit that referenced this pull request Sep 4, 2026
…example (#4006)

## Problem

The `worktree-path` examples in the user-config guide are introduced as
being **"for repo at `~/code/myproject`"**, and every example states the
path it produces. For all but one, that arithmetic checks out. The
bare-repository example doesn't:

```toml
worktree-path = "{{ repo_path }}/../{{ branch | sanitize }}"
```

Heading claimed `~/code/myproject/feature-auth`. With `repo_path` at
`~/code/myproject` as the section says, `{{ repo_path
}}/../feature-auth` resolves to `~/code/feature-auth` — one directory up
from the stated result.

## Fix

The template is right; the heading silently switched the repo's location
without saying so. `{{ repo_path }}` for a bare repo is the bare
directory itself (as the variable list a few lines above states), so the
claimed result holds only when that directory is a hidden child — the
`myproject/.git` layout that [tips-patterns.md
documents](https://github.com/max-sixty/worktrunk/blob/main/docs/src/content/docs/tips-patterns.md#bare-repository-layout),
and that `wt switch`'s bare-repo offer writes this exact template for.
So the heading now names it:

> Bare repository cloned to `~/code/myproject/.git`
(`~/code/myproject/feature-auth`):

Edited in `src/cli/mod.rs` (the primary source); the four generated
mirrors and two `--help` snapshots are regenerated output.

## Testing

No regression test — this is a documentation string with no behavior
attached. The generated mirrors are pinned by the existing sync tests,
which is what caught them here:

- `cargo test --test integration readme_sync` — 18 passed (regenerates
`dev/config.example.toml`, `docs/src/content/docs/config.md`, and both
`skills/.../reference/config.md` mirrors).
- `cargo insta test --accept --test integration -- test_help` — 47
passed (`help_config_create`, `help_config_long`).
- `cargo fmt --check` — clean.
- `cargo test --test integration` — 2048 passed, 1 failed.

<details><summary>The one integration failure is a sandbox artifact, not
a regression</summary>


`step_copy_ignored::test_copy_ignored_preserves_file_executable_permissions`
expects `0644` and gets `0664`. The tend sandbox runs with `umask 0002`
(group-writable) rather than the `0022` the test assumes.

Confirmed unrelated: it reproduces identically with this branch's
changes stashed, i.e. on the merge base. Both `ci` and `coverage` on
`main` are green at `2026-09-03T10:17:26Z`. This diff touches only doc
strings and snapshot files and cannot reach file-permission code.

</details>

<details><summary>Checked against the in-flight docs PRs</summary>

#4000, #3999, and #3998 each touch the same five files (`src/cli/mod.rs`
plus the four config mirrors), so I checked for the duplication that
sank #4001. None of them edits the `worktree-path` examples region, and
`git merge-tree` against each reports a clean merge with this branch.

</details>

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants