Skip to main content

fluidfix

Zero-token repair decisions for mechanical single-line bugs. A machine-authored four-instruction kernel decides which repair to try, your test suite judges it, and a language model — when you use one at all — is only ever the eyes. Every output is either a repair your suite accepts — measured byte-exact in 26 of 26 accepted repairs on the benchmark — or an explicit refusal. There is no "plausible fix" branch.

pip install --upgrade fluidfix            # core: zero runtime dependencies
pip install "fluidfix[llm]"     # adds the Claude Opus 5 observer
# commit-and-forget: watch the suite, restore what breaks, refuse what is novel
fluidfix guard path/to/project --python path/to/venv/bin/python --interval 900 --commit

# or one-shot on a known defect file
fluidfix repair path/to/project --file pkg/module.py --python path/to/venv/bin/python

How fast will it be on your repo? Repair time is suite runs x your suite's own runtime — test count barely matters. Ask before you commit:

fluidfix estimate .
  1990 passed, 25 skipped in 4.87s
  suite runtime: 5.60s  (+~0.5s pytest startup per run)

EXPECTED REPAIR TIME on this repo
  typical in-vocabulary defect (2-10 suite runs):  12.2s - 61s

(Those bounds are real: the same repo repaired in 36s and 50s.)

from fluidfix import Oracle, build_packet, MechanicalObserver, repair

oracle = Oracle("path/to/project", python="path/to/venv/bin/python")
packet = build_packet(oracle, "pkg/module.py")          # mechanical, 0 tokens
observations = MechanicalObserver().observe([packet])[0]
print(repair(oracle, "pkg/module.py", observations).summary())

▶ Full demo video (76s, real-time output) · ▶ Live session, unedited + its wall-clock-stamped terminal log (every command shown, breaks included — 3 repairs and 1 refusal in 6.5s of machine time) · Beginner quickstart · Step-by-step tested instructions — every step enforced by tests/test_demo_walkthrough.py in CI.

Watch it (each under 30 seconds, real runs)

Live from PyPI install + exhaustive selfcheck
Deploy, break, forget guard repairs and commits in 0.7s
Real library 455-test suite, byte-exact restore
Teach a class once refused -> register() -> repaired
One hard example, whole class one dictionary fixes 3 different files

Measured, not promised

All numbers below are from a live benchmark on 33 injected single-line bugs in five real PyPI libraries (humanize, inflection, natsort, parse, wcwidth), each library's own suite as the oracle, run 2026-08-30. Per-bug data and methodology ship with this package in docs/BENCHMARK.md; the corpus, injector, and recorded baselines are from fluid-router benchmark/.

fluidfix (Claude Opus 5 as eyes) full Claude Opus 5 debugging
in-vocabulary byte-exact 26/27 22/27 (5 green-only)
out-of-vocabulary 6/6 refused honestly 5/6 exact
silently wrong repairs 0 —
tokens¹ 125,402 total (3,800/bug) 1,322,802 (40,084/bug)
decision cost after that 0 tokens² ~40k tokens each time
  • The observer named the correct defective line 33/33 from lean packets averaging ~1,060 tokens.
  • The mechanical localiser (no model at all) put the true defective line in the packet for 33/33 bugs, at zero tokens.
  • The kernel's decisions are invariant under all 16 renumberings of the act vocabulary: 432/432 live decisions correct; a frozen lookup table scores 27/432 on the same test.
  • With no model anywhere, fluid-router's recorded blind-search kernel scores 17/27 byte-exact at zero tokens — without the localisation this package adds. fluidfix's mechanical mode is validated end-to-end but not yet corpus-scored; see docs/BENCHMARK.md.

¹ Fleet-level harness measurement, all agent context included; the two token columns use different accounting and support the ~10× ratio, not a precise figure. Provenance: docs/data/lean_arm_tokens.json. ² fluid-router2's C verifier measures its kernels at 1.55 ns/decision; this package's pure-Python reference is ~0.6 µs. Either way: no tokens.

The guard: deploy, commit, forget

Most deployed software is not being actively developed — it is being kept alive. fluidfix guard is built for exactly that. It needs no defect file: when the suite goes red it finds the fault file mechanically (traceback frames, else failing-test coverage ranking), repairs it, and — with --commit — records the restoration:

$ fluidfix guard . --commit
[16:43:06] billing.py: repaired line 2 in 4 suite runs (0.7s):
  - return p * (1 - rate)
  + return p * (1 + rate)
  committed

Run it one-shot in CI (exit 0 green/repaired, exit 2 refused), or under cron with --interval. Green suite: it touches nothing. Novel fault class: it refuses, leaves the tree byte-identical, and writes .fluidfix/last_refusal.json — the teach-me signal for register() below. .fluidfix/ is the guard's state directory: add it to your .gitignore.

How it works

suite fails ──► localise (frames ∪ failing-test coverage ∪ AST spans; 0 tokens)
            ──► observe (mechanical regexes, or one batched Claude call)
            ──► EMIT names the fault      m & (-m)
            ──► route() picks the act     15 & ((x>>4)+((x>>8)-x))   ◄ the brain
            ──► apply & run the suite     green → HALT
            ──► ADVANCE and try the next  m - (m & (-m))
            ──► empty mask → refuse, never guess

The routing expression was authored by a program-synthesis engine and is vendored verbatim from fluid-router (verdict: minimal in D∩I); the loop discipline is fluid-router2's EMIT/ADVANCE/HALT, exhaustively verified on all 256 mask states. Run the proofs yourself, offline, in seconds:

fluidfix selfcheck

What should we test first?

fluidfix maintains exactly what your tests cover, so that is the question worth asking before adopting it — and your repository already knows, because every bug fix in its history names the file that broke:

fluidfix hotspots .

Measured on Box2D's own history: guarding 60% of its past defects costs testing 58 files, not 60% of the engine. Defects cluster, so coverage aimed at the cluster is worth roughly twice coverage spread evenly.

Languages

language command judge status
Python fluidfix guard pytest stable
C / C++ fluidfix cguard your test binary, plus the compiler as a cheap first oracle alpha
C# / .NET fluidfix cguard --build-cmd "dotnet build" --test-cmd "dotnet test --no-build" dotnet test (xunit measured) alpha
Java fluidfix jguard JUnit via Maven alpha

C# needed no adapter at all — cguard is generic over its build and test commands. Supporting it cost one source extension (.cs) and one regex for the Failed Class.Method [2 ms] shape that dotnet prints. Measured: a cross-product sign flip in a .NET class library repaired byte-exact in 14 suite runs (20.8s), warm cycle 1.63s.

Unity is not the same as C#. The language works; Unity's own test framework generally needs the Editor in batch mode to run tests, which is a harder oracle and is untested here.

Adding a language is an adapter, not a rewrite — the kernels route integers and edit lines of text, and never learn the language. Java took 223 lines, C took ~450. Measured on two real game repos, all byte-exact: Box2D's b2Cross sign flip in 46 suite runs (82.8s), cglm's glm_vec3_add in 100 runs, and a pointer-arithmetic defect in Box2D's contact_solver.c — with no traceback frame, no discriminating literal and no name affinity — in 428 runs once the gcov tier was supplying executed-line evidence.

selfcheck re-derives five machine-authored laws with no network and no dependencies: fluid-router (which repair), fluid-router2 (which candidate next), the engine law (what to do when blocked — one controller that governs four different jobs, 0 of 256 situations ruling differently), the ranking law (which line first) and the SIGHT law (which file first — two tiers, where pointing evidence outranks circumstantial evidence algebraically).

Safety properties

  • Refuses on a green suite. Searching without a failing test has been measured to corrupt working code while reporting success; repair() checks first and returns "nothing to repair".
  • Refuses outside its vocabulary. and/or confusion, flipped booleans, *// swaps have no act — the mask comes back empty and fluidfix says so, loudly, instead of guessing.
  • Restores byte-exactly on failure. Every rejected candidate is rolled back; a refused repair leaves the tree untouched.
  • Bounded candidates. A candidate that will not terminate is a failed candidate, not a hung pipeline.
  • The oracle is defended. Stale-bytecode, plugin-collision, exit-first-swallows-coverage, and truncated-node-id failure classes are all encoded in oracle.py, each one a scar from a measured harness defect.

Teaching it new classes — the maintenance loop

The four shipped acts are a starter dictionary, not a ceiling. A fault class is teachable the moment its repair can be expressed as a mechanical transform of the defective line:

import re
from fluidfix import register

register(4, "logic-flip", 'an "and" that should be "or", or vice versa',
         re.compile(r"\b(?:and|or)\b"),
         lambda line, obs: (line.replace(" or ", " and ", 1) if " or " in line
                            else line.replace(" and ", " or ", 1)))

One registration, once — the router is never edited: it infers the new class's act code from the same single worked example (tests/test_regressions.py shows an and/or bug going from refused to repaired with exactly this snippet). That is the deployment story fluidfix is built for: ship it on a maintained codebase, let the known classes repair themselves for free, and when an update introduces a novel fault class, hand that class to fluidfix once and maintenance is free again.

The honest boundary: classes whose repair needs information absent from the defective line — a wrong variable, a missing guard, a different algorithm — are not transforms, and are refused rather than attempted. (Measured share of real one-line fixes that are single-token substitutions: ~16%; see fluid-router's benchmark/domain/.) The refusal is your signal to spend a frontier model exactly once, on the class, never again on its instances.

Teach it your bugs

docs/TEACHING.md is the full guide: how to turn a refusal into a registered fault class, what makes a transform safe, and how the router infers the new act from one worked example. examples/company_rules.py is a ready-to-adapt dictionary of registrations to copy into your own deployment.

Licensing

AGPL-3.0-or-later. Section 13 (network use) applies. If AGPL does not suit your use — proprietary products, SaaS without source offer — commercial licenses are available: see COMMERCIAL.md.

Metadata

Release files for fluidfix 0.15.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fluidfix 0.15.0
File Size Uploaded Provenance
fluidfix-0.15.0.tar.gz 9.3 MB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fluidfix 0.15.0
File Interpreter ABI Platform
fluidfix-0.15.0-py3-none-any.whl Python 3 none any Details

Total release size: 9.4 MB

Release files / fluidfix-0.15.0.tar.gz

Download URL fluidfix-0.15.0.tar.gz
Size 9.3 MB
Tags Source
SHA-256 checksum
How to use checksums
fc6e23fdbf7701c1a7d97ace55970d1522980db0717fb2fbff68e55b2be155de
BLAKE2b-256 checksum
How to use checksums
e239e6129516660643ca18a7f3521e525e2a5a1a4b5d552f1df176dc931a7fe9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / fluidfix-0.15.0-py3-none-any.whl

Download URL fluidfix-0.15.0-py3-none-any.whl
Size 112.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
293dd62a69dd4e42bf741ff68ceac9393b7da3c56206e0aafc2460347f755c27
BLAKE2b-256 checksum
How to use checksums
e0c24dedc4d5e7404c0b46ff30f9ee9b5d23998374bdb68c3870ef454b788181
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Security for fluidfix 0.15.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for fluidfix-0.15.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page