Skip to content

fix(import): RM-17159 Avoid duplicate sidebar slugs#27

Draft
xavierandueza wants to merge 2 commits into
mainfrom
fix/rm-17159-importer-sidepage-duplication
Draft

fix(import): RM-17159 Avoid duplicate sidebar slugs#27
xavierandueza wants to merge 2 commits into
mainfrom
fix/rm-17159-importer-sidepage-duplication

Conversation

@xavierandueza

Copy link
Copy Markdown
Contributor
🚥 Resolves RM-17159

🧰 Changes

  • BEFORE: an imported page could reuse the same slug as its containing sidebar category, which could create duplicate sidebar slugs.
  • AFTER: category slugs are reserved when planning imported page slugs, so colliding pages are expanded or given a deterministic fallback.

🧬 QA & Testing

  • node --test src/commands/import.slug-planner.test.js
  • npm test
  • npm run step:skeleton https://docs.couchbase.com/llms.txt from the linked runner setup

[RECORDING/IMAGES]

@xavierandueza xavierandueza self-assigned this Jul 2, 2026

@xavierandueza xavierandueza left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Code quality review comments. I cannot request changes on my own PR via GitHub, but these should be treated as requested changes before merge.

Comment thread src/commands/import.js Outdated
}
for (const slug of reservedSlugs) {
if (!groups.has(slug)) groups.set(slug, [])
groups.get(slug).push({ reserved: true })

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This works, but it makes the slug planner's core model more ad-hoc by injecting a fake { reserved: true } entry into a collection that otherwise contains page entries. That sentinel then leaks into the growth logic via !e.reserved, while the rest of the function still assumes entries have page, segments, depth, etc.

I think there is a cleaner code-judo move here: keep entries as only real pages, and make the collision check explicitly account for blocked category slugs. For example, after grouping real entries, treat reservedSlugs.has(slug) as a collision for that real group and grow those real entries, without appending synthetic objects to the group. That keeps the data model honest and removes the new mixed-shape branch entirely.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(agent response)
Fixed — kept slug groups limited to real page entries and made reserved category slugs an explicit collision condition. 6631b7a

Comment thread src/commands/import.js Outdated
@@ -4348,8 +4355,8 @@ export function ensureUniqueSlugs(categories) {
slug = `${base}-${n}`
styles.error(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This fallback is now an expected path for a single-segment category landing page — the new test even blesses api -> api-2 — so emitting it as styles.error is misleading. The import succeeds and there is no organizer duplicate in that case; we just ran out of URL context because the page and category intentionally have the same slug.

Can we split the expected page/category fallback from the true duplicate case, or downgrade this to warning/info with a message that doesn't imply the organize step did something wrong? Error-level output should be reserved for actual failures or data corruption, otherwise successful imports look broken.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(agent response)
Fixed — page/category fallback now emits a warning with a non-error message, while true duplicate page slugs keep the existing error-level signal. 6631b7a

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.

1 participant