Skip to content

Flywheel 1.0.4

Choose a tag to compare

@HarperZ9 HarperZ9 released this 26 Sep 01:50
· 280 commits to main since this release
5d8b89d

Flywheel 1.0.4

A self-hostable, model-agnostic AI workstation and coding harness. Flywheel runs a task
with any model, frontier or local, behind one OpenAI-compatible surface, and your keys and
data stay on your machine. An answer is accepted only when a real check passes, such as a
test run or a Lean proof. Each accepted answer carries a sealed receipt, and the witness
re-runs that receipt offline to return MATCH, DRIFT, or UNVERIFIABLE.

Correction, 2026-09-26: the opening says keys and data stay on your machine. Your keys
are stored only on your machine and sent only to their own provider; Flywheel's records
stay on your machine. The content of each request goes to the hosted provider you route
it to.

1.0.4 brings the Windows installer level with a pip install and closes three security gaps
in how Flywheel starts its lanes and its local agent. It also makes flywheel --version
print the version. One change needs action from some users: a lane that reads a provider
key now needs that key granted to it by name (see Upgrade).

What 1.0.4 fixes

  • The installer bundles the current lanes (#296). The 1.0.3 installer bundled older code
    than a pip install for six lanes. The frozen app now carries the versions the lane
    registry pins: chorus 0.3.1, relay 0.2.5, plexus 0.2.2, mneme 0.4.2, canon 0.2.0 and
    accountable-surface 0.3.1. gather 1.8.2, crucible 1.2.0, index 2.13.0 and forum 1.14.0
    were already current.
  • Lanes start with a minimal environment (#295). Every pip or npm lane used to inherit
    the gateway's whole environment, so a provider API key exported for the gateway reached
    every lane process. A lane now starts with a base set (PATH, system and temp
    directories, locale, CA bundles, FLYWHEEL_HOME and workspace roots), the non-secret
    variables it declares, and any variable you grant it by name with env_allow in
    lanes.json. Proxy variables also need a grant, because a proxy URL can carry a user
    name and password.
  • The local agent takes its authority from you (#295). local_agent_run read
    allow_write, allow_exec and root from the tool call, so a model could grant itself
    exec or point file tools anywhere, and the string "false" counted as true. Grants now
    come from how you start the server (--allow-write, --allow-exec, --allow-online,
    --root, or the matching FLYWHEEL_LOCAL_AGENT_* variables). A tool argument can only
    narrow them. A root outside the workspace, a root that is your home directory, and a
    root that contains or sits inside FLYWHEEL_HOME are refused before any agent step runs.
    When the gateway launches the bundled local-model lane, it confines the agent to its
    own --root.
  • The gateway token and the receipt signing key are unreadable from the Windows sandbox
    (#295). A sandboxed agent command could open ~/.flywheel/gateway.token. Both files now
    carry a medium mandatory label that the low-integrity sandbox cannot read, applied every
    time the gateway loads them. On macOS and Linux the sandbox's credential denylist now
    hides the token and the signing key, including under a custom FLYWHEEL_HOME.
  • flywheel --version prints the version (#296). It used to print a usage error.

A correction to the 1.0.3 notes

The 1.0.3 notes said the 1.0.2 installer build stopped at a version check. They did not
say that 5 of the 31 automated checks on the 1.0.2 release commit had failed: two
whole-suite test shards, both Flutter builds and the installer build. 1.0.2 went to the
Python Package Index with those failures. The cause was the version declaration that
#281 fixed in 1.0.3.

Upgrade

  • Engine: pip install -U flywheel-verify
  • Desktop app: the Windows installer (Flywheel-Setup-1.0.4-x64.exe) is attached below.
  • If a lane needs a provider key, grant it by name in lanes.json, for example
    "env_allow": ["ANTHROPIC_API_KEY"] on the forum or accountable-surface row. forum,
    accountable-surface, relay's online route, mneme's extraction and gather's credentialed
    sources need this for real model runs. The "Lane environment" section of
    docs/lane-runtime-selection.md lists each lane's variables.
  • To let the local agent write, run commands or go online, start its server with the
    matching flag, for example
    python -m harness.local_agent_cli --mcp --root /path/to/project --allow-write, or set
    the matching FLYWHEEL_LOCAL_AGENT_* variable. Every grant is off by default.

Limits

  • Lanes still run outside any sandbox, as your user. A lane can read the gateway token
    and the signing key, and can edit lanes.json to grant itself a variable on its next
    start. Closing this needs a filesystem boundary for lanes.
  • On Windows the sandbox can still read other credential files, such as .ssh, .aws
    and .npmrc, and it can still reach loopback. With the token unreadable, a loopback
    connection alone carries no gateway authority for a sandboxed command.
  • relay's own local_agent_run tool still reads its grants from tool arguments. The
    gateway's local agent is fixed; relay's needs its own release.
  • The bundled accountable-surface 0.3.1 runs with the coherence-membrane and
    proof-surface copies the desktop runtime already ships, not with versions a pip install
    resolves.
  • The limits listed for 1.0.3 on the verifier still hold: code inside the pytest process
    can forge its own report, the workdir restore does not undo writes outside the workdir,
    the math oracle does not bind a proof to the task's theorem, and a def built on an
    axiom a metaprogram added can still pass.
  • On the shipped benchmark the verified loop shows no measured accuracy uplift over
    single-shot. The interval includes zero.
  • A receipt proves a check reproduces. It does not prove the answer is true of the world.

Known issues (added 28 September 2026): the Windows app's lanes

The 1.0.4 notes describe the Windows installer's lanes more strongly than the
installed app delivered. We rebuilt the 1.0.4 engine from its release tag with the
release's own freeze steps and ran it the way a fresh machine would: no Python, no
Node and no lane packages on the PATH, and a throwaway profile. This page corrects
six statements about the installed Windows app; the engine you get from
pip install flywheel-verify is not affected by those. It also names the lane
advisories that cover the lane releases 1.0.4 pins: canon 0.2.0's and crucible 1.2.0's,
in both the app and a pip install, and gather's, relay's, forum's and learn's, in a pip install.
It also corrects what the notes say about where your data goes, for both installs.

What the notes said, and what we measured

"1.0.4 brings the Windows installer level with a pip install." It did not
for lanes. In the 1.0.4 app engine, rebuilt from its tag and run the way the app
starts it, one lane, bulletin, ran its main read actions. Nine bundled lanes (gather,
crucible, chorus, index, plexus, mneme, canon, relay and accountable-surface) answered
only their status and doctor tools (relay answered relay.status only) and refused
every other tool with CAPABILITY_NOT_ADMITTED. forum, local-model and writing did not
start. articulate, calibrate-pro, learn and telos were not in the installer. On the
same machine, every lane that a pip install or a source checkout started answered its
health tool and read tools with a real result.

"The installer bundles the current lanes," including forum 1.14.0. forum 1.14.0
is in the installer, but the bundled forum process exits as it starts, because the
build left out the data file that holds its default roster. The 1.0.4 release check
counted that exit as a pass. Its receipt records forum's exit code as 1 next to an
overall result of PASS.

"A lane now starts with a base set ... and any variable you grant it by name with
env_allow in lanes.json."
This holds for lanes that run from pip or npm. The
ten lanes bundled inside the Windows app start with a fixed set of eleven system
variables. A variable you grant with env_allow does not reach them, and
neither do FLYWHEEL_HOME or a lane's own declared settings. A key saved in the
app's Keys panel reaches no lane. The Upgrade step that says to add
"env_allow": ["ANTHROPIC_API_KEY"] to the forum or accountable-surface row has no
effect in the app.

"When the gateway launches the bundled local-model lane, it confines the agent to
its own --root."
The confinement itself is in 1.0.4, but the 1.0.4 app never
used it. The app started the local-model lane as python -m harness.local_mcp and
the writing lane as python -m harness.writing_mcp, found through your PATH. On a
machine with no Python, neither lane starts. On a machine whose python has an
older flywheel-verify, the app runs that older local agent, which predates the 1.0.4
grant fix. The last point is inferred from version order; we measured the launch
command and saw the app pick up a 0.3.5 install, but did not run that agent against
the grant cases.

README: "About fifteen composable lanes ship in the roster, ten of them bundled
natively from source."
Ten lanes are bundled from source. In the 1.0.4 app, nine
of them answer a health check only and the tenth, forum, does not start, so the
sentence reads as more than the app delivers.

"The frozen app now carries the versions the lane registry pins," with index 2.13.0
"already current."
The 1.0.4 app, like the 1.0.3 app, bundled index 2.13.0 plus one
later commit, a bounded context-envelope output in four source files. No index release
held that commit until 2.14.0, which Flywheel 1.1.0 pins. A pip install of 1.0.4 got
index 2.13.0 from PyPI, as the registry pins.

"... your keys and data stay on your machine." The 1.0.4 notes open with this.

Correction, 2026-09-26: Flywheel's records and your keys stay on your machine, and each
key is sent only to its own provider. The content of each request, including files and
tool output the agent reads, goes to the model provider you route it to, under that
provider's terms. With a local model it stays on your machine.

canon 0.2.0, which 1.0.4 ships, is inside the range of GHSA-48rq-xjfx-6j4f.
Its shared context store keeps an ingested event as sent, secret-shaped values
included, returns query excerpts and pending references without scrubbing them, and
lists recorded transcript paths, which then reach the next prompt your client sends
to its model provider. canon 0.4.2 fixes this, and Flywheel 1.1.0 pins it.

crucible 1.2.0, which 1.0.4 pins, is inside the range of GHSA-49qx-cj4f-wfqv.
In the 1.0.4 app its status and doctor answers read MATCH without measuring anything,
and a pip install runs assess, where a measurement file can widen the tolerance that
decides MATCH. crucible 1.3.0 fixes both, and Flywheel 1.1.0 pins it.

gather 1.8.2, relay 0.2.5 and forum 1.14.0, which 1.0.4 pins, are inside eight lane
advisories.
gather: GHSA-pxvv-rg3f-4v5w, GHSA-r4f3-9xrf-72m5, GHSA-j6j7-39vh-qrp4
and GHSA-r38f-cr69-jpp8 (tool arguments that run commands, send secrets or reach a
network share, and programs planted in the working folder). relay: GHSA-phjr-6qrc-39mw,
GHSA-xxcc-grhg-v9g7 and GHSA-82fg-qprm-q5r7 (session files outside the store, planted
CLI binaries and PATH entries, provider keys in shell children). forum:
GHSA-36gv-h885-fmjf (approvals not tied to a raised gate, command executors given the
working folder and the whole environment, an open local daemon).

In the 1.0.4 app, gather and relay answer only status and doctor and forum does not
start, so the affected tools do not run there. A pip install of 1.0.4 runs them.
Flywheel 1.1.0 pins gather 2.0.0, relay 0.5.0 and forum 1.15.1.

learn 1.6.0, which 1.0.4's lane registry pins, is inside two advisories published on
27 September.
GHSA-2cf9-7hp2-ffh7: learn's MCP tools could read and write files outside
its folder, and learn resume submitted and paid without the opt-in. GHSA-wq39-vc75-wxcr:
learn started peer commands in the folder it ran in, so a Python package planted there
could run. The 1.0.4 app does not ship learn. On a pip install, flywheel install learn
installs the newest learn, so one installed before learn 2.0.0 came out on 27 September
is 1.6.0 or older; npm ls -g @harperz9/learn shows which. learn 2.0.0 fixes both.
Flywheel 1.1.0 pins learn 2.0.0.

If you run 1.0.4 today

  • For lane work, use the engine from pip: python -m pip install -U flywheel-verify,
    then flywheel lanes --probe to see which lanes answer. Lane keys granted with
    env_allow work there.
  • In the Windows app, read a lane's "live" status as "the lane answers its health
    check", not as "its main action runs".
  • Do not send secrets through the context capture route on 1.0.4. If you did,
    treat the context database as holding them until you upgrade and purge it with
    canon 0.4.2.
  • Read crucible's status and doctor MATCH as a capability probe, never as a verdict.
    Before you trust a MATCH from crucible's assess on 1.0.4, compare each measurement's
    tolerance with the one you registered.
  • On a pip install, move to Flywheel 1.1.0 for the fixed gather, relay, forum and
    crucible.
    Upgrading relay alone on 1.0.4 stops that lane: 1.0.4 starts relay as
    python -m relay.local_mcp --mcp, which relay 0.3.0 and later refuse.
  • If you installed learn, upgrade to learn 2.0.0. Until then, follow the workarounds
    in GHSA-2cf9-7hp2-ffh7 and GHSA-wq39-vc75-wxcr: run learn assist and learn visualize
    from a folder you control, and do not run learn resume --native on a workflow with
    a submit or cost step.
  • If Python is on your PATH and you use the app's local-model or writing lane, make
    sure that Python has flywheel-verify 1.0.4, because the app runs that copy:
    python -m pip install -U flywheel-verify.

What 1.1.0 changes

Flywheel 1.1.0 rebuilds how the app runs lanes: each lane's main tools are admitted
under a reviewed policy, local-model and writing run inside the bundled engine, forum
ships its data files, articulate, calibrate-pro and learn join the installer with a
bundled Node runtime, and each lane card states its setup. Its notes list what an
installed-app check measured for every lane, including the lanes still below that bar.