fix: deploy pipeline drafts with freshly-inferred assets, not a stale snapshot

"Save all" spread `...draft.script` into createScript, which carries a `assets`
snapshot that isn't refreshed when the body is edited. So a renamed/removed
output (e.g. an old `CREATE TABLE exciting_en32z9` later changed to
`exciting_880909`) was re-deployed as a phantom write edge and lingered as an
orphan asset on the graph — shown with no producer, and shifting position on
click as the graph re-derived.

saveDraft now re-runs inferAssets on the current body and passes the result as
`assets`, overriding the snapshot — mirroring the per-pane save. The backend
clears+reinserts from the sent set, so a re-deploy drops the stale rows.
Verified: deploying with the fresh asset set removes the orphan from the graph.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-06-16 18:31:20 +02:00
parent f6f675296d
commit cc1e1892ad
@@ -789,6 +789,19 @@
// per-pane save uses). The createScript call is the real
// validation gate — if the body is broken it'll reject there.
}
// Re-infer the asset lineage from the CURRENT body. The draft's
// `script.assets` is a snapshot that isn't refreshed on edit, so without
// this a renamed/removed output (e.g. an old `CREATE TABLE foo`) would
// be re-deployed as a phantom write edge and linger as an orphan asset.
// Mirrors the per-pane save, which sends live-inferred assets.
let assets: AssetWithAltAccessType[] = []
try {
const inferred = await inferAssets(script.language, script.content)
if (inferred?.status !== 'error') assets = (inferred?.assets ?? []) as AssetWithAltAccessType[]
} catch {
// Same fallback as above — an unparsable body deploys with no
// lineage rather than the stale snapshot.
}
await ScriptService.createScript({
workspace: ws,
requestBody: {
@@ -805,7 +818,10 @@
is_template: false,
tag: script.tag,
kind: script.kind as Script['kind'] | undefined,
lock: undefined
lock: undefined,
// Freshly inferred above — overrides the stale snapshot carried
// by `...script`, so the deployed lineage matches the body.
assets: assets as any
}
})
}