Skip to content
This repository was archived by the owner on Nov 12, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion mseries/CODEXBAR-PORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ ones.** Upgrade by re-pinning, re-installing upstream, and re-verifying each ite
7. If upstream starts reporting a provider we draw ourselves (a `claude` entry), our card steps aside; check for double cards.
8. Record the pin, what was re-verified and what was not in `OS9-HANDOFF.md`; push; run `deploy-codexbar.sh`.

`codexbar --version` reads the `VERSION` file the tarball installs beside the binary, so it can name the new
release while an old binary still runs. Confirm what `~/.local/lib/codexbar-cli/codexbar-upstream` resolves to.
v0.78.0 linked `libxml2.so.2` and ran through a compat wrapper on this base (`codexbar_install_cli_compat`);
v0.79.0+ does not, and the next install or deploy replaces the wrapper with a symlink to `CodexBarCLI`.

## Do not lose

- Our helpers are installed from this repo by the installers and the deploy script; the installer does not delete user config.
Expand Down Expand Up @@ -459,7 +464,7 @@ This handles Pro-to-Max upgrades whose issued token still says Pro.
## Unified T3 presentation — 2026-10-26

`mseries/t3-wingpanel` embeds this maintained native view and RepoBar's view in
one T3 menu, shared with the dock. The backend pin remains v0.78.0 and the
one T3 menu, shared with the dock. The backend pin is v0.83.0 (bumped 2026-10-31) and the
`codexbar-linux --snapshot` schema is unchanged. Supported standalone deployments
retain a rollback module outside Wingpanel discovery when `libmseries-t3.so`
is installed; helpers/settings/provider assets remain maintained. Native module
Expand Down
4 changes: 4 additions & 0 deletions mseries/OS9-HANDOFF.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## CodexBar upstream v0.78.0 -> v0.83.0 (staged, not deployed) — 2026-10-31

Bumped `install-codexbar.sh` to v0.83.0. Read the v0.79.0-v0.83.0 release notes; both aarch64 tarballs pass their published sha256. In an arm64 Ubuntu 26.04 container, v0.83.0 accepts every CLI form our helpers use (`usage --provider codex|claude|opencodego [--source api] --format json`, `config providers --format json`, `config set-api-key --provider ... --stdin`); the only errors were "signed out" provider errors, not parsing errors (v0.83.0 rejects malformed arguments). `--all-accounts`/`--account` still exist, `grok` is still listed, `CODEX_HOME` is still honored. Upstream `Integrations/Linux`: the settings QML is unchanged, `snapshot()` is unchanged, `DesktopController::probe` now drops rows for other providers in custom mode, and `install.py` handles odd paths. v0.79.0+ no longer links `libxml2.so.2`: `codexbar_install_cli_compat` now retires its wrapper (symlink to `CodexBarCLI`, removes `compat/` and `.real`) when the current CLI does not need it, and drops a stale remembered binary when a plain binary is installed; new `test-codexbar-cli-compat.py` (6 cases); a container run using the live 0.78-behind-wrapper layout ends on a clean symlink running 0.83.0. Not done: install/deploy on the j314s (not reachable from this session), `check-codexbar-port.sh` against the live app, the snapshot fixture comparison and a signed-in usage read. Next: on the j314s run `bash mseries/install-codexbar.sh --skip-system-deps`, `bash mseries/deploy-codexbar.sh`, `bash mseries/check-codexbar-port.sh`.

## Warren local AI and eGPU updates — 2026-10-30

Installed `mseries-nvidia-open-source` `595.112.07+apple.1-1` (SHA-256 `a397b68a...b209ab23`) containing the three prepared NVIDIA fixes and license at `/usr/src/mseries-nvidia-open-595.112.07`. This is source only; no NVIDIA module or matching CUDA userspace is installed. The [source package script](nvidia-egpu/package-source.sh) verifies the exact prepared diff before packaging.
Expand Down
4 changes: 2 additions & 2 deletions mseries/install-codexbar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -euo pipefail
[[ $(uname -m) == aarch64 ]] || { echo 'This installer requires ARM64' >&2; exit 1; }
repo=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
source "$repo/mseries/lib-apt.sh"
version=v0.78.0
version=v0.83.0
if [[ ${1:-} != --skip-system-deps ]]; then
mseries_apt_refresh
sudo apt-get install -y \
Expand All @@ -27,7 +27,7 @@ source "$repo/mseries/lib-codexbar.sh"
codexbar_install_helpers "$repo"
tar -xzf "CodexBarCLI-${version}-linux-aarch64.tar.gz" -C "$HOME/.local/lib/codexbar-cli"
mv -f "$HOME/.local/lib/codexbar-cli/codexbar" "$HOME/.local/lib/codexbar-cli/codexbar-upstream"
# v0.78.0's CLI links libxml2.so.2; wrap it when this base only ships the newer soname.
# v0.78.0's CLI linked libxml2.so.2 and needed a wrapper on this base; v0.79.0+ does not, and the shim removes itself.
codexbar_install_cli_compat
codexbar_install_wrapper "$repo"
tar -xzf "CodexBarDesktop-${version}-linux-aarch64.tar.gz"
Expand Down
35 changes: 31 additions & 4 deletions mseries/lib-codexbar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,43 @@ codexbar_install_helpers() {
codexbar_install_cli_compat
}

# codexbar_cli_needs_libxml2 BINARY: true when the CLI binary links libxml2.so.2.
codexbar_cli_needs_libxml2() {
LC_ALL=C ldd "$1" 2>/dev/null | grep -q 'libxml2\.so\.2'
}

# codexbar_install_cli_compat: upstream v0.78.0's CLI links libxml2.so.2, but
# libxml2 >= 2.14 renamed the soname (libxml2.so.16 on this base), so the CLI
# cannot load. Resolve the old soname from a compat directory and route
# codexbar-upstream through a wrapper that points the loader there. The wrapper
# is a no-op when the system provides libxml2.so.2 (an older base, or an upstream
# rebuild); delete this shim when that day comes. Idempotent: the real binary's
# name is remembered in codexbar-upstream.real.
# is a no-op when the system provides libxml2.so.2 (an older base). Upstream
# v0.79.0 and later no longer link libxml2; for them the shim removes itself.
# Idempotent: the real binary's name is remembered in codexbar-upstream.real.
codexbar_install_cli_compat() {
local lib="$HOME/.local/lib/codexbar-cli" soname real base
local lib="$HOME/.local/lib/codexbar-cli" soname real base current
[[ -e $lib/codexbar-upstream || -L $lib/codexbar-upstream ]] || return 0
if [[ -f $lib/codexbar-upstream && ! -L $lib/codexbar-upstream \
&& $(head -c 2 "$lib/codexbar-upstream") == '#!' ]]; then
# Our wrapper: the binary it runs is the current CLI.
current=$lib/$(cat "$lib/codexbar-upstream.real" 2>/dev/null)
else
# An install moved upstream's codexbar (a symlink to CodexBarCLI, or a plain binary)
# over the wrapper. It is current; a remembered name may point at the previous version.
current=$(readlink -f "$lib/codexbar-upstream")
[[ $current == "$lib/codexbar-upstream.bin" ]] || rm -f "$lib/codexbar-upstream.bin"
rm -f "$lib/codexbar-upstream.real"
fi
if [[ -f $current ]] && ! codexbar_cli_needs_libxml2 "$current"; then
# Upstream v0.79.0+ does not link libxml2: point codexbar-upstream straight at the
# binary (rename, so callers never find it missing) and drop the shim.
if [[ $current != "$(readlink -f "$lib/codexbar-upstream")" ]]; then
ln -sfn "$(basename "$current")" "$lib/codexbar-upstream.new"
mv -f "$lib/codexbar-upstream.new" "$lib/codexbar-upstream"
fi
rm -f "$lib/codexbar-upstream.real"
rm -rf "$lib/compat"
return 0
fi
if ldconfig -p | awk '{print $1}' | grep -qx libxml2.so.2; then
return 0
fi
Expand Down
2 changes: 1 addition & 1 deletion mseries/t3-wingpanel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ requires a recent, connected, non-stale feed and live application bus owner;
a one-shot expiry clears an idle badge without polling collectors. One normal
RepoBar object retains the existing background notification/settings behavior;
the visible embedded GitHub view never duplicates notifications. CodexBar's
v0.78.0 custom collectors, accounts, sessions, wrappers and daemon stay in use.
custom collectors, accounts, sessions, wrappers and daemon stay in use.

## Build and stage

Expand Down
130 changes: 130 additions & 0 deletions mseries/test-codexbar-cli-compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
"""codexbar_install_cli_compat: the libxml2 shim must follow upstream upgrades and remove itself
once the CLI no longer links libxml2.so.2 (upstream v0.79.0+)."""

import os
import pathlib
import subprocess
import tempfile
import unittest

LIB_SH = pathlib.Path(__file__).with_name("lib-codexbar.sh")
# Fake binaries; the stub below reports libxml2 for any file containing "needs-libxml2".
OLD = b"\x7fELF v0.78.0 needs-libxml2"
NEW = b"\x7fELF v0.83.0"
NEW_NEEDS = b"\x7fELF v0.8x needs-libxml2"


class CliCompat(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
root = pathlib.Path(self.temp.name)
self.home = root / "home"
self.lib = self.home / ".local/lib/codexbar-cli"
self.lib.mkdir(parents=True)
shims = root / "bin"
shims.mkdir()
# A base that ships only the renamed libxml2 soname, like Ubuntu 26.04.
(shims / "ldconfig").write_text(
"#!/bin/sh\nprintf '\\tlibxml2.so.16 (libc6,AArch64) => /usr/lib/libxml2.so.16\\n'\n")
(shims / "ldconfig").chmod(0o755)
self.path = f"{shims}:{os.environ['PATH']}"

def compat(self):
script = (f'source "{LIB_SH}"\n'
'codexbar_cli_needs_libxml2() { grep -q needs-libxml2 "$1"; }\n'
'codexbar_install_cli_compat\n')
subprocess.run(["bash", "-c", script], check=True,
env={**os.environ, "HOME": str(self.home), "PATH": self.path})

def install(self, payload, symlink=True):
"""install-codexbar.sh: extract the tarball into lib, then move codexbar over codexbar-upstream.
Upstream's tarball ships codexbar as a symlink to CodexBarCLI."""
extracted = self.lib / "codexbar"
if symlink:
(self.lib / "CodexBarCLI").write_bytes(payload)
extracted.symlink_to("CodexBarCLI")
else:
extracted.write_bytes(payload)
os.replace(extracted, self.lib / "codexbar-upstream")

def executes(self):
"""Bytes of the binary codexbar-upstream ends up running."""
upstream = self.lib / "codexbar-upstream"
if not upstream.is_symlink() and upstream.read_bytes().startswith(b"#!"):
text = upstream.read_text()
self.assertIn("compat", text)
return (self.lib / (self.lib / "codexbar-upstream.real").read_text().strip()).read_bytes()
return upstream.read_bytes()

def assert_no_shim(self):
for leftover in ("codexbar-upstream.real", "codexbar-upstream.bin", "compat"):
self.assertFalse((self.lib / leftover).exists(), leftover)

def test_cli_that_links_libxml2_gets_the_wrapper(self):
self.install(OLD)
self.compat()

self.assertTrue((self.lib / "compat/libxml2.so.2").is_symlink())
self.assertEqual((self.lib / "codexbar-upstream.real").read_text().strip(), "CodexBarCLI")
self.assertEqual(self.executes(), OLD)

def test_rerun_on_wrapper_is_idempotent(self):
self.install(OLD)
self.compat()
wrapper = (self.lib / "codexbar-upstream").read_bytes()

self.compat()

self.assertEqual((self.lib / "codexbar-upstream").read_bytes(), wrapper)
self.assertEqual(self.executes(), OLD)

def test_upgrade_to_cli_without_libxml2_removes_the_shim(self):
self.install(OLD)
self.compat()

self.install(NEW)
self.compat()

self.assertTrue((self.lib / "codexbar-upstream").is_symlink())
self.assertEqual(self.executes(), NEW)
self.assert_no_shim()

def test_wrapper_left_over_a_replaced_binary_is_retired(self):
# A v0.83.0 tarball extracted over CodexBarCLI while the wrapper stayed (the previous
# code's upgrade result): the next deploy points codexbar-upstream at the binary directly.
self.install(OLD)
self.compat()
(self.lib / "CodexBarCLI").write_bytes(NEW)

self.compat()

self.assertTrue((self.lib / "codexbar-upstream").is_symlink())
self.assertEqual(self.executes(), NEW)
self.assert_no_shim()

def test_plain_binary_upgrade_that_still_needs_libxml2_wraps_the_new_binary(self):
self.install(OLD, symlink=False)
self.compat()
self.assertEqual((self.lib / "codexbar-upstream.real").read_text().strip(), "codexbar-upstream.bin")

self.install(NEW_NEEDS, symlink=False)
self.compat()

self.assertEqual(self.executes(), NEW_NEEDS)

def test_plain_binary_upgrade_without_libxml2_drops_the_old_binary(self):
self.install(OLD, symlink=False)
self.compat()

self.install(NEW, symlink=False)
self.compat()
self.compat()

self.assertEqual(self.executes(), NEW)
self.assert_no_shim()


if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions mseries/validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ check codexbar 'test-codexbar-claude.py' 'python3 mseries/test-codexbar-claude.p
check codexbar 'test-codexbar-claude-history.py' 'python3 mseries/test-codexbar-claude-history.py'
check codexbar 'test-codexbar-claude-handoff.py' 'python3 mseries/test-codexbar-claude-handoff.py'
check codexbar 'test-codexbar-wrapper.py' 'python3 mseries/test-codexbar-wrapper.py'
check codexbar 'test-codexbar-cli-compat.py' 'python3 mseries/test-codexbar-cli-compat.py'
check codexbar 'test-codexbar-opencode-local.py' 'python3 mseries/test-codexbar-opencode-local.py'
check codexbar 'test-codexbar-opencode-login.py' 'python3 mseries/test-codexbar-opencode-login.py'

Expand Down
Loading