* feat(android): add Wear proxy protocol
Introduce a bounded, versioned phone/watch RPC contract and wire its test, lint, and build gates before either runtime endpoint lands.
Co-authored-by: Sebastian Schubotz <git@sibbl.de>
* test(android): lock Wear wire names
Cover every supported RPC method and event discriminator so phone and watch cannot silently drift.
Co-authored-by: Sebastian Schubotz <git@sibbl.net>
* fix(android): bound Wear JSON depth
Reject excessively nested Data Layer envelopes before kotlinx.serialization can recurse through them.
* fix(android): enforce Wear depth on encode
Keep outbound messages inside the same JSON nesting contract enforced by the decoder.
* fix(android): preflight Wear payload depth
Traverse arbitrary JSON payloads iteratively before serialization so deeply nested local trees fail safely.
---------
Co-authored-by: Sebastian Schubotz <git@sibbl.de>
Co-authored-by: Sebastian Schubotz <git@sibbl.net>
* fix(daemon): write Windows gateway launchers in encodings wscript/cmd can decode
gateway.vbs and gateway.cmd were written as UTF-8 without BOM, but
wscript.exe only reads .vbs as ANSI or UTF-16 LE with BOM and cmd.exe
reads .cmd in the console OEM code page, so installs under CJK profile
paths failed with "file not found" (#107416).
Write .vbs as UTF-16 LE with BOM, write non-ASCII .cmd content in the
system code page when it matches the console page (CJK/Thai locales),
and BOM-sniff plus code-page-fallback on read so launchers from older
installs keep parsing and migrate on refresh. The hidden .vbs launch
path originates from #95480, which addressed console visibility only.
* refactor(daemon): drop unused WindowsLauncherScriptFormat export
The type is only referenced by encodeWindowsLauncherScript's format
parameter within the module, so the export tripped check-deadcode-exports.
Keep it module-local.
* fix(daemon): mark code-page cmd launchers with their encoding for deterministic readback
Prepend an ASCII '@rem openclaw-launcher-encoding=<label>' line to code-page
.cmd launchers and decode by that marker instead of sniffing UTF-8. Some GBK
byte sequences are valid UTF-8 (隆 = C2 A1 reads as ¡), so the old sniff
silently corrupted readback and rejected valid paths; the marker makes decode
deterministic and drops the code-page probe (a PowerShell spawn) from the
frequent readScheduledTaskCommand poll path.
Also fix the representability guard for euc-kr: Node ICU decodes euc-kr as
KS X 1001 only, but Windows code page 949 is cp949/UHC, so the TextDecoder
cross-check false-rejected ~8,800 UHC extension syllables (똠 = 8C 63) that
iconv encodes and cmd.exe reads fine. Verify euc-kr via iconv's own cp949
round-trip; keep TextDecoder for the other five labels.
* fix(infra): write Windows restart helper scripts through the launcher encoder
The update-time restart helper wrote its temp .cmd as raw UTF-8 while
embedding the restart-log path, task name, and task script path, so a CJK
profile path or task name broke the same way as the gateway launchers
(#107416). Route the write through encodeWindowsLauncherScript: ASCII content
stays byte-identical UTF-8, CJK content gets the marked code-page encoding, and
an unrepresentable task name now fails the restart attempt cleanly instead of
writing a script cmd.exe would misread.
* chore(deps): minimize pnpm-lock delta for the iconv-lite promotion
Reset pnpm-lock.yaml to origin/main and re-add only the iconv-lite root
importer entry, dropping the unrelated @types/node peer-context flips and
audio-decode deprecation metadata that a mismatched-toolchain regeneration had
pulled in. The diff vs main is now the three-line importer entry only; the
version already resolves in main's tree via express -> body-parser/raw-body.
* refactor(windows): centralize launcher encoding
Co-authored-by: Jason Yao <wsyjh8@gmail.com>
* style(windows): format launcher encoding test
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
* refactor(plugin-sdk)!: delete the zero-consumer channel-ingress facade, AccessFacts projections, and dead dispatch aliases
* chore(plugin-sdk): refresh API baseline hash for the facade deletions
* fix(channels): drop dead AccessFacts field writes stranded by the facade deletion
* chore(plugin-sdk): refresh API baseline hash after rebase
User-facing name is now OpenClaw (the system speaks); internal code name is
system-agent. Gateway methods crestodian.* -> openclaw.chat/openclaw.setup.*,
agent tool -> openclaw, reserved agent ids openclaw + retired crestodian.
openclaw setup routes: onboarding flags -> onboard, -m/--yes -> system agent,
bare configured interactive -> OpenClaw chat, unconfigured -> onboarding.
Hidden crestodian CLI and /crestodian TUI aliases kept; docs moved to
docs/cli/openclaw.md with redirect stub. macOS/Android strings in lockstep.
Refs #107237
Catalog session rows (sidebar context menu + click), the built-in viewer
header, and a new "Open Codex/Claude sessions in" preference can launch the
native CLI (codex resume / claude --resume) in the operator terminal on the
machine that owns the session.
- Gateway-local sessions spawn through the existing terminal launch policy
(sandbox/enabled gates preserved) with the resume command in the session cwd.
- Paired-node sessions run through a new seq-ordered node PTY relay: a
duplex node-host command streams PTY output via node.invoke.progress and
receives keystrokes/resize via a new node.invoke.input event, behind the
unchanged terminal.* client protocol (TerminalSessionManager gains a backend
abstraction; node relay reuses the streaming-invoke controller).
- Owner boundary: each plugin owns its resume command and builds argv from a
validated thread id; the gateway routes node opens through the node command
allowlist and plugin invoke policy (no advertisement-only trust), and nodes
re-verify session eligibility before spawning.
- UI setting catalogOpenTarget + canOpenTerminal capability gate every entry
point; capability requires the owning host to actually have the CLI.
Node PATH is normalized before command-availability probes, Windows .cmd/.bat
shims spawn via ComSpec, and catalog terminal opens reattach persisted tabs
before opening the new tab.
* refactor: delete dead infra and config exports
* refactor: preserve live infra and config contracts
* refactor(config): remove obsolete file-store lifecycle APIs
* refactor(infra): finish current-main dead export cleanup
* ci: enforce changed-file TypeScript LOC ratchet
* ci: derive release-gate LOC base from PR
* test(ci): exclude repository test helpers from LOC ratchet
* ci: validate LOC ratchet on PR merge tree
* style: format release maintainer skill
* ci: run LOC ratchet for fast-only changes
* fix(ci): harden LOC ratchet comparisons
* fix(ci): cover native TypeScript in LOC ratchet
* fix(ci): compare LOC against tested merge tree
* test(ci): cover LOC manifest routing
Remove the hard 500-line TypeScript LOC ratchet from CI and local check planning, along with its package commands, implementation, baseline, and dedicated tests. Keep the remaining pull-request temp-creation report on its own pr-base fetch.\n\nVerification: 99 focused tooling tests; actionlint; zizmor; workflow guards; exact-head autoreview.
* refactor: use semver package for version ordering
* refactor: centralize semver validation
* chore: keep release notes in PR body
* refactor: update semver LOC ratchet
* fix(agents): decode full HTML entity set
* fix(agents): preserve mixed-case nbsp extraction
* chore: leave release notes to release automation
* chore(ci): lower web fetch LOC baseline
* fix(agents): use literal entity radices
* chore(deadcode): add generated knip unused-export baseline
* ci(deadcode): replace broken export report lanes with enforced knip exports ratchet
* chore(deadcode): regenerate unused-export baseline on current main
* chore(deadcode): regenerate unused-export baseline on current main
* fix(extensions): make indexed access explicit across channel plugins
Transport-payload-safe burn-down: malformed Telegram/Discord/QQ/LINE
and sibling channel input keeps existing skip paths; no synthesized
fields, no new throws in delivery loops. Zalo escape sentinels preserve
literal matches instead of undefined replacements.
* fix(extensions): make indexed access explicit across provider and memory plugins
Stream and model iteration, tool-block guards, capture guards, and
sparse accumulators; singleton model reads carry named invariants.
* fix(extensions): make indexed access explicit across tooling plugins, flip the extensions lane
Remaining plugins (oc-path, qa-lab, browser, logbook, and siblings) plus
the tsconfig.extensions.json flag flip. Cleanup: logbook sampleFrames
NaN index at max=1, QA retry clamp at non-positive attempts, dead Canvas
probe and OpenShell no-op slice removed, twitch test setup leak excluded
from the prod lane.
* refactor(plugin-sdk): expose expectDefined via a focused SDK subpath
Extensions imported @openclaw/normalization-core directly, crossing the
external-plugin packaging boundary (it only worked because the runtime
builder bundles undeclared workspace helpers). expect-runtime joins the
canonical entrypoints JSON, generated exports, API baseline, docs, and
subpath contract test; all 78 extension imports now use the SDK seam.
Two scanner-shaped locals renamed for review-bundle hygiene.
* chore(plugin-sdk): raise surface budgets for the expect-runtime subpath
One new entrypoint with one callable export, added intentionally as the
packaging-honest seam for extension invariant helpers.
* fix(ui): make indexed access explicit across the Control UI
Burns down all 322 ui-lane noUncheckedIndexedAccess errors: untrusted
markdown/diff/patch parsing gets miss-tolerant guards (renderer rules
degrade to empty output instead of throwing mid-render), accumulators
use canonical sparse initialization, DOM lookups stay null-guarded, and
length-checked constructions carry named invariants.
* feat(tooling): enforce noUncheckedIndexedAccess in the core and ui lanes
Flips the flag on for tsconfig.core.json and tsconfig.ui.json (covering
src, all packages including the two deferred ones, and ui) and retires
the strict-ratchet lane wholesale: config, script, projects reference,
check/CI wiring, changed-lane routing, and sync test. The assertion-ban
oxlint override stays as an independent surface.