Skip to content

Latest commit

 

History

1,342 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Flywheel: run an AI task with any model, keep a record you can recheck offline.

Run an AI task with any model. Keep a record you can recheck offline.

PyPI license CI downloads python: 3.11+ deps: none (core)

Flywheel runs an AI task with the local or hosted model and tools you choose. It records the run, and optional sealed tool-call receipts can be inspected and rechecked offline. The repository also includes a native desktop app.

Flywheel has two parts. The Python engine routes tasks, checks tool requests, runs verification, writes the run ledger, and serves a local gateway. The Flutter client provides the native desktop interface.

Project Telos | gather | crucible | index | forum | telos | learn | relay | mneme

Try it

For the native desktop app, download the Windows installer from Releases. It carries its own engine, so the app runs on a clean machine with no Python installed, and it starts that engine itself.

For the engine on its own:

python -m pip install flywheel-verify
flywheel up

This starts the local API gateway on http://127.0.0.1:8799 and serves a browser shell there. The shell is the fallback surface for development and CI; the desktop app is the native one.

For a workflow you can use in an existing agent host, see the Flywheel Evidence Task skill. It can be installed independently of the engine and includes Codex and Claude plugin manifests, examples, and reproducible download packaging.

How a run works

One task, from the moment you send it to the point where somebody who was not there can check it. Every stage writes a receipt, and the last stage needs no network and no model.

Eight stages: a task is routed to a model, the model asks for a tool, the capability check either allows it or refuses it with the reason returned to the model, the tool runs, a receipt is written, the ledger is sealed, and a later recheck reports match, changed, or unverifiable.

The refusal edge is the one worth reading twice. A blocked tool request is not an error the run dies on: the reason goes back to the model, which can pick a different route. What the ledger keeps is the request, the refusal, and the reason, so a reader later can see what was asked for as well as what ran.

What the capability check decides

Stage four reads a shell command the way a shell reads it, then names what the command is able to do. That name settles the decision. Seven commands are below with the reason each one lands where it does.

Seven shell commands and what the capability check does with each of them. A dangerous word inside quotes is a printed string and runs, while the same word reached through a command substitution is found and blocked. A pipe records both of its capability classes even though one of them names the decision. An environment prefix does not hide the executable behind it. A command that will not parse is escalated to a person rather than admitted. The marked row is the honest gap: an executable the curated map has never seen is admitted, and written down as unknown.

A denied word matters only in the executable position, so quoted text prints and a substitution gets walked into. The marked row is the gap this repository does not paper over: the map of names is curated by hand, and an executable it has never seen is admitted, then written down as unknown.

Verification record

The review for pull request #60 records the checks for this README change:

  • The file-size, standard-library verifier, claim-language, public-instruction, and writing gates passed.
  • python -m harness.cli_entry gate returned PASS and an offline recheck of MATCH.
  • GitHub Actions ran the whole test suite on Ubuntu and Windows. The linked CI checks are the source of record; this README does not freeze a test count that can change by revision or platform.

These checks cover the repository's deterministic code and documentation paths. They do not prove that a model answer is correct, measure live provider reliability, or test every host and hardware configuration.

Benchmarks

7 suites run with no model endpoint and no network, so you get these numbers back on your own machine:

python scripts/run_offline_benchmarks.py
suite what it answers headline
accountability does an unaccountable system score badly here dimensions 8; harness_overall 1.0; separation 0.99; strawman_overall 0.01
governed-agent does a workflow refuse an action above its tier failed 0; mean_quality_score 0.542; pass_rate 1.0; passed 6; scenarios 6
agent-recovery does an injected fault recover without failing quietly receipt_completeness 1.0; recovery_success_rate 1.0; scenarios 6; silent_failure_rate 0.0
stateful-provider-swap does state survive a provider swap checks 10; pass_rate 1.0; passed True
source-mined do the mined checks still hold against their datasets cases 26; failed 0; metrics_asserted 170; pass_rate 1.0; passed 26
paired-replication did continued pretraining change general code completion delta_points -0.0305; gains 9; p_exact 0.4049; regressions 14; tasks 164
receipting-cost what does it cost to keep the receipt durability_share 0.9282; log_bytes_per_action 788.3; ms_per_witnessed_action 7.18; recheck_us_per_record 12.8; verdict MATCH

The strawman, a system with no receipts, scores 1% on the same axes. A benchmark that everything passes measures nothing.

Against 5 named peers (codex, cursor, claude code, hermes, omp): 48 capabilities, 48 witnessed in this repository by a check that runs every time the matrix is read, and 10 that every peer was read on and none declares. 9 rows carry at least one peer surface nobody here has read, and a star is withheld from every one of them, so the starred count moves up as the reading is done and not before. The peer columns are dated readings of public documentation and public source, not measurements taken here.

Full results, the matrix, and the measurements that were not taken: docs/BENCHMARKS.md.

One of those suites recomputes the project's only capability comparison, and it is negative: continued pretraining on the workspace corpus moved general code completion -3.05 percentage points over 164 tasks, p = 0.40. It is here because a negative result published is worth more than a positive one withheld.

The arms benchmark is a separate instrument, retired on 2026-07-26. The arms were not independent: the treatment's first attempt is the same call as the baseline's only attempt, so the treatment cannot score lower and the difference is not a comparison. The quantity measured is verified pass@k. The retired table read verified inference 9/10 against single-shot 8/10, difference +0.100 with 95% CI [-0.236, +0.420], an interval that includes zero, and no capability uplift is claimed.

For the distinction between retry diagnostics and evidence of workflow uplift, see the evaluation guide.

What is in this repo

The browser shell, the command line, curl and MCP clients all reach one gateway on localhost, which routes to a local model or an external check and writes a receipt either way, escalating only what does not pass.

This monorepo contains both halves of the platform:

  • harness/ is the Python engine. It runs tasks, checks tool requests, writes receipts, discovers companion tools, and exposes the localhost API. The installed runtime uses only the Python standard library.
  • desktop/ is the Flutter client. It talks to the gateway over localhost and can launch the bundled engine on a Windows machine without a separate Python installation.
  • site/ is the browser fallback used in development and CI.

To run the native client from a development checkout:

cd desktop
flutter run -d windows --release

From a repository checkout, python -m harness.cli_entry app --port 8799 also serves the development and CI fallback at /site/index.html.

Included tools

Flywheel can connect to fourteen companion tools. Each has a public repository:

Tool Repository What it does
gather gather Collect research and record its sources.
crucible crucible Recheck a claim and report a match, change, or missing evidence.
index index Map files and symbols in a workspace.
forum forum Route work among models and record decisions.
learn learn Turn your material and recorded attempts into a study plan.
telos telos Reconcile findings from several tools.
local-model archived predecessor Historical engine repository. Its runtime is now part of Flywheel; the lane name remains for compatibility.
relay relay Run a coding agent with a local or hosted model.
plexus plexus Find installed tools and connect them.
mneme mneme Store and retrieve memories with source checks.
calibrate-pro calibrate-pro Check display calibration targets and readiness.
accountable-surface accountable-surface Require approval before actions and keep a tamper-evident record.
canon canon Keep one set of instructions and memories across the assistants you use, and see what each one would be given.
bulletin bulletin Reach an open message board where agents post, search, and reply under a signed identity. Watch it live.

List their configured state or probe their live MCP connections:

flywheel lanes
flywheel lanes --probe    # live MCP handshake per lane

Watch the board

One of those tools runs in public. The bulletin board is live at https://harperz9.github.io/bulletin.html, and opening it needs no key and no account: you see the rooms, the feed, and each thread as agents post, search, reply, and coordinate.

Anyone can join the conversation rather than only read it. The board checks an Ed25519 signature and never asks what produced it, so a person holding a key posts into the same rooms and under the same tier limits as an agent. The client is one file with no dependencies; it generates your key, solves the proof of work, and registers you.

What the board holds is public and untrusted. A post is text somebody else wrote, and every read response says so in the same words. Read it as data.

Run records and sealed receipts

A local model proposes, an external check disposes, and the pair is written to a content-addressed receipt; a pass goes to the proof cache and anything that does not pass escalates.

Routed runs keep a ledger containing tool names, arguments, and outputs. When sealed tool-call receipts are enabled, they also record:

  • the capability (builtin-read, builtin-write, builtin-exec, external-mcp, or unknown);
  • the outcome;
  • argument and output hashes;
  • the prior receipt's hash for offline verification.

Optional sealed receipts form an ordered hash chain. If one receipt is invalid, later entries in that chain become unverifiable.

Checking an answer before it ships

An assistant that rechecks its own arithmetic gets the same wrong number twice. So Flywheel checks a value against the source that decides it, and reports three outcomes rather than two: the value agrees and the answer names its source, the value disagrees, or nothing could confirm it.

flywheel check-output --contract task.contract.json --answer answer.json --allow-commands

Exit 0 confirmed, exit 1 disagrees, exit 3 unchecked. An unchecked value never reads as a confirmed one. The report also says whether the answer may ship: RELEASE, RELEASE_WITH_CAVEAT, or HOLD with the fields that blocked it. Inside a lane, a held answer does not accept.

Tax was the example. Finance, medicine, and law each ship a pack of field templates for the values that go wrong the same way: a dose banded by a formulary rather than computed, a deadline counted in calendar days where the rule counts court days, an amount carried to two decimals in a currency that has none.

flywheel packs medicine

A pack ships field shapes and arithmetic and no domain data. The authorities stay yours to supply.

The answer can arrive as the document it was written in, and the report goes back out as one:

flywheel check-output --contract c.json --answer memo.md --report review.pdf

Markdown, LaTeX, and PDF all carry an answer. The report is written to whichever of .txt, .md, .tex, .pdf, or .json the suffix names, and the PDF is byte-identical across runs so it can be hashed into a receipt.

--lean Answer.lean --verify-lean emits the check as a Lean 4 file and runs the kernel on it. What the kernel settles becomes a theorem, what an outside authority decided becomes a named axiom, and one #print axioms line prints everything the result rests on. A kernel that refuses an obligation the report passed lands on the exit code.

See docs/OUTPUT-VALIDATION.md for the contract format, the checker protocol, and the retry loop, docs/PROOF-AND-FORMATS.md for the document formats and the proof, and docs/CRITICAL-DOMAINS.md for the packs and the failure classes they catch.

What landed recently

Four capabilities added since the last release, each reachable from the desktop app and over the localhost API.

A signature on what a run cites. A hash binds a receipt to its own contents and cannot bind it to an author, so an editor who rewrites a whole citation cone leaves a store that is internally consistent about a history that did not happen. harness/grounding_signatures.py reads an Ed25519 sidecar filed beside a receipt and answers with a reason. Absent and invalid stay separate facts, so a partial rollout does not read as an attack. Left unconfigured, an unsigned store behaves exactly as before.

Scheduled runs, with the occurrence as the unit. A tick is a pull rather than a daemon: nothing runs unless something asks. Each schedule names its catch-up policy by name, so a machine that was asleep for six hours either fires every missed occurrence, fires the most recent one, or drops them, and you can read which. The fires form a hash chain, and a broken chain is printed as broken instead of folded into a green count.

A code scan that seals what it covered. A scan that found nothing and a scan that looked at nothing print the same number. This one records three things beside the count: how many files were read out of how many exist, whether the ruleset still fires, and how many findings were suppressed. A broken chain refuses the run and returns the reason rather than a status code.

Every live route reachable from the app. A coverage gate walks the gateway's dispatch table and the Flutter source, and fails when a route the engine serves has no way in from the client. It reads 152 of 152 today, and the gate fails on an unclaimed gain as well as a loss.

Lessons from recorded failures

A proposed lesson includes hashes of its evidence and remains a proposal until a person accepts it. Verification detects changes to the lesson's sealed claim and evidence hashes. The originating system must separately recheck whether referenced evidence still exists or has changed. See docs/LESSON-LOOP.md.

Offline-first

The Flutter desktop GUI launches a bundled engine by absolute path and serves its UI menu on localhost only. No external web address is contacted to show the GUI. The gateway serves /api/* and the UI on http://127.0.0.1:8799.

Install

pip install flywheel-verify
flywheel up

flywheel-verify is the PyPI distribution name (the bare flywheel name is an unrelated package); the installed command is flywheel. Zero runtime dependencies, stdlib only.

No model download required. The engine is ready for real work the moment it installs: point it at any hosted provider you hold a key for (the roster reports credential presence only, never values) and every route carries the same receipt discipline. Local models get the same support and stay optional: ollama needs no extras at all (the gateway talks to it over HTTP), the published 14B and 32B weights are separate downloads for when you want them, and the local HF serve/training stack installs with pip install "flywheel-verify[local]". Receipt signing and egress monitoring have their own extras ([signing], [monitor]); receipt verification stays stdlib-only.

Subscription sign-in is wired in: flywheel auth login <provider> runs a stepwise flow (documented PKCE where the provider sanctions it, the provider's own official tool where it does not), stores the token in the OS credential store, and the router picks it up with no further setup. See GETTING-STARTED.md.

Or from source:

git clone https://github.com/HarperZ9/flywheel.git
cd flywheel
pip install -e .
python scripts/run_harness_cli.py app --port 8799

The native desktop app ships as a Windows installer with the engine bundled (no Python needed): download Flywheel-Setup-<version>-x64.exe from the releases page and verify it against the release's SHA256SUMS.txt.

Documentation

Development disclosure

Zain Dana Harper maintains this repository. AI-assisted tools are used for parts of development and documentation. Public source, tests, benchmark artifacts, and releases are the evidence for what ships; AI output is not treated as proof.

License

FSL-1.1-MIT (Functional Source License). See LICENSE.

About

The one platform: engine + native desktop client for accountable AI infrastructure. Verified-inference loop, receipt-wrapped agent tool calls, lane composition (gather, crucible, index, forum, learn, telos). Offline-first. FSL-1.1-MIT.

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages