OpenFn / OpenFn/lightning

Record sandbox workflow lineage across a fork

Open
#4,938 0 comments 0 reactions 1 assignee View on GitHub

@elias-ba is already working on this.

Since Jul 8, 2026.

tech-debt
Dominant language
Elixir
Stars
296
Forks
86
Avg merge
1d 13h
Merged PRs (30d)
50

Description

As a maintainer of the sandbox merge, I want each sandbox workflow to carry a stable link to the parent workflow it was cloned from, so that merges, deletions, and renames are resolved by identity instead of guessed from names.

Follow-up to #4919 (the fix there is a safe interim) and part of #4852 (Sandbox DevX epic).

The gap

When a sandbox is provisioned, create_sandbox_workflows builds a map of parent workflow id to new sandbox workflow id, uses it only to wire up the clone, and discards it. Each sandbox workflow ends up with a fresh id and no stored link to its origin, so at merge time MergeProjects.merge_project re-matches the two projects by workflow name.

The lineage we need exists at fork time and we throw it away. Working from names alone, the merge cannot tell a workflow added to the parent after the fork from one deleted in the sandbox (the #4919 bug), cannot follow a workflow through a rename, and falls back to name-and-structure heuristics for node and divergence matching. Persisting the origin link fixes these at the root.

Approaches

Ways to persist the link, lightest to most capable:

  • Option A — a column on workflows (recommended). A nullable source_workflow_id referencing the origin workflow, set in create_sandbox_workflows from the map it already builds. Smallest change, and it gives per-workflow identity, so it covers both the deletion distinction and rename-following.
  • Option B — a workflow_lineages table. One row per clone (sandbox workflow, origin workflow, forked-at). Same per-workflow identity as A, with room for multi-hop history later, but heavier than this needs today.
  • Option C — a fork manifest on the sandbox. Just the set of origin workflow ids captured at fork. Lightest, and enough to tell added-after-fork from deleted-in-sandbox, but it carries no per-workflow identity, so it does not help renames or node matching.

Recommendation: Option A. A and B meet the full goal; C is a lighter alternative if only the deletion distinction is wanted.

How the merge uses it

With per-workflow identity (A or B), the merge resolves the parent/sandbox correspondence by the stored link first and falls back to name matching only for sandboxes created before this ships. That retires the workflow_added_after_fork? timestamp guess and lets a rename be matched in place instead of read as a delete plus a create.

Open decisions

  • Existing sandboxes have no stored lineage. Decide between a one-time best-effort backfill (by name and fork time) and keeping the name fallback for old sandboxes while new ones get exact lineage.
  • How far to take it. The floor is the identity work above. The fuller end is a three-way merge on a recorded fork baseline (base versus sandbox versus current parent), which also makes divergence and conflicts precise and builds on the same lineage. Which to build is a product and priorities call at pickup, not pre-decided here.

Acceptance criteria

  • Given a sandbox created after this ships (via A or B), when I open its merge screen, then added-after-fork and deleted-in-sandbox workflows are distinguished without using creation times.
  • Given I rename a workflow in the sandbox, when I merge, then it is matched to its origin and updated in place, not shown as a delete plus a create.
  • Given an older sandbox with no stored lineage, when I merge, then the name fallback still works and nothing regresses.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.