Skip to content

feat(flex-chain): guarded repair tool that restores hours and re-walks the chain - #909

Merged
renemadsen merged 16 commits into
masterfrom
feat/flex-chain-repair-tool
Oct 7, 2026
Merged

renemadsen merged 16 commits into
masterfrom
feat/flex-chain-repair-tool

Conversation

@renemadsen

Copy link
Copy Markdown
Member

Summary

A tool for repairing historic flex balances with the product's own chain code (sub-project 3 of the 2026-09 flex drift programme). Design: docs/superpowers/specs/2026-09-27-flex-chain-repair-tool-design.md, plan: docs/superpowers/plans/2026-09-27-flex-chain-repair-tool.md.

  • FlexChainRepair.RepairWorkerAsync handles one worker inside one transaction:
    • locks the worker's rows;
    • guards every restore line against the version and hours seen at dump time;
    • restores the hours;
    • carries the chain with FlexChainRecompute.RunForwardAsync from the first row;
    • checks every balance against the expected values, two-sided and with a continuity check.
    • It commits only with apply set and every check passing. A dry run (the default) always rolls back.
  • FlexChainRepair.RevertAsync puts back one worker's rows from the before-image, only where a row is still at the version the repair left.
  • FlexChainRepairCsv reads and writes the restore manifest, the expected balances and the before-image (invariant culture).
  • A thin console under tools/FlexChainRepair is not in the .sln and not packed.

No change to RunForwardAsync, CarryChain, DayLock or any entity.

Tests

FlexChainRepairTests (21) and FlexChainRepairCsvTests (6) run against MariaDB in CI. They cover:

  • apply and dry run;
  • the guard: stale version, changed hours, another worker's row, a removed row, duplicate lines;
  • an open shift restored to 0, and a break healed by the walk alone;
  • expected mismatches and missing rows, and continuity for rows without an expected entry;
  • locked days and version history;
  • revert, including skipping rows changed after the repair.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1

renemadsen and others added 5 commits September 27, 2026 14:51
…e-walks the chain

RepairWorkerAsync locks the worker's rows, checks every restore line
against the version and hours seen at dump time, restores the hours,
carries the chain with RunForwardAsync, and compares every balance
with the expected values (two-sided, plus continuity). It commits only
on apply with every check passing; a dry run always rolls back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
RevertAsync writes each captured row back only where the row is still
at the version the repair left, under a row lock, dry run by default.
One worker per call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI lite review requested due to automatic review settings September 27, 2026 13:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Review effort: Lite
Findings: 1 High severity · 5 Medium severity

Open (6)
What changed in this PR

Adds a guarded flex-chain repair/revert library with CSV support and database tests. The console described in the PR documentation is not included.

Changes:

  • Added repair, rollback, guard, mismatch, and continuity logic.
  • Added invariant-culture CSV parsing and before-image serialization.
  • Added MariaDB-backed repair/revert tests and design documentation.
File Description
Microting.TimePlanningBase/​Infrastructure/​Helpers/​FlexChainRepairTypes.cs Updated as part of this pull request.
Microting.TimePlanningBase/​Infrastructure/​Helpers/​FlexChainRepairCsv.cs Updated as part of this pull request.
Microting.TimePlanningBase/​Infrastructure/​Helpers/​FlexChainRepair.cs Updated as part of this pull request.
Microting.TimePlanningBase.Tests/​FlexChainRepairTests.cs Updated as part of this pull request.
Microting.TimePlanningBase.Tests/​FlexChainRepairCsvTests.cs Updated as part of this pull request.
docs/​superpowers/​specs/​2026-09-27-flex-chain-repair-tool-design.md Updated as part of this pull request.
docs/​superpowers/​plans/​2026-09-27-flex-chain-repair-tool.md Updated as part of this pull request.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Microting.TimePlanningBase/Infrastructure/Helpers/FlexChainRepairCsv.cs Outdated
Comment thread docs/superpowers/plans/2026-09-27-flex-chain-repair-tool.md
Comment thread docs/superpowers/specs/2026-09-27-flex-chain-repair-tool-design.md
renemadsen and others added 2 commits September 27, 2026 15:28
- revert skips a row whose worker differs from the before-image's
- re-check the reconciled boundary under the row lock
- a worker with no live rows still fails its restore lines / expected entries
- CSV rejects NaN and infinities, naming line and column

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Dry run by default; --apply requires --confirm-database to match the
connection's database. One fresh context per worker. The before-image of
each applied worker is written and flushed to disk before anything else,
and an apply run stops at the first worker whose state is unknown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI review requested due to automatic review settings September 27, 2026 13:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread tools/FlexChainRepair/Program.cs Outdated
Comment thread tools/FlexChainRepair/Program.cs
Comment thread Microting.TimePlanningBase/Infrastructure/Helpers/FlexChainRepair.cs Outdated
Comment thread tools/FlexChainRepair/Program.cs Outdated
Comment thread tools/FlexChainRepair/Program.cs Outdated
Copilot AI review requested due to automatic review settings September 27, 2026 13:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- reject a NaN, infinite or negative tolerance
- a lost commit acknowledgement counts as landed only for this worker's
  rows written during this call
- console checks every expected/restore Id against its row's worker,
  and refuses a walked worker with no expected balances
- a value flag followed by another flag is an invocation error, so
  `--out --apply` can never turn into a dry run
- unreadable input files exit 2; README adds a pre-apply snapshot step

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI review requested due to automatic review settings September 27, 2026 14:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Incomplete expected-balance coverage can allow unsafe commits, alongside additional correctness, reporting, and documentation issues.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (6)
Previously missed (1)

In code that hasn't changed since last review

Low severity Update plan to match current per-worker error behavior

docs/​superpowers/​plans/​2026-09-27-flex-chain-repair-tool.md:684

This implementation-plan bullet is now inconsistent with the shipped console: --apply stops after the first worker exception, and revert invokes RevertAsync once per worker group. Keeping the plan's "loop continues"/single-call description can mislead future changes and operators about the safety boundary; update it to match the current per-worker stop behavior and grouping.

Comment thread tools/FlexChainRepair/Program.cs Outdated
…against the oracle

A live row with no expected balance and an Id at or below the highest
expected Id existed when the oracle was built, so it is a mismatch
("Uncovered") instead of passing on continuity alone. The console checks
the same across the whole file before any worker runs, which also catches
a file missing a worker's newest rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI review requested due to automatic review settings September 27, 2026 14:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Critical input-validation and partial-apply risks, plus additional correctness and coverage gaps, remain unresolved.

Review effort: Lite
Findings: 2 High severity

Open (2)
Resolved since last review (1)

Comment thread tools/FlexChainRepair/Program.cs Outdated
…e Ids up front

RepairWorkerAsync refuses NaN/infinite restore or expected values before
touching the database (every check is `abs(a - b) > limit`, which a NaN
passes). The console rejects duplicate restore Ids before any worker runs,
so a malformed manifest cannot surface only after earlier workers committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI review requested due to automatic review settings September 27, 2026 14:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Critical identity-validation and duplicate before-image handling issues remain unresolved, with CLI test and documentation follow-up also needed.

Review effort: Lite
Findings: 2 High severity

Open (2)
Resolved since last review (2)
Previously missed (1)

In code that hasn't changed since last review

Low severity Align worker failure guidance with apply-mode behavior

docs/​superpowers/​plans/​2026-09-27-flex-chain-repair-tool.md:683

This implementation plan still says a thrown worker is caught and the loop continues, but the delivered console intentionally stops on --apply (stop = apply in Program.cs) because the commit may have landed without an acknowledgement. Update this operational description to distinguish dry-run continuation from apply stop; otherwise the plan gives conflicting guidance for handling an uncertain worker outcome.

Comment thread tools/FlexChainRepair/Program.cs
…tes up front

RepairWorkerAsync refuses an expected entry filed under another row's key
or another worker. The console rejects duplicate before-image Ids before
any revert group runs. The plan now describes the delivered stop-on-error
behaviour of an apply run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI review requested due to automatic review settings September 27, 2026 14:50
@renemadsen

Copy link
Copy Markdown
Member Author

Re the round-5 overview's "previously missed" note on the plan's worker-failure wording (no inline thread): valid — fixed in e1a26f2. The plan now says a dry run continues past a thrown worker while an --apply run stops there, matching the delivered console.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Address the revert input validation, retry-safe before-image reporting, standalone project CI coverage, and dry-run artifact handling.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (2)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Add CI build and tests for FlexChainRepair project

tools/​FlexChainRepair/​FlexChainRepair.csproj:10

This executable is intentionally outside Microting.TimePlanningBase.sln, but the repository CI only runs dotnet build at the solution root and tests Microting.TimePlanningBase.Tests; it never builds or exercises this project. Consequently a compile/API regression in the repair command can merge undetected. Add an explicit CI build (and at least argument/preflight tests) for tools/FlexChainRepair/FlexChainRepair.csproj while keeping it out of the solution.

…air tool in CI

RevertAsync refuses NaN/infinite captured values before touching the
database, since they are written back verbatim. CI now builds
tools/FlexChainRepair (kept out of the solution) so a compile break in
the console cannot merge unnoticed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI review requested due to automatic review settings September 27, 2026 15:10
@renemadsen

renemadsen commented Sep 27, 2026 •

Copy link
Copy Markdown
Member Author

Re the round-6 overview's "previously missed" note (CI never builds tools/FlexChainRepair): valid — fixed in 20b3668. All three workflows now run dotnet build tools/FlexChainRepair/FlexChainRepair.csproj --configuration Release after the solution build, keeping the tool out of the .sln. Argument/pre-flight tests for the console are set aside: the console holds no repair logic (that is all in the library, with 33 repair tests and 8 CSV tests), and its argument handling and every pre-flight were exercised end to end against a local copy of real data — dry run, apply, idempotent re-run, revert to identical data, and each refusal path (truncated oracle, wrong-worker lines, duplicate Ids, --out --apply).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved issues affect active-site selection, diagnostic-file preservation, and valid zero-row worker handling.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)

The repair walk picked any non-removed AssignedSite, unordered, resigned
ones included. It now uses the non-removed, not-resigned site with the
lowest Id — the same definition the console walks and the oracle uses —
so a resigned site's one-minute settings cannot shape the chain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI review requested due to automatic review settings September 27, 2026 15:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Address the critical walk-only commit/retry safety issue and add coverage for the CLI safety path.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)

The pre-flight refused a run when an active worker had no expected
balances, even when that worker has no PlanRegistrations rows at all —
nothing to walk or check (the library already treats it as a no-op).
Only workers with live rows must now be covered by the oracle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VDsVLaH7SqGi1bFk8nAtP1
Copilot AI review requested due to automatic review settings September 27, 2026 19:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Prevent dry runs from producing misleading or silently reusable before-image artifacts, and clarify the documented dry-run file behavior.

Review effort: Lite
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity Safety statement incorrectly claims dry runs write nothing

tools/​FlexChainRepair/​README.md:18

The opening safety statement says that neither command writes anything during a dry run, but both RunRepair and RunRevert create and populate report CSVs under --out even when --apply is absent (and RunRepair also creates an empty before-image.csv). This can mislead operators about the files a dry run will create; clarify that dry runs roll back database changes but still write reports, or change the implementation to avoid those files.

…air-tool

# Conflicts:
#	.github/workflows/dotnet-core-master.yml
#	.github/workflows/dotnet-core-pr.yml
#	.github/workflows/dotnet-core.yml
Copilot AI lite review requested due to automatic review settings October 7, 2026 14:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Moderate CLI error-handling, output-safety, validation, and reporting issues remain.

Review effort: Lite
Findings: 1 Medium severity

Open (1)

Comment on lines +349 to +350
await using var beforeImageStream =
new FileStream(Path.Combine(outDir, "before-image.csv"), FileMode.CreateNew, FileAccess.Write);
@renemadsen
renemadsen merged commit 5a22864 into master Oct 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants