Skip to content

renameRepositoryIdentity omits 7 identity-bearing Drizzle-schema tables (repository_ai_keys, repository_linear_keys, bounties, review_suppression, agent_pending_actions, issue_watch_subscriptions, github_agent_command_feedback) #8379

Description

@JSONbored

Context

src/db/repo-identity-rename.ts's renameRepositoryIdentity(env, oldFullName, newFullName) fixes a real bug where a GitHub repo-rename webhook orphans every row already recorded under the old owner/repo string (see the module's own header comment: GitHub sends the same installation + the new full_name, but upsertRepositoryFromGitHub's onConflictDoUpdate keys on full_name, so the very next webhook after a rename silently forks a second, disconnected row instead of updating the existing one).

The fix walks every src/db/schema.ts table that carries a repo_full_name-shaped identity column and moves the old name's rows forward to the new name (fold-then-rename where a unique constraint could collide, plain rename otherwise). The module's own comment states the intended contract explicitly: "New tables extend this function directly, following the same shape."

That contract has drifted. Seven tables in src/db/schema.ts carry a repo_full_name column, are actively read/written by live code, and are not touched by renameRepositoryIdentity at all — a rename webhook silently leaves their rows pinned to the old name forever, exactly the bug this module exists to prevent:

Table (schema.ts var / SQL name) Column shape Live writer Correct fold strategy
repositoryAiKeys / repository_ai_keys repo_full_name PRIMARY KEY src/db/repositories.ts (BYOK provider-key store) Fold-then-rename (delete any pre-existing newFullName row, then UPDATE ... WHERE repo_full_name = oldFullName) — same anchor-table shape as repositories/burdenForecasts/repoQueueTrendSnapshots/repoSyncState already in the module.
repositoryLinearKeys / repository_linear_keys repo_full_name PRIMARY KEY src/db/repositories.ts (Linear API key store, #3186) Same fold-then-rename anchor shape.
bounties UNIQUE (repo_full_name, issue_number) src/db/repositories.ts, read across src/signals/data-quality.ts, src/signals/local-branch.ts, src/signals/review-risk.ts, src/mcp/server.ts, src/openapi/spec.ts, src/github/commands.ts, src/queue/signal-snapshot.ts, src/api/routes.ts, src/services/decision-pack.ts, src/services/agent-orchestrator.ts, src/services/issue-quality.ts Fold on colliding issue_number values, same shape as the module's existing pullRequests/issues handling.
reviewSuppression / review_suppression UNIQUE (repo_full_name, category, path_glob, pattern_hash) — a 4-column composite key src/db/repositories.ts Per-tuple fold (select the colliding (category, path_glob, pattern_hash) triples under oldFullName, delete any matching newFullName rows, then rename), same shape as the module's existing checkSummaries handling.
agentPendingActions / agent_pending_actions UNIQUE (repo_full_name, pull_number, action_class) — a 3-column composite key src/db/repositories.ts (the agent-layer approval queue, #779) Per-tuple fold on (pull_number, action_class), same shape as the module's existing pullRequestFiles handling.
issueWatchSubscriptions / issue_watch_subscriptions UNIQUE (login, repo_full_name) src/db/repositories.ts Fold on colliding login values, same single-column-fold shape as the module's existing contributorRepoStats handling.
githubAgentCommandFeedback / github_agent_command_feedback No unique index touches repo_full_name (its only unique index is (answer_id, actor_hash); repo_full_name/issue_number are only a non-unique index) src/db/repositories.ts Plain rename (UPDATE ... WHERE repo_full_name = oldFullName), no fold needed — same shape as the module's existing repoSnapshots/repoGithubTotalsSnapshots handling.

Every one of these tables is actively queried by live application code (verified via grep across src/), so this is not the "orphaned table, no live writer" case the module explicitly and deliberately excludes for review_targets/repo_chunks/the four AI-result caches. A repo rename today silently and permanently disconnects a repo's BYOK provider keys, Linear integration key, open bounties, review-suppression rules, pending agent approval-queue actions, issue-watch subscriptions, and command-feedback votes from the renamed repo — each of those features degrades or breaks for that repo until an operator notices and manually re-keys them.

Requirements

  • Extend renameRepositoryIdentity in src/db/repo-identity-rename.ts to cover all seven tables listed above, using the exact fold strategy noted for each (mirroring the existing per-table blocks already in the file for tables with the same key shape — do not invent a new generic cross-table helper; this file's own header comment explains why it's deliberately one explicit block per table).
  • Import the seven Drizzle table objects from ../db/schema alongside the existing imports.
  • Preserve the function's existing invariants: idempotent (safe to re-run for a redelivered webhook), collision-safe (a row that already exists under newFullName is folded away in favor of the pre-existing oldFullName row, never the reverse), and a no-op when oldFullName === newFullName.
  • Do not touch any of the tables the module's own comment deliberately excludes (the AI/LLM result caches, review_targets, repo_chunks).

Deliverables

  • repositoryAiKeys fold-then-rename added to renameRepositoryIdentity.
  • repositoryLinearKeys fold-then-rename added.
  • bounties fold-then-rename (on issue_number) added.
  • reviewSuppression per-tuple fold (on category, path_glob, pattern_hash) added.
  • agentPendingActions per-tuple fold (on pull_number, action_class) added.
  • issueWatchSubscriptions fold (on login) added.
  • githubAgentCommandFeedback plain rename added.

Test Coverage Requirements

src/db/repo-identity-rename.ts is under src/**, so it is Codecov patch-gated at 99%, branch-counted. test/unit/repo-identity-rename.test.ts already has one describe block per existing table with a consistent pattern — for each of the seven new tables, add a matching block asserting:

  • A row under oldFullName with no colliding row under newFullName is renamed cleanly (all identity columns updated).
  • A row under oldFullName that collides with a pre-existing row under newFullName (same unique key) folds correctly — the oldFullName row's data wins, the stray newFullName row is removed, no duplicate remains.
  • A rename with nothing under oldFullName for that table is a safe no-op (already covered by the top-level "safe no-op when nothing exists yet" test, but confirm the new table doesn't throw).
  • renameRepositoryIdentity is idempotent (running it twice in a row for the same table produces the same end state).

Expected Outcome

A GitHub repository rename correctly carries a repo's BYOK AI key, Linear integration key, open bounties, review-suppression rules, pending agent-approval-queue actions, issue-watch subscriptions, and command-feedback votes forward to the new name — none of them are silently orphaned under the stale old name.

Links & Resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions