Skip to content

Prepare FreeOS 0.1.0 runtime and distribution fixes - #107

Draft
XYAIStudio wants to merge 9 commits into
developfrom
codex/freeos-0.1.0-upstream-foundation
Draft

XYAIStudio wants to merge 9 commits into
developfrom
codex/freeos-0.1.0-upstream-foundation

Conversation

@XYAIStudio

@XYAIStudio XYAIStudio commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

Prepare FreeOS 0.1.0 with safer SQLite restart, user-controlled Ollama discovery, malformed-config preservation and cleanup of stale system messages before model calls. Align Python/runtime version metadata and route FreeOS distribution through GitHub Releases without publishing the Octop-compatible package name to PyPI.

Validation so far: backend 3,611 passed / 117 skipped; frontend 1,075 passed; Ruff, mypy, frontend lint/typecheck/format checks and production build passed. The 0.1.0 wheel and sdist have been built and the embedded dashboard/version metadata verified.

This is the development integration PR. Packaged runtime, native desktop and security acceptance are in progress; do not publish a stable release until those checks are complete. v0.0.10 remains available until the replacement release and its assets are verified.

Prepare FreeOS 0.1.0. Distribution stays on GitHub Releases. This remains a draft.

b2f69645

  • READMEs and the user guide no longer recommend the Tencent COS …/octop/install.* URLs. Those scripts install upstream PyPI octop, not FreeOS.
  • Primary install path is GitHub Releases FreeOS-desktop-*. CLI/source installs use raw.githubusercontent.com/XYAIStudio/FreeOS/develop/scripts/install.* or a local scripts/install.sh. Release notes can pin a tag after one exists.
  • New installs use ~/.freeos. scripts/install.sh, install.ps1, and install.bat follow PathLayout: FREEOS_HOME, OCTOP_HOME, existing ~/.freeos, existing ~/.octop when ~/.freeos is absent, otherwise ~/.freeos. The desktop app still does not adopt a leftover ~/.octop.

Earlier on this branch

  • 17bc806d: FnOS artifacts FreeOS-fnos-*, expired WeCom QR removed, npm audit bumps (vite 6.4.5, vitest 4.1.12, follow-redirects 1.16.1). Dashboard and organization jobs went green on that commit.
  • 65c5b560: distribution name freeos (freeos-0.1.0*.whl / .tar.gz); import package stays octop.

Still manual: G-02 packages, G-03 clean-VM, G-06 upgrade soak. CodeQL still runs only on main.

Open in Web Open in Cursor 

Theater-ahyeon and others added 9 commits October 3, 2026 23:22
* fix(update): checkpoint SQLite WAL before desktop process restart

In desktop/portable mode, POST /api/update/restart replaced the process
image with os.execv without flushing the SQLite WAL. Because SqlitePool
uses WAL mode with a large autocheckpoint window, all writes since the
last checkpoint were lost on restart (#800).

Change _restart_desktop_process to accept the OctopServer, and before
execv run PRAGMA wal_checkpoint(TRUNCATE) and close the pool when the
database is SQLite. The restart endpoint now injects the server via
Depends(get_server).

Fixes #800.

* style(tests): format desktop restart regression cases
… (#738)

* fix(config): never rewrite an unparseable config.json as empty (#730)

Four call sites read config.json, treated a parse failure as an empty dict and
wrote that back, destroying every other key. One trailing comma plus one
`octop run --port 8088` wiped 17 of 18 keys including the whole `database`
section; the next boot silently came up as a greenfield SQLite instance (fresh
setup-wizard password, zero warnings) while the PostgreSQL data sat unreachable.
Losing `bind_host` the same way is what makes #730's reporter unable to reach
the server from the LAN.

A torn write creates the same precondition with no user error: three of the four
sites wrote config.json with a bare write_text, so a crash / OOM / full disk
mid-write left invalid JSON that the next plugin toggle then wiped.

One shared policy in a new leaf helper, infra/utils/json_file.py:

  absent file            -> {} and write (first run, unchanged)
  valid JSON object      -> merge and write (unchanged)
  unparseable/non-object -> raise CONFIG_FILE_CORRUPT, write nothing

The error names the file and the parser line/column but never the contents,
which hold database credentials. Writes now go through write_json_atomic (temp +
os.replace, fd closed on every path, temp removed on failure) so no reader can
observe a torn file.

Sites: cli/commands/run.py (_save_configfile_overrides, plus
_load_configfile_overrides which used to fall back to launch defaults),
infra/agents/plugins/manager.py (_write_global_plugin_enabled = the dashboard
toggle), infra/setup/service.py (persist_bind_options),
infra/agents/plugins/seed.py. `octop run` / `octop service start` report the
error and exit 1 via fail_octop (now NoReturn) instead of a traceback.

Supersedes the pinned "treat a malformed file as empty so the next run rewrites
it cleanly" contract: its fixture (`{not valid json`) had nothing to lose, so
the test could not observe the destruction. Rewritten as
test_run_reports_corrupt_config_cleanly and
test_run_does_not_overwrite_corrupt_config.

Verified end-to-end against a real OctopServer + real PostgreSQL. Before: one
`octop run --port` flipped driver postgresql -> sqlite, the instance reverted to
the first-run wizard, and users=1/agents=1 were orphaned in PG with no warning.
After: exit 1, config.json byte-identical, boot fails loudly instead of
switching backends. Mutation check: restoring the lenient policy in the helper
reddens 9 tests spanning all four sites.

make all green (3299 passed, 16 skipped); mypy --strict clean; dashboard
`npx tsc --noEmit` clean.

* fix(config): name the file when config.json is corrupt (#730)

`load_config` let a bare `json.JSONDecodeError` escape: it reports a line and
column but never says *which* file failed, and this entry point is reached from
boot, backup and several CLI commands — not only `octop run`. Raise a ValueError
naming the path and the parser position, refuse a non-object document, and never
echo file contents (config.json holds database credentials).

Same policy as infra/utils/json_file.py, duplicated here because octop.config
must stay free of infra imports (AGENTS.md §5).

`octop run` already exits cleanly on a corrupt config through resolve_bind; this
covers the remaining entry points.

make all green (3301 passed, 16 skipped); mypy --strict clean.

* fix(config): preserve config.json permissions in atomic writes

Self-review against CONTRIBUTING.md / AGENTS.md §7 caught a regression in the
atomic writer added earlier in this branch: tempfile.mkstemp creates the temp
file 0600, so replacing config.json silently tightened an existing 0644 file to
0600. Under `octop service start --scope system` that runs as root and writes
into the service user's home, a root-owned 0600 config.json is unreadable by the
service user and the unit cannot start; the bare write_text it replaced produced
the umask default.

write_json_atomic now chmods the temp file to the mode of the file being
replaced, or to `0o666 & ~umask` for a new file — matching the two pre-existing
config.json writers (infra/db/rebind.py, infra/backup/auto.py; both
write_text + replace) rather than mkstemp's 0600. POSIX-guarded, so Windows
behaviour is unchanged and no test asserts mode bits off POSIX (AGENTS.md §7).

Also adds the missing CHANGELOG line for the load_config error-message change.

Verified: new file -> 0644, existing 0644 -> 0644, existing 0600 -> 0600.
make all green (3303 passed, 16 skipped); make typecheck-frontend green;
eslint 0 errors (67 pre-existing react-hooks warnings).

Note: `make check-all` is red on develop itself — prettier --check fails on
dashboard/src/pages/Agent/Skills/components/SkillsTabs.tsx exactly as committed
by 83378876. Left untouched here; confirmed pre-existing by checking develop's
version of that file in isolation.
Refresh the openXYOS lock so npm ci resolves on Node 24 and require Node >=22.12.
Wait for the SearchConfig source label before asserting it; that was the Node 24
dashboard failure while the spinner was still mounted.

Bind the organization sidecar to 127.0.0.1 from the server default and every
desktop launcher. Seed local accounts only under FREEOS_ORG_LOCAL_TEST, with a
random password stored beside the database and a forced change on first sign-in.
The UI no longer shows a shared demo password.

Mark rc/a/b/dev tags as GitHub prereleases in the release, desktop attach, and
FNOS attach workflows. Collapse the changelog to a single 0.1.0 section and
stop README_CN from directing installs at PyPI octop. Order desktop version
compare so a final release sorts above its rc.

Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Name new FnOS artifacts FreeOS-fnos-*.fpk in the workflow, build script,
release links, and user docs. Older Release assets may still be named
Octop-fnos-*.

Remove the expired WeCom QR from the user guide and README_CN. Readers
go to GitHub Discussions or the existing Discord link.

Bump vite to 6.4.5, vitest to 4.1.12, and follow-redirects to 1.16.1 so
Desktop Package npm audit exits 0.

Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
Set the distribution name to freeos so the wheel and sdist are freeos-0.1.0*.
The import package and the octop CLI alias stay. FnOS, portable packaging,
and release notes use the new filenames and say not to pip install octop.

User-facing paths in the docs this change touches name ~/.octop as the data
directory. FREEOS_HOME applies only when it is already set; this release
does not migrate that directory to ~/.freeos.

Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>
README and the user guide no longer recommend the Tencent COS
octop/install URLs. Those scripts install PyPI octop. Desktop packages
on GitHub Releases are the primary install path; CLI installs use this
repo's develop scripts.

New installs use ~/.freeos. install.sh, install.ps1, and install.bat
follow PathLayout: FREEOS_HOME, OCTOP_HOME, an existing ~/.freeos, an
existing ~/.octop when ~/.freeos is absent, otherwise ~/.freeos. The
desktop app still does not adopt a leftover ~/.octop.

Co-authored-by: haoboy007-sudo <haoboy007-sudo@users.noreply.github.com>

This branch has not been deployed

No deployments
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.

4 participants