Skip to content

Repairing a fold defect relies on re-reading everything, with no way to ask for a re-derivation #197

Description

@Nitjsefnie

Description

Every derived row this system holds is repaired for free when a fold defect is fixed, and nothing in the codebase provides that. It falls out of the fold recomputing every closure from a full snapshot on every run: updateSettlement rewrites every column, calibrations upsert, and closures no longer emitted are deleted, so the next pass after a fix simply produces the right answer and overwrites the wrong one.

That is the entire recovery plan for issue 176, which refused nineteen settlements that should have been recorded. No migration was written for it because none was needed.

Nothing marks derived rows with the version of the logic that produced them, and there is no way to ask for a re-derivation. The property is real but accidental, and it costs a full re-read of every issue on every pass to keep — which is issue 190, where that cost exhausted the GitHub budget and stopped reconciliation entirely.

So the repair path exists only as a side effect of the thing that has to stop.

Expected Behavior

Re-derivation is a feature that can be asked for: after a fold change, the rows that fold produced can be recomputed deliberately, and it is visible which rows have been recomputed and which are still the output of older logic.

Reproduction Steps

Not a runtime failure, so there is nothing to trigger. The absence is shown by asking the questions the current schema cannot answer:

  1. \d settlements, \d self_work_calibrations, \d unwritable_closures — no column records which version of the fold produced the row.
  2. There is no route, command, or moderation control that re-derives a repository's rows. scripts/reconcile.ts re-folds from the current snapshot rather than marking anything for re-derivation, and it does not currently start at all (issue 12).

Environment / Context

Filed on the maintainer's instruction while designing issue 196, which replaces the full re-read with an incremental fetch keyed on a last-updated watermark. That change removes the accidental self-healing, so the two belong together: 196 is why the property has to become explicit, and this is what replaces it. Ordering matters — landing 196 without this leaves no way to repair a fold defect except a hand-written migration per defect.

Suggested Fix

Unverified. Stamp derived rows with the identity of the fold logic that produced them, and re-derive rows whose stamp is older than the current one. A value bumped deliberately when fold behaviour changes is more honest than a content hash of the source, which would churn on every unrelated edit; it also makes the decision "this change alters what the fold would have written" explicit at the moment someone is best placed to judge it.

Given the queue from issue 13, re-derivation is naturally a job kind rather than a separate mechanism: marking a repository for re-derivation enqueues it, and the worker already handles leases, retries and follow-ups. The watermark from 196 is what such a job ignores — that is precisely its purpose.

Worth deciding rather than assuming: whether re-derivation is per repository or per issue. Issue 176 affected specific closures that could be named, so a targeted re-derivation would have been cheaper than a full pass — but naming them required knowing the defect's shape, which is not always available.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area: ledgerScoring, settlement, calibration and moderationenhancementNew feature or requestoffered: largeOpening catalog · comparison 8 · reserve 8settled: 6Actual catalog · 6 points

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions