Skip to content

fix(compile): drop same-batch duplicate page titles in compile_kb#440

Open
nickmopen wants to merge 1 commit into
vouchdev:testfrom
nickmopen:fix/issue-439-compile-same-batch-collision
Open

fix(compile): drop same-batch duplicate page titles in compile_kb#440
nickmopen wants to merge 1 commit into
vouchdev:testfrom
nickmopen:fix/issue-439-compile-same-batch-collision

Conversation

@nickmopen

Copy link
Copy Markdown

What changed

compile_kb() now folds each accepted draft's title/slug into taken_names as soon as it survives phase-1 validation, so a second same-titled draft later in the same batch is dropped by the existing collision guard instead of also passing.

Why

taken_names was computed once before the phase-1 validation loop and never grew as survivors were accepted — unlike phase-2 wikilink resolution just below it, which does fold survivors back in. Two same-titled (or same-slugifying) drafts returned in one compile_kb() LLM response both passed _draft_problem() and got filed as separate PAGE proposals sharing the same id. proposals.approve() deliberately routes an existing page id through update_page() (the vault-edit path), so approving the first proposal created the page and approving the second silently overwrote it — no error, no diff, no "already exists" signal to the reviewer. Fixes #439.

What might break

  • On-disk layout: none.
  • Behaviour change (intentional): a compile batch containing two drafts with colliding titles now proposes only the first; the second is dropped with reason page for '<title>' already exists or is pending review, same message already used for cross-call collisions. No prior behaviour relied on both surviving — that was the bug.

VEP

Not a surface change (no object-model, kb.* method, on-disk-layout, or audit-log-shape change) — internal validation-ordering fix in compile.py.

Tests

  • make check (lint + mypy + pytest) — clean on the touched files. Full local suite: 1012/1020 passed (excluding tests/embeddings); the 8 pre-existing failures and 2 excluded modules (test_http_server.py, test_http_server_mcp.py, which bind real sockets) are Windows-local environment artifacts unrelated to this change (os.getuid absence, \ vs / path separators, symlink privilege requirements, a cat-based LLM stub) — none touch compile.py, proposals.py, or the new test. CI runs on Ubuntu where these don't occur.
  • New regression test test_same_batch_duplicate_titles_second_dropped reproduces the issue's repro exactly: two same-titled drafts in one batch, second is dropped, and approving the first leaves the page with the first draft's body untouched.
  • CHANGELOG.md updated under ## [Unreleased].

Fixes #439

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1173efbc-2c47-41df-9f26-7509dff3302e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added docs documentation, specs, examples, and repo guidance tests tests and fixtures size: XS less than 50 changed non-doc lines labels Jul 8, 2026
taken_names was computed once before the phase-1 validation loop and
never grew as survivors were accepted, unlike phase-2 wikilink
resolution just below it. two same-titled drafts in one compile_kb()
LLM response both passed the collision guard and got filed as separate
PAGE proposals with the same id; approving the first created the page
and approving the second silently overwrote it via the update_page
vault-edit path, with no error or diff shown to the reviewer.

fold each survivor's title/slug into taken_names as soon as it's
accepted, so a same-batch duplicate is dropped the same way a
collision with an existing page or pending proposal already is.

Fixes vouchdev#439
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs documentation, specs, examples, and repo guidance size: XS less than 50 changed non-doc lines tests tests and fixtures

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant