Skip to content

Deliver the shared offline core and Omarchy Fcitx5 installation - #63

Open
nervouna wants to merge 21 commits into
mainfrom
portable-core
Open

nervouna wants to merge 21 commits into
mainfrom
portable-core

Conversation

@nervouna

@nervouna nervouna commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Scope

This brings the existing portable-core work onto main and adds the verified Omarchy installation path. The macOS input frontend still uses the Swift engine; its shared-core cutover is not part of this PR.

  • Use the shared Rust dictionary generator for production preparation and the existing macOS update worker, with one source catalog and target-native caches.
  • Port offline session policy, candidate ordering, settings, custom phrases, personal learning and backup/import. Keep the Swift comparison fixtures and expose the frontend C ABI.
  • Add the Fcitx5 frontend with preedit/candidates, commit delivery, focus/reset, sensitive-field handling, configuration and explicit personal-data import.
  • Build relocatable Linux directory packages with native resources, notices, corresponding sources and a checksum manifest.
  • Install immutable user-local releases without sudo or network access. Support upgrade, rollback, interrupted-operation recovery, restoration of a prior manual registration, and uninstall while keeping personal dictionaries and settings.
  • Fix issues found on the ARM64 device: portable SHA-256 commands, addon discovery, raw-Pinyin commits on focus loss, backup-path lifetime and phrase text in warnings.

Verification

On ARM64 Arch Linux/Omarchy, Hyprland and Fcitx5 5.1.23:

  • Native runtime tests, 291 ranking comparisons, target-native production preparation, the 21-sample initial/persisted learned baseline, engine/personal-data parity and C ABI consumers passed during the Omarchy bring-up.
  • The user confirmed that the installed input method works.
  • The managed package at dec1f3f built successfully. All 20 installer tests passed, including failure recovery and preservation of existing registrations and personal data.
  • A real-package exercise installed, upgraded to a test-only identity with the same binaries, rolled back, and uninstalled in temporary directories. Each switch loaded the addon on a private D-Bus and checked preedit/candidates, commits, focus, sensitive fields, configuration and backup import. Personal-data fixtures survived.
  • The live manual installation was upgraded, its original descriptors restored and compared byte-for-byte, then the managed package reinstalled. The desktop loaded the managed library/resources; US keyboard and Pinyin entries were retained. No automatic service restarts were reported.
  • ELF runtime paths are relative; the installed addon does not depend on checkout-local library paths.

Earlier macOS dictionary/engine parity and same-host performance results are recorded in #35. This iteration did not install or activate a macOS build. CI now includes the isolated Linux installer and frontend helper checks.

Deferred

Steam Deck validation was explicitly deferred by the user. KDE Plasma, Flatpak application compatibility and persistence across SteamOS updates remain unverified. This PR therefore does not close the Linux delivery issue. The macOS cutover stays in #37 for the next iteration.

Refs #32, #35, #36.

Rebasing onto main brought in the prepared context index (#60): the Swift
generator's `spelling` step wrote `pinyin_simp.context.bin`, but on this
branch that step runs the Rust CLI, so built resources lacked the index
and `IFContextRanker` could not start.

Port `IFContextRanker.buildIndex` to the dictionary crate and return it
from `spelling` beside the 32 schema files, so the build CLI, the Swift
update worker and the C ABI share one implementation. The Swift reference
export and recorded fixtures now carry the index hash; parity checks
compare its bytes against the retained Swift builder.

Also fold main's other changes into the moved pieces: drop the Sogou
source from the embedded catalog, split `IFDictionaryError` so the
standalone ranking reference still compiles, and point the corresponding-
source bundle at `Core/config/chinese-sources.json` and
`Core/scripts/resource-dependencies.sh`.

Refs #35
…baseline

Add `engine.rs`: `Engine` owns one runtime, the prepared context index and
Rime's native custom_phrase.txt; `InputSession` ports `IFEngine`'s ordering and
selection by displayed index, digit/Up/Down policy, preceding-text context,
candidate counts and input preferences applied by replacing schema nodes at a
composition boundary, ASCII mode, shared idle phrase reloads and commit text
preserved across a settings reload. Port `InputPreferences`, `CustomPhrase`
and the property-channel framing; load the prepared `pinyin_simp.context.bin`
in the ranker. The bridge gains input, highlight, commit, option, channel and
schema-patch entry points over Rime's public C API.

Quality recording stays outside the engine: an optional observer receives each
completed mutation with the displayed snapshots before and after, after the
policy lock is released.

`tests/parity.rs` runs on prepared production resources (`parity.sh`): all 21
quality-baseline samples reproduce `baseline.json`, including learning after a
runtime restart, and the ported Swift engine regressions pass for basic cases,
context ranking, custom phrases, input settings and ASCII boundaries.

Refs #35
…ust core

`Engine::personal_learning_entries`, `delete_personal_learning` and
`undo_personal_learning` port `EnginePersonalLearning.swift` over the same Lua
`learning_manage` channel. They run only at the idle boundary after Rime's
native undo window and carry a learning revision that commits, Backspace or
Delete, new sessions and invalidation supersede.

`personal.rs` defines the portable backup: it reads and writes the macOS
format-1 document, keeps the three user dictionaries, custom phrases, the
candidate count and input options, discloses skipped macOS-only preferences
and rejects unknown fields. Export snapshots closed dictionaries through the
existing native helper on a copy; import restores snapshots into staging, moves
the originals aside, installs the new databases and restores the originals on
any failure; `recover` finishes an interrupted import. Nothing runs while an
engine is initialized in the process.

The parity test trains on production resources, manages entries (busy,
conflict, delete, undo), exports and imports between isolated directories,
imports a macOS-format document with synthetic rows, and checks that rejected
snapshots leave every dictionary unchanged.

Refs #35
…ocol

Add `performance-baseline`, the Rust counterpart of the Swift headless capture,
and `performance.sh`, which runs five fresh release processes on prepared
production resources and prints the distributions beside the approved review
limits. Record a same-host comparison with the Swift engine in the README:
key latency matches, startup and peak RSS are lower, and every approved limit
holds.

Refs #35
Add src/abi.rs and include/inkflow_rime.h over Engine/InputSession:
engine and session lifetime, Rime keysym events, immutable snapshots with
UTF-8 byte offsets, token-identified selection and highlight, paging,
commit draining, preceding text, configuration (candidate count, input
option bitmask, custom phrases), ASCII mode and the mutation observer as
a C callback delivered outside the engine lock. Every export catches
panics, writes outputs only on success and reports a thread-local
message; handles have no thread affinity.

Build the crate as cdylib and staticlib beside the rlib. abi.sh compiles
tests/abi.c against the shared library: the fixture part drives the real
runtime lifetime and resource validation with the probe schema, the
production part needs prepared resources. test.sh runs the former and
parity.sh both.

Refs #36
Linux/fcitx5 holds a CMake project, addon and input-method descriptors,
and an InputMethodEngine that keeps one engine session per input
context. Keys reach the engine synchronously with Rime keysyms and
translated modifier masks; every mutation drains the commit exactly once
and rebuilds the preedit (client or panel) and candidate list from a
fresh snapshot using UTF-8 byte offsets. The candidate list routes
clicks, paging and cursor moves back through the ABI with the snapshot
they were shown from, so late actions on a superseded page are rejected.
Reset and focus changes clear the composition, switching input methods
commits it, password and sensitive contexts never compose, and
surrounding text is read only behind the client's capability when a
composition starts. Resource and user paths follow XDG.

bridge.h keeps the platform-independent helpers (paths, preedit layout,
modifiers, bounded preceding text) with a test that runs anywhere;
test.sh also compiles the addon syntax-only against an fcitx5 source
tree. The CMake build and runtime behavior are unverified until they run
on the Linux host, as the README states.

Refs #36
…ry point

Export the macOS backup document through the C ABI: ifr_backup_parse
validates a format-1 document and exposes its candidate count, input
options, phrases and the non-portable preferences it skips;
ifr_backup_import and ifr_personal_recover run personal::import and
recover, and refuse while any engine is initialized in the process.
Backup::from_json now reports a missing field as Incompatible instead of
panicking on the map index; the C consumer found it through the
catch_unwind boundary.

The Fcitx5 addon gains conf/inkflow.conf (candidates per page, the
fourteen input options under their macOS names, custom phrases as
code=text) applied to every live session and to sessions created on
first use, and an ImportBackup path consumed once: the addon destroys
every session and the engine, imports with rollback, writes the
backup's settings into the configuration and recreates the engine.

Refs #36
Use the available SHA-256 tool and an explicit addon library path for user-local installs. Prevent raw preedit commits on focus loss, retain the backup path while consuming an import request, and omit phrase text from warnings.

Add isolated installed-addon tests covering commits, focus, sensitive fields, configuration and backup import. Refs #36.
Stage relocatable native libraries, target resources, notices and corresponding sources. Install immutable releases with checksum verification, service-aware recovery, rollback, manual-registration restoration and data-preserving uninstall.

Add isolated installer and real-package lifecycle checks. Keep Steam Deck validation and the macOS cutover out of this iteration. Refs #36.
Record shutdown separately from file changes, retain partial manual registrations, and fsync installer updates before clearing recovery information. Reject packages with incomplete runtime resources and exercise persistent restoration failures.

Package the legacy dictionary from its pinned archive extraction and reject untracked source inputs. Refs #36.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T12:16:44.654968Z d7490e5 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d7490e5738

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Linux/fcitx5/src/engine.cpp
Comment thread Linux/fcitx5/src/engine.cpp
…oggle ASCII mode with standalone left Shift

- Run ifr_personal_recover before every engine start; if a pending import cannot be
  rolled back, keys pass through instead of Rime opening mixed dictionaries.
- A standalone left Shift press and release now calls ifr_session_toggle_ascii_mode,
  matching the macOS frontend; any other key or Ctrl/Alt/Super disarms it.
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.

1 participant