What is Conta Fork Yeah?

What it solves

Many domains keep data on a per-period basis — a fiscal year, a budget cycle, a sprint, a software release, a campaign window — where each period is a separate edit-target but is conceptually a continuation of the one before. The pattern shows up well outside finance: course catalogues per semester, schedule rosters per season, configuration sets per release, anything else that’s versioned by an integer period.

At period boundary you rarely start from a blank slate — you want to carry the previous period’s data forward and continue editing it from there. You may also want to copy a snapshot of the current data without progressing the period, for scenarios like "save as" or branching.

The naïve approach — load the source graph, deep-copy it, save the copy — runs into three recurring problems:

  1. Lineage is lost. Once the copy is saved, there’s no record of where it came from or which row was the parent of which.

  2. Identifiers are reused or randomised inconsistently. References between entities point at the wrong period, or stop pointing anywhere.

  3. Partial failures are catastrophic. A single invalid item halfway through a 200-entry copy aborts the whole operation.

conta-fork-yeah provides primitives for all three:

  • Lineage is recorded explicitly on each forked entity via ForkSources. A continued copy from season 1 to season 2 carries a forkedFrom like:

    {
      "continuedFrom": {
        "forkMode": "ToNext",
        "identifier": "dj:8a1c…->nj:550e…",
        "forkedAt": "2026-04-28T08:30:00Z"
      }
    }
  • New identifiers are generated through a single SourceIdentifierGenerator per fork operation, so cross-references stay consistent.

  • Bulk forks use ForkAttempt so each item succeeds or fails independently and the caller can inspect the outcome.

Where the name comes from

The vocabulary is borrowed straight from version control. Forking a repository takes an existing project as the starting point, produces a divergent copy, and keeps a pointer back to where it came from — and from that point forward the two histories evolve independently.

conta-fork-yeah applies the same idea to domain object graphs:

  • the existing graph is the source,

  • the new graph is the fork,

  • the pointer back is ForkSources (with copiedFrom / continuedFrom slots),

  • the two then evolve independently.

The metaphor extends a bit further: the mode of a fork — ToCopy, ToNext, ToPrevious — is roughly analogous to "fork at HEAD", "fork onto next branch", "fork onto previous branch". And like a repository fork, nothing automatically flows back from one to the other after the split (see Forks and Commands).

Vocabulary

The library uses a small set of terms consistently:

Fork

The act of producing a new instance of an entity (and usually its children) from an existing one.

Source

The entity that was forked from. Recorded on the new entity as part of its ForkSources.

Mode

How the fork happened — ToCopy, ToNext, or ToPrevious. See The Forking Model.

Lineage

The chain of ForkSource records left on a forked entity. Lets you walk backwards from the new instance to whatever it was derived from.

Identifier

The key:uuid pair that uniquely names an entity in the lineage chain (e.g. fa:550e8400-…).

Source identifier

A path of up to three identifiers that locates an entity inside its parent hierarchy (e.g. dj:…→nj:…). See Identifiers.