Skip to content

Pilot: formal verification (TLA+ / Lean) of the sync engine and other data-loss-critical state machines #792

Description

@padak

Summary

Evaluate formal methods (Lean 4 proofs, TLA+ model checking) for the parts of kbagent where a logic error means lost or duplicated production data. Inspired by Anthropic's use of Lean/TLA+ on the Claude Agent SDK state machines: extract a small model from real code, prove invariants / search for counterexamples, replay every counterexample against the real code as a failing test, then fix.

This is deliberately targeted, not "verify the whole CLI".

Why kbagent is a partial fit

Most historical kbagent bugs are not internal-logic bugs a model would catch:

  • Misunderstood Keboola API semantics (DELETE on a trashed config purges permanently, notification ?event= is silently ignored, Metastore opaque 401). A model only proves properties of the model; if it encodes the API as wrongly as the code does, the proof passes and the bug stays.
  • Documentation / plugin drift (CLAUDE.md convention v0.6.0: Branch lifecycle management + security hardening #17).
  • Windows vs POSIX OS behavior.

Where it does fit (ranked)

  1. Sync engine (pull / push / diff) -- a real three-way state machine (local tree / manifest baseline / remote) with branch trees and ignored components, and a documented history of data-loss bugs: delete-dir-then-push destroyed production configs (sync: ignore keboola.mcp-server-tool workspace records like keboola.sandboxes — and manifest ignoredComponents is never read #689), scaffold push created 34 duplicates (config new --output-dir --push writes a scaffold without the created config ID → duplicates on next sync push #644), permanent phantom drift (sync push stamps pull_config_hash from disk while diff compares an API-derived hash — every pushed config stays "REMOTE MODIFIED" forever (mirror of #466) #686), cross-branch tree mixing (sync: production diff/push after 'sync pull --branch' flags the whole orphaned main/ tree as added (mass-duplicate risk) #649). Each is expressible as an invariant, e.g. push never deletes a remote config the user did not deliberately delete locally; pull --force never silently discards a local modification.
  2. Destructive operations under network failure (TLA+) -- config delete locate-first guard, notification replace-recipient create-then-delete, non-retried project create, job run idempotency. Question: can any interleaving of timeout / retry / concurrent run lose or duplicate a resource?
  3. Cross-process concurrency on local state -- auth.json has a real cross-process lock; config.json uses a weaker helper. Parallel agent invocations + serve + scheduler are the classic interleavings tests miss. (No known bug -- a place to look.)
  4. Permission engine -- pure function with safety properties (--deny-destructive never permits a destructive op; adding a deny never grants). Property-based tests (Hypothesis) likely give the same confidence far cheaper than Lean.

Not worth it: HTTP client wrappers, output formatting, self-update, merge-request derived states (truth lives server-side).

Risks

  • Model drift: Lean/TLA+ cannot be extracted from Python; the model is a hand-written abstraction. The durable artifact is the regression tests born from counterexamples, not the proofs.
  • Human review is the bottleneck: someone must confirm the model matches both the code and live API behavior.

Pilot plan (sync engine)

  1. Derive invariants from the sync bug history and current code.
  2. Model push/pull/diff classification in TLA+ (TLC counterexample search); prove the pure classification properties in Lean where it is cheap.
  3. Replay every counterexample as a pytest against the real code.
  4. Reproduced -> fix + regression test in a normal PR. Not reproduced -> tighten the model.

Success criterion: number of counterexamples that reproduce as failing tests against real code. Zero reproducible findings -> stop, fall back to property-based testing. The model is committed as documentation only, not a CI gate.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions