The footer showed invented percentages. It now shows what two harnesses actually report, or says it does not know. lumbridge-core gains an append-only per-profile UsageLedger and a projection that labels every derived value estimated, withholds a burn rate from a single sample, withholds a window fraction with no reported ceiling, withholds an exhaustion estimate that lands after the reset, and reports an expired window as rolled over rather than freezing its last percentage. A missing fact renders as missing, never as zero. (0012) lumbridge-harness is the impure side: processes, clocks, and untrusted wire text in, observations out. Three adapters: - Codex's account/rateLimits/read over the app-server's JSON-RPC stdio. The client cannot express a request outside a two-variant enum and answers every server-to-client request with -32601, so a harness asking Lumbridge for a credential is refused by construction. (0013) - Claude Code's session transcripts, as a byte-offset tail follower that reports nothing until the backlog is read to EOF — a partially-read backlog is indistinguishable from a burst of spend, and the first run against 20 MB reported forty-six billion tokens an hour. The parser models four counters, so the conversations in those files are not representable. (0014) - Claude Code's five-hour and seven-day subscription windows, via a bridge installed as its statusLine command. 0014 had claimed no such surface existed; it does, and the record is corrected in place rather than quietly edited. Lumbridge does not read the OAuth credential to call the account usage endpoint, which is what comparable tools do — AGENTS.md forbids it, and 0015 says so rather than leaving the gap unexplained. Also in here: a capability-check ordering fix in the workspace reducer, where the applied-request replay table was consulted before the capability check and so answered questions the caller had no right to ask; the GPUI spike wired to the live probes with per-harness gauges and provenance chips; and a launcher that matches its own window by PID, because GPUI sets WM_NAME but not _NET_WM_NAME and a title match never succeeded. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
122 lines
4.5 KiB
Bash
Executable File
122 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
repo_path=${LUMBRIDGE_REPO:-/home/metal/Desktop/Lumbridge Code/lumbridge}
|
|
window_title='Lumbridge · GPUI workspace'
|
|
bacon_title='Lumbridge · Bacon'
|
|
manifest_path="$repo_path/spikes/gpui-shell/Cargo.toml"
|
|
binary_path="$repo_path/spikes/gpui-shell/target/debug/lumbridge-spike-gpui"
|
|
|
|
if [[ ! -d "$repo_path/.git" ]]; then
|
|
echo "Lumbridge repository not found at $repo_path" >&2
|
|
exit 1
|
|
fi
|
|
|
|
export DISPLAY=${DISPLAY:-:0}
|
|
export XAUTHORITY=${XAUTHORITY:-/run/user/1000/gdm/Xauthority}
|
|
export XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/run/user/1000}
|
|
export DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS:-unix:path=/run/user/1000/bus}
|
|
|
|
for command_name in wmctrl xdotool; do
|
|
if ! command -v "$command_name" >/dev/null 2>&1; then
|
|
echo "required command not found: $command_name" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
if [[ ! -x "$binary_path" ]]; then
|
|
if ! command -v cargo >/dev/null 2>&1; then
|
|
# Non-login Tailscale SSH commands do not inherit metal's Cargo PATH.
|
|
# shellcheck source=/dev/null
|
|
source /home/metal/.cargo/env
|
|
fi
|
|
if ! command -v cargo >/dev/null 2>&1; then
|
|
echo "required command not found: cargo" >&2
|
|
exit 1
|
|
fi
|
|
xkb_runtime=/usr/lib/x86_64-linux-gnu/libxkbcommon-x11.so.0
|
|
if [[ -e "$xkb_runtime" ]]; then
|
|
native_libs="$repo_path/spikes/gpui-shell/target/native-libs"
|
|
mkdir -p "$native_libs"
|
|
ln -sfn "$xkb_runtime" "$native_libs/libxkbcommon-x11.so"
|
|
export LIBRARY_PATH="$native_libs${LIBRARY_PATH:+:$LIBRARY_PATH}"
|
|
fi
|
|
cargo build --locked --manifest-path "$manifest_path"
|
|
fi
|
|
|
|
# GPUI's X11 client sets WM_NAME but not _NET_WM_NAME, so wmctrl's window list
|
|
# reports its title as N/A and a title match never succeeds. xdotool reads
|
|
# WM_NAME, and matching the launched PID avoids picking up another client that
|
|
# merely mentions the window title.
|
|
window_for_pid() {
|
|
local pid=$1 candidate
|
|
for candidate in $(xdotool search --name 'GPUI workspace' 2>/dev/null); do
|
|
if [[ "$(xdotool getwindowpid "$candidate" 2>/dev/null || true)" == "$pid" ]]; then
|
|
printf '%s\n' "$candidate"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
existing_id=''
|
|
app_pid=$(pgrep -f "^$binary_path$" | head -n 1 || true)
|
|
if [[ -n "$app_pid" ]]; then
|
|
existing_id=$(window_for_pid "$app_pid" || true)
|
|
fi
|
|
if [[ -z "$existing_id" ]]; then
|
|
"$binary_path" >"$XDG_RUNTIME_DIR/lumbridge-gpui.log" 2>&1 &
|
|
app_pid=$!
|
|
for _attempt in $(seq 1 80); do
|
|
existing_id=$(window_for_pid "$app_pid" || true)
|
|
[[ -n "$existing_id" ]] && break
|
|
sleep 0.1
|
|
done
|
|
fi
|
|
|
|
if [[ -z "$existing_id" ]]; then
|
|
echo "Lumbridge window did not become visible; see $XDG_RUNTIME_DIR/lumbridge-gpui.log" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Gigabyte G34WQC is 3440x1440 at X=0. Lumbridge owns the whole panel: the
|
|
# workspace is a wall of agents and every pixel of width buys another column.
|
|
# Set LUMBRIDGE_HALF=1 to fall back to the left half beside Bacon.
|
|
if [[ "${LUMBRIDGE_HALF:-0}" == "1" ]]; then
|
|
bacon_id=$(wmctrl -l | awk -v title="$bacon_title" 'index($0, title) { print $1; exit }')
|
|
if [[ -n "$bacon_id" ]]; then
|
|
wmctrl -i -r "$bacon_id" -b remove,maximized_vert,maximized_horz
|
|
# GNOME's X11 move coordinate is scaled on this display even though window
|
|
# sizes are not; 860 places the frame at physical X=1720.
|
|
wmctrl -i -r "$bacon_id" -e 0,860,0,1720,1400
|
|
fi
|
|
wmctrl -i -r "$existing_id" -b remove,fullscreen
|
|
wmctrl -i -r "$existing_id" -b remove,maximized_vert,maximized_horz
|
|
wmctrl -i -r "$existing_id" -e 0,0,0,1720,1400
|
|
wmctrl -i -a "$existing_id"
|
|
# GPUI's undecorated X11 client ignores direct position requests under GNOME.
|
|
# Use the window manager's move interaction to settle it into the left half.
|
|
xdotool key alt+F7
|
|
sleep 0.15
|
|
xdotool mousemove 860 660 click 1
|
|
echo "Lumbridge is on the left half of the Gigabyte display (window $existing_id)."
|
|
exit 0
|
|
fi
|
|
|
|
# Fullscreen drops the title bar and the shell owns all 3440x1440. Move it onto
|
|
# the Gigabyte first: a fullscreen request applies to whichever output the
|
|
# window is currently on, so placing it after would fullscreen the wrong panel.
|
|
wmctrl -i -r "$existing_id" -b remove,fullscreen
|
|
wmctrl -i -r "$existing_id" -b remove,maximized_vert,maximized_horz
|
|
wmctrl -i -r "$existing_id" -e 0,0,0,1720,1400
|
|
wmctrl -i -a "$existing_id"
|
|
xdotool key alt+F7
|
|
sleep 0.15
|
|
xdotool mousemove 860 660 click 1
|
|
sleep 0.2
|
|
wmctrl -i -r "$existing_id" -b add,fullscreen
|
|
sleep 0.3
|
|
|
|
geometry=$(xdotool getwindowgeometry "$existing_id" | awk '/Geometry/ { print $2 }')
|
|
echo "Lumbridge is fullscreen on the Gigabyte display at ${geometry} (window $existing_id)."
|