Pin work_products identity to (company, workspace, path)

The natural key used to be (companyId, provider, externalId), so two
workspaces with the same workspace-relative path collided onto one
row. Provenance was also frozen at the first write: `created_by_run_id`
never refreshed, so a run that edited a pre-existing file never
qualified as a deliverable and the DocumentCenter "open" link could
still jump into the first workspace after a repo move.

Migration v45 adds `workspace_id` + `last_touched_by_run_id`, backfills
`workspace_id` via the task/run join, seeds `last_touched_by_run_id =
created_by_run_id`, and installs a partial unique index on
`(company_id, workspace_id, provider, external_id)` scoped to rows
that have a workspace. The artifact projector now records
`workspace_id` on insert and refreshes `last_touched_by_run_id` on
every upsert. The deliverable signal query reads either provenance
column so a run that only edited a pre-existing file still counts.
`resolveWorkProductTarget` prefers the stored `workspace_id` and falls
back to the task/run join for legacy NULL rows.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-19 15:43:48 -04:00
1 parent d1483dcd5d
commit d9b35d73ab
12 files changed
+179 -25

No files matched your search

+2
View File
@@ -9,6 +9,7 @@ import { createMigrationsV41V41 } from "./migrations/v41-v41";
import { createMigrationsV42V42 } from "./migrations/v42-v42";
import { createMigrationsV43V43 } from "./migrations/v43-v43";
import { createMigrationsV44V44 } from "./migrations/v44-v44";
import { createMigrationsV45V45 } from "./migrations/v45-v45";
import {
columnExists,
nowIso,
@@ -193,6 +194,7 @@ export function runMigrations(
...createMigrationsV42V42(deps),
...createMigrationsV43V43(deps),
...createMigrationsV44V44(deps),
...createMigrationsV45V45(deps),
];
for (const migration of migrations) {