Skip to content

docs: link the canonical home-page install anchor, not the deindexed duplicate - #4001

Closed
worktrunk-bot wants to merge 1 commit into
mainfrom
nightly/clean-33724232227
Closed

docs: link the canonical home-page install anchor, not the deindexed duplicate#4001
worktrunk-bot wants to merge 1 commit into
mainfrom
nightly/clean-33724232227

Conversation

@worktrunk-bot

Copy link
Copy Markdown
Collaborator

The FAQ's Windows section and the Claude Code hook wrapper both point at https://worktrunk.dev/worktrunk/#install, a route the home page itself declares non-canonical: worktrunk.md carries rel=canonical to / plus robots: noindex, and astro.config.mjs excludes /worktrunk/ from the sitemap. Both links now name /#install, the canonical home-page anchor that docs/src/pages/index.astro renders. All three came in together with the Astro rebuild (#3866), so this is migration fallout rather than a deliberate target.

Making the primary say /#install required widening the mirror generator: SITE_LINK_PATTERN demanded a page segment (/([^)/]+)/), so a page-less site-root link matched nothing, survived the rewrite, and tripped assert_no_untransformed_site_links. The page segment is now optional, and the two identical rewrite closures collapse into one rewrite_site_links so the shape lives in one place. A slash-less ](/page) still matches nothing and still trips the guardrail.

Verified with cargo test --test integration readme_sync (19 passed) and pre-commit run over the changed files. test_site_root_links_rewrite_to_the_canonical_url is the regression test — reverting just the regex to its old shape fails it on the first assertion.

Surfaces touched

docs/src/content/docs/faq.md is the primary; skills/worktrunk/reference/faq.md, plugins/worktrunk/skills/worktrunk/reference/faq.md, and docs/public/faq.md (a symlink to the first mirror) were regenerated by test_docs_are_in_sync, which passes on the second run. plugins/worktrunk/hooks/wt.sh is hand-written and carries the URL in a runtime error message, so it was edited directly.

Found by the nightly rolling survey — an anchor-validation pass over docs/src/content/docs/ flagged this as the only broken-or-non-canonical internal link across the site.

@worktrunk-bot worktrunk-bot added the nightly-cleanup Issues found by nightly code quality sweep label Sep 3, 2026

@worktrunk-bot worktrunk-bot left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This duplicates #4000. That PR (yours, opened ~7 hours earlier) already makes the byte-identical edit to all four non-test files here — docs/src/content/docs/faq.md, both skills/.../reference/faq.md mirrors, and the error string in plugins/worktrunk/hooks/wt.sh — and widens SITE_LINK_PATTERN the same way, hoisting the two closures into a shared helper (expand_site_link there, rewrite_site_links here). #4000 also carries the piece this PR can't see the need for: docs/src/site-navigation.mjs gains { label: 'Install', link: '/#install' }, which is what makes the widened pattern load-bearing beyond the one FAQ link.

The nightly survey that opened this evidently didn't check open PRs before writing the fix. My recommendation is to close this one — but there is one thing worth salvaging first.

#4000 adds no test for the widened regex. The only new test in this PR, test_site_root_links_rewrite_to_the_canonical_url, is the regression pin for the change, and #4000's readme_sync.rs hunks add nothing equivalent. It transfers to #4000 unmodified: I traced all four assertions against #4000's (?:([^)/#]+)/)? and they hold, including the negative case [hooks](/hook) staying unmatched.

The one substantive difference between the two regexes is that character class — #4000 excludes # from the page segment, this PR doesn't. They diverge only on a malformed segment like ](/a#b/), which this PR would rewrite and #4000 would route to assert_no_untransformed_site_links. #4000's is the stricter and better one; nothing here depends on the looser class.

What I verified

Everything the description claims checks out:

  • docs/src/content/docs/worktrunk.md frontmatter carries rel=canonicalhttps://worktrunk.dev/ and robots: noindex; docs/astro.config.mjs filters ${site}/worktrunk/ out of the sitemap. So /worktrunk/#install really was the deindexed route.
  • ## Install exists in worktrunk.md (line 120), which docs/src/pages/index.astro renders at /, so /#install resolves.
  • git grep 'worktrunk\.dev/worktrunk/\|](/worktrunk/' returns nothing — the sweep is complete.
  • cargo test --test integration readme_sync — 19 passed, including the new test.

On the regex widening specifically: the new-match set is exactly ](/) and ](/#anchor), because skipping the optional group forces the tail to be ) or #…) immediately. It admits nothing else, and ](/page) still falls through to the guardrail. Worth noting it also closes a pre-existing hole in the other direction — UNTRANSFORMED_SITE_LINK_PATTERN's [^)]+ requires at least one character, so a bare ](/) was invisible to both the rewrite and the guardrail before this.

plugins/worktrunk/hooks/wt.sh is on the hold-for-human list in this repo's review reference, since it's the dispatcher the WorktreeRemove hook shells out to. I'm naming it for the record rather than requesting a second opinion on it: the edit is a URL inside a >&2 string in a Windows-Terminal branch that immediately exit 1s, it can't reach the removal dispatch, and #4000 makes the same edit. No approval either way — this is a self-authored PR.

@worktrunk-bot

Copy link
Copy Markdown
Collaborator Author

Closing as a duplicate of #4000, per my review above. #4000 (opened ~7 hours earlier) makes the byte-identical edits to all four non-test files here — docs/src/content/docs/faq.md, both skills/.../reference/faq.md mirrors, and the error string in plugins/worktrunk/hooks/wt.sh — and widens SITE_LINK_PATTERN the same way, with a stricter page-segment class ([^)/#]+ vs [^)/]+ here). Nothing in this branch is worth keeping over that one.

The nightly survey that opened this didn't check open PRs before writing the fix; that's the thing to correct, not the code.

I've carried the one salvageable piece — the regression test — over to #4000 as a comment, adapted to its expand_site_link helper and verified against its head. My review overstated the gap it fills: #4000's widening is already pinned indirectly by test_docs_are_in_sync, and the test's real value is decoupling that pin from the one FAQ line plus covering the bare ](/) form. Details in that comment.

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

nightly-cleanup Issues found by nightly code quality sweep

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant