Skip to content

refactor(wikilinks): always store [[Title]] links as sentinels#1133

Merged
perber merged 5 commits into
mainfrom
refactor/wikilink-always-sentinel
Jun 5, 2026
Merged

refactor(wikilinks): always store [[Title]] links as sentinels#1133
perber merged 5 commits into
mainfrom
refactor/wikilink-always-sentinel

Conversation

@perber

@perber perber commented Jun 5, 2026

Copy link
Copy Markdown
Owner

[[Title]] wiki-links are now stored as wikilink:Title sentinels regardless of whether the target page already exists. Previously a single unambiguous match was stored as a resolved route path, causing inconsistencies across rename, move, and delete flows.

Key changes:

  • helpers.go: single-match title lookups (pure and slash-fallback) now return wikilinkSentinel(target) instead of normalizeWikiPath(path)
  • links_store.go: GetRefactorSourcePageIDsForWikiLinkTitle finds source pages via sentinel to_path for use in rename refactoring
  • link_service.go: delegates new store method; HealWikiLinksForPage guards against ambiguous titles; adds HealWikiLinksForTitleIfUnambiguous
  • refactor.go: buildApplyPlan merges sentinel-based page IDs into affectedPageIDs on title-changing renames; getAffectedPages now also queries sentinel-based pages so the preview matches what apply does
  • link_effect.go: on title-changing slug updates, breaks stale wikilink:OldTitle sentinels via MarkIncomingLinksBrokenForPage then re-heals if OldTitle is still unambiguous; post-delete heal loop deduplicates by title to avoid redundant DB round-trips

[[Title]] wiki-links are now stored as wikilink:Title sentinels
regardless of whether the target page already exists. Previously a
single unambiguous match was stored as a resolved route path, causing
inconsistencies across rename, move, and delete flows.

Key changes:
- helpers.go: single-match title lookups (pure and slash-fallback) now
  return wikilinkSentinel(target) instead of normalizeWikiPath(path)
- links_store.go: GetRefactorSourcePageIDsForWikiLinkTitle finds source
  pages via sentinel to_path for use in rename refactoring
- link_service.go: delegates new store method; HealWikiLinksForPage
  guards against ambiguous titles; adds HealWikiLinksForTitleIfUnambiguous
- refactor.go: buildApplyPlan merges sentinel-based page IDs into
  affectedPageIDs on title-changing renames; getAffectedPages now also
  queries sentinel-based pages so the preview matches what apply does
- link_effect.go: on title-changing slug updates, breaks stale
  wikilink:OldTitle sentinels via MarkIncomingLinksBrokenForPage then
  re-heals if OldTitle is still unambiguous; post-delete heal loop
  deduplicates by title to avoid redundant DB round-trips
Copilot AI review requested due to automatic review settings June 5, 2026 13:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors title-based [[Title]] wiki-links to be stored uniformly as wikilink:Title sentinel to_path values (even when the target page exists), improving consistency across rename/move/delete flows and enabling reliable healing/refactoring of title-based links.

Changes:

  • Store resolved [[Title]] links as wikilink:Title sentinels (instead of resolved route paths) during link extraction/resolution.
  • Extend refactor preview/apply to include pages referencing the old title via wikilink:OldTitle sentinels so rename previews match apply behavior.
  • Update link indexing side effects and tests to correctly break/heal sentinel-based links during rename/delete scenarios.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/wiki/pagesave/link_effect.go Breaks/heals incoming links for rename/delete flows, including sentinel-based wikilink:* links.
internal/wiki/pages/refactor.go Includes sentinel-based source pages in rename preview/apply affected sets so refactor coverage matches sentinel storage.
internal/wiki/pages/pages_test.go Updates/refines refactor and delete tests to match sentinel storage and new heal/break semantics.
internal/links/links_store.go Adds store query to find source pages referencing a specific wikilink:Title sentinel.
internal/links/link_service.go Adds service wrapper, guards healing to only occur when a title is unambiguous, and adds “heal-if-unambiguous” helper.
internal/links/link_service_test.go Adds test coverage for the new ambiguity guard behavior in HealWikiLinksForPage.
internal/links/helpers.go Changes wiki-link target resolution to store wikilink:Title even for single unambiguous matches.

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

Comment thread internal/wiki/pagesave/link_effect.go Outdated
perber added 4 commits June 5, 2026 18:58
Cover the key behaviors of the sentinel refactoring:
- Rename preview includes [[Title]] sentinel pages as affected pages
  with wiki-link syntax in matchedPaths (not raw route paths)
- Rename apply with rewriteLinks rewrites [[Title]] to [[NewTitle]]
- Rename refactor dialog shows [[Title]] page with correct matched path
- Move preview shows path-hint [[folder/slug]] as affected page
- Ambiguous [[Title]] shows 0 broken links in the link panel
- Ambiguous [[Title]] appears as backlink for both matching pages
- Delete dialog shows backlink warning for [[Title]] references
…og e2e test

PageSaveEvent.Before was never set for update operations, making the
title-change side effect in LinkIndexSideEffect dead code. Populate it
so MarkIncomingLinksBrokenForPage and HealWikiLinksForTitleIfUnambiguous
fire correctly on title-changing renames.

Fix the e2e test that expected the refactor dialog to appear without
triggering a manual save — auto-save skips slug changes by design, so
the test must click the save button first.
Wait for the manual save button to become enabled before
triggering the refactor dialog.

Verify the rewritten wikilink against the stored page content
instead of rendered article text so the assertion matches viewer
behavior.
PageSaveEvent.Before for update events points to the live PageNode,
which UpdateNode mutates in place — so Before.Title is the new title,
not the old one.  Remove Before from update events (satisfying the
existing EventBeforeIsOmittedForLiveNodeSafety test), introduce an
explicit OldTitle field that is captured before UpdateNode runs, and
use After.ID (stable across renames) instead of Before.ID in the
link effect.

Add TestLinkIndexSideEffect_Rename_HealsPreexistingBrokenWikilinks
to cover the scenario: pre-existing broken [[Alpha]] sentinels
(ambiguous before the rename) are healed to the one remaining Alpha
page once the renamed page exits the title.
@perber
perber merged commit 3cc5ee8 into main Jun 5, 2026
9 checks passed
@perber
perber deleted the refactor/wikilink-always-sentinel branch June 5, 2026 20:02
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