Imported from XiXiphus/BilineIME (
AGENTS.md). Install upstream withnpx skills add XiXiphus/BilineIME. Copyright stays with the author.
Repo Instructions
Product invariants
- Keep the Chinese IME core as the primary system. Bilingual preview and English-layer commit are optional overlays and never own Chinese ranking, paging, parsing, or composition state.
- Treat raw pinyin cursor editing as IME composition state, not host text editing. Raw keystrokes stay unspaced internally; parser-derived syllable or abbreviated-initial boundaries may appear in host marked text. Candidate mode renders candidates only. Raw-buffer-only is the sole panel fallback that may render raw input.
- While composing, consume modified editing keys inside the IME:
Option/Command+Left/Right,Option/Command+Backspace, and their Shift variants must not leak to the host. - Preserve the user's preferred candidate column across short rows and page boundaries. A short row may clamp the visible selection without overwriting that preference.
- Match Apple Chinese input behavior for uppercase Latin letters. While idle,
Shift+ASCII letterinserts uppercase Latin directly. While composing, it remains a literal segment inside the same composition, may be followed by more pinyin, participates in candidate display and commit, and never causes an implicit Chinese commit or mode switch. - Prefer the smallest correct change. Preserve the current state-machine shape unless a broader refactor removes repeated special cases or restores one of these invariants.
Local automation contract
- This checkout is a development machine. For in-scope development and verification, Codex may autonomously build, install the user-scope dev bundles, open apps, inspect and operate System Settings, add or select the dev input source, focus TextEdit, inject test keys, browse candidates, capture screenshots across displays, and restore the previous input source.
- Prefer stable programmatic controls in this order: package tests and direct
APIs,
bilinectl, then Computer Use for UI-only gaps. Do not duplicatebilinectllifecycle logic in ad-hoc shell or GUI scripts. - Keep routine reinstalls on the same stable app paths. Stage and verify every bundle before replacement; do not unregister the stable install, reset global LaunchServices, kill unrelated text agents, or erase input-source state as a normal update step.
- Use Computer Use interactively, from freshly observed accessibility or screen
state. Do not commit coordinate-based permission or onboarding automation to
the repository, and do not make installer
postinstallscripts click UI. - A permission or source-enrollment screen is a recoverable local setup state, not an automatic reason to stop. Open the relevant page, complete ordinary authorized UI steps when policy allows, re-check readiness, and continue.
- Never type, persist, echo, or script a password, recovery key, biometric approval, API secret, or other credential. Pause at an authentication field so the user can enter it. Do not use credentials mentioned in conversation as automation input.
- Preserve unrelated worktree changes and user data. Before host automation, inspect TextEdit state and use a blank disposable document. Never clear, close, or repurpose a document that may contain user content.
- Destructive reset, system-scope installation, reboot, logout, global LaunchServices reset, data purge, and permission expansion still require their normal explicit confirmation or handoff. Prefer the user-scope dev lane for routine work.
Verification for IME changes
If a change affects composition, punctuation, candidate browsing, active layer, marked text, candidate panel rendering, settings refresh, install flow, or any host-facing IME behavior, complete the full local verification ladder:
- Run focused package tests for the changed behavior.
- Run
make build-ime. - Run
make install-ime. - Run
bilinectl smoke-host dev --check. - If the source is not ready, use
bilinectl smoke-host dev --prepareplus Computer Use to complete the local UI setup, then repeat the readiness check. - Run
make smoke-ime-host SMOKE_SCENARIO=fulland inspect its telemetry and rendered candidate UI. Use a narrower scenario while iterating, but finish with every scenario affected by the change. - For performance-sensitive changes, also run the relevant package and host performance suites and compare against a recorded baseline.
Real-host automation rules:
TextEditis the first host. Other hosts add coverage; they do not replace the TextEdit baseline.bilinectl smoke-host dev --confirm/make smoke-ime-hostandbilinectl perf-host dev --confirm/make perf-ime-hostare the canonical deterministic key-injection and telemetry paths. They are local-only and never CI gates.- Computer Use may prepare or inspect the host, handle UI-only setup, and verify candidate rendering. Prefer the harness for repeatable key sequences and assertions.
- Run interactive host commands through
scripts/with-test-awake.sh(the Make targets already do this). Itscaffeinatedisplay/idle assertions and renewed user-active assertion are bound to the child command and must not be replaced by a detached daemon or an unrequested permanent power-setting change. - The harness must classify readiness before typing, retain evidence, and restore the previous input source and changed test configuration where possible. A failure must leave enough state and artifacts to reproduce it.
- Registry readiness and the globally selected TIS source are prerequisites,
not proof that the foreground host activated the controller. Success requires
a fresh snapshot emitted by one verified IME process and controller ID with
hostBundleID=com.apple.TextEdit; stale unified-log events never count. A navigation key is causal only after that controller emits a higher monotonickeyActionApplied.actionSequencefor the matching key and routed action. - On macOS 26, if TIS selection succeeds but TextEdit does not produce that handshake, first perform a Finder-to-TextEdit focus round trip and retry the same document. Treat logout as first-enrollment recovery only, and never jump straight to broad cache or LaunchServices resets.
- Attach only to one existing untitled, unmodified, blank TextEdit document. Verify the same process/document and frontmost text-area focus immediately before every injected key, then restore the original blank document, input source, and changed configuration or report cleanup failure explicitly.
Tests/remains CI-safe. Real-host automation stays underSources/bilinectl/; Computer Use orchestration remains an agent workflow, not a Swift Package test.- Multi-display candidate checks use Computer Use or OS-level screenshots of all relevant displays; they no longer default to asking the user to provide screenshots.
Report verification in two explicit layers:
- code/build verification
- real-host smoke and visual verification
Do not claim an IME-facing behavior change is complete when only package tests or a successful build are available. If a system prompt or authentication step blocks the host layer, report the exact completed layer and resume after the handoff instead of treating the build as final evidence.