Files
sim/apps
Vikhyath MondretiandClaude Opus 5 3a03774e42 fix(forks): stop copying connector-managed knowledge base documents (#6818)
* fix(forks): stop copying connector-managed knowledge base documents

A fork copies a KB's documents but never its connectors, so a
connector-sourced document arrives with `connector_id` nulled and its
`external_id` intact. The sync engine keys every existing/tombstone/
exclusion lookup off `connector_id`, so that copy is invisible to it -
never updated, reconciled, or purged - and `doc_connector_external_id_idx`
does not constrain it either, since its `connector_id` is NULL.

Attaching a connector in the child then re-ingests every page as a NEW
row on top of the snapshot. Each fork hop re-copies the previous hop's
orphans and adds one more generation, so a prod -> UAT -> staging chain
leaves three rows per page and a knowledge search returns the same page
three times, one of them serving content frozen at the fork date.

Exclude connector-managed documents from all four doors a document can
enter a fork through: the whole-KB content copy, the in-transaction
placeholder pre-creation, the sync-only copy into an already-mapped KB,
and the content fill (guarded for payloads planned by a pre-change
worker mid-rollout). The placeholder path matters as much as the copy
loop - filtering only the content phase would leave a permanently
archived row behind a persisted `knowledge_document` mapping. Skipped on
both sides, the reference clears like any other uncopied document's.

A document whose connector was deleted already has a null `connector_id`
(the FK is ON DELETE SET NULL) and is static in the source too, so it
still copies. One count(*) per copied KB logs what was left behind, since
a fully connector-synced KB now forks to zero documents.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(forks): keep the skipped-document count from failing a copied KB

The connector-managed count feeds a log line, but it sat inside the KB's
try block, so a transient failure on a COUNT(*) would roll back a copy
that had otherwise succeeded and clear every reference to it.

Move it into a helper that swallows its own error. Counting is not
copying: only the copy itself may fail a resource. Test proven red by
removing the catch - the mutation reports a knowledge-base failure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(forks): clean up full-KB placeholders planned before the exclusion

The mapped-KB fill guarded a pre-change plan, but the full-KB path did
not: a placeholder planned by an old worker for a connector-managed
document is simply no longer returned by the page query, so nothing fills
it and it stays archived behind a live mapping that a remapped
document-selector still resolves to.

Report those child ids as failed documents so the shared cleanup clears
their references and drops the rows, and delete their persisted identity
so a later sync does not resolve to a row cleanup removes. Keyed on the
SOURCE being connector-managed, which can never become copyable, so it
cannot race a concurrent attempt mid-fill the way a "source is gone"
check could.

The mapping drop is now one helper shared with the mapped-KB catch.
Test proven red by removing the reconciliation block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(forks): make the stale-plan probe best-effort

The probe ran inside the KB try, so a transient SELECT would reach the
catch, roll back a complete copy, delete the child base, and clear every
reference to it. Weighing it as "load-bearing, so fail closed" was wrong:
the probe runs on EVERY copied KB that has referenced documents, while
the state it repairs exists only inside a rollout window. Failing closed
traded a common-path outage against a rare-squared one.

It now swallows its own failure with a loud error log, leaving that
pre-existing state in place rather than destroying a good copy. Test
proven red by removing the catch - the mutation reports the KB failure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 14:23:19 -07:00
..