i3blocks: daily-limits click works under i3blocks' PATH; deps: anthropic 1.12.1, pyflakes 4.0.3
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run

i3blocks' environment has no ~/.local/bin, so `command -v daily-limits`
failed and every left-click on ⏻/🎮 was silently dropped. Call the launcher
by path (DAILY_LIMITS_BIN), detach with setsid, and notify when it is
missing. Also bumps the two pins behind latest stable that turned the
freshness gate red on 433cec27.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrjUTo1yhgAsUUasdw4bpG
This commit is contained in:
Krzysztof Rudnicki 2026-10-09 11:53:10 +02:00
parent 433cec278e
commit 5f14add664
8 changed files with 97 additions and 44 deletions

View File

@ -0,0 +1,11 @@
{
"title": "i3blocks: left-click on ⏻/🎮 opens the daily-limits popup",
"objective": "A left-click on either block launches `daily-limits --gui` even though i3blocks' PATH lacks ~/.local/bin, and a missing launcher is reported instead of ignored.",
"acceptance_criteria": [
"With PATH=/usr/bin:/bin and BLOCK_BUTTON=1 both blocks run $DAILY_LIMITS_BIN --gui",
"A missing launcher triggers notify-send",
"The three i3blocks test suites pass and pre-commit is clean"
],
"out_of_scope": ["The daily-limits GUI itself", "A phone version"],
"verifier": "bash linux_configuration/tests/test_i3blocks_{gaming_budget,shutdown_hint,efficiency}.sh; pre-commit run"
}

View File

@ -1,37 +0,0 @@
{
"intent": "Turn the Shell tests workflow green again: test_network_diagnostics.bats still sourced its scripts through the scripts/ level the flatten removed.",
"scope": [
"linux_configuration/tests/test_network_diagnostics.bats - DIAG_DIR and its header comment",
"NEXT_SESSION_RESTRUCTURE.md / NEXT_SESSION_PROMPT.md - handoff rewrite for the two remaining units",
"Non-goal: the diagnostics scripts themselves, which are correctly placed."
],
"changes": [
"DIAG_DIR pointed at $REPO_DIR/scripts/diagnostics; the flatten dissolved linux_configuration/scripts/, so setup() failed to source and all 30 tests errored. Now $REPO_DIR/diagnostics.",
"Fixed the header comment naming the same dead path.",
"Rewrote the handoff docs around the two units that remain, with the verified numbers and the traps this session paid for."
],
"verification": [
{
"command": "bats linux_configuration/tests/test_network_diagnostics.bats",
"result": "pass",
"evidence": "30/30 ok. Previously every test failed in setup with 'No such file or directory' on .../scripts/diagnostics/steam-download-duty.sh."
},
{
"command": "grep -rn 'linux_configuration/scripts/|scripts/single_use|single_use/' over tracked .sh/.bats/.py/.yml",
"result": "pass",
"evidence": "No matches. This was the last stale reference to the removed levels inside the repo; the 8 remaining live-state hits are installed copies under /usr/local/bin, outside the tree."
},
{
"command": "gh run view 32656921622 --log-failed",
"result": "pass",
"evidence": "Confirmed the CI failure was exactly this suite. The previous run (cbdf3a3d) was green because ci-mirror aborted before the bats stage, so the breakage was latent rather than newly introduced."
}
],
"risks": [
"CI_GREEN_SKIP=1 is used for this commit because the ci-baseline-green hook refuses to build on a red main and this commit IS the fix - the documented escape for exactly this case."
],
"rollback": [
"git revert the commit; the bats suite returns to the dead path and Shell tests goes red again.",
"After rollback, run bats linux_configuration/tests/test_network_diagnostics.bats to confirm the expected failure."
]
}

View File

@ -0,0 +1,31 @@
{
"intent": "Left-clicking the ⏻ or 🎮 i3blocks block opens the daily-limits popup; before this, every click was a silent no-op.",
"scope": [
"linux_configuration/i3blocks/gaming_budget.sh, shutdown_countdown.sh",
"linux_configuration/tests/test_i3blocks_gaming_budget.sh, test_i3blocks_shutdown_hint.sh"
],
"changes": [
"Root cause: the i3blocks process PATH has no ~/.local/bin, where daily-limits' install.sh puts the binary, so `command -v daily-limits` failed and the click was dropped",
"Both blocks call DAILY_LIMITS_BIN (default $HOME/.local/bin/daily-limits) by path, detached with setsid -f",
"A missing launcher raises a critical notify-send instead of doing nothing",
"Regression tests: click with PATH=/usr/bin:/bin runs `--gui`; missing launcher notifies"
],
"verification": [
{
"command": "env -i PATH=/usr/local/bin:/usr/bin:/bin BLOCK_BUTTON=1 DAILY_LIMITS_BIN=<stub> bash i3blocks/{gaming_budget,shutdown_countdown}.sh (i3blocks' real PATH from /proc/<pid>/environ)",
"result": "pass",
"evidence": "stub log: 'clicked --gui' twice; block output unchanged (🎮 2h35 left · 2h25/5h00 ..., ⏻ 22:00 ... →max 23:00)"
},
{
"command": "capped.sh bash tests/test_i3blocks_gaming_budget.sh; test_i3blocks_shutdown_hint.sh; test_i3blocks_efficiency.sh",
"result": "pass",
"evidence": "All gaming_budget checks passed. / All shutdown hint tests passed. / All i3blocks efficiency regression tests passed."
}
],
"risks": [
"If daily-limits is installed elsewhere, DAILY_LIMITS_BIN must be set in the i3blocks environment"
],
"rollback": [
"git revert this commit; clicks go back to doing nothing under i3blocks' PATH"
]
}

View File

@ -30,8 +30,15 @@ emit() {
printf '%s\n%s\n%s\n' "$1" "$2" "$3"
}
if [[ ${BLOCK_BUTTON:-0} -eq 1 ]] && command -v daily-limits >/dev/null 2>&1; then
daily-limits --gui >/dev/null 2>&1 &
# i3blocks' PATH has no ~/.local/bin, where daily-limits' install.sh puts it,
# so a bare `daily-limits` made every click a silent no-op.
readonly DAILY_LIMITS_BIN=${DAILY_LIMITS_BIN:-$HOME/.local/bin/daily-limits}
if [[ ${BLOCK_BUTTON:-0} -eq 1 ]]; then
if [[ -x $DAILY_LIMITS_BIN ]]; then
setsid -f "$DAILY_LIMITS_BIN" --gui >/dev/null 2>&1
else
notify-send -u critical 'daily-limits' "not installed: $DAILY_LIMITS_BIN" || true
fi
fi
# One jq pass renders four lines: generated_at, full text, short text, color.

View File

@ -20,9 +20,12 @@ LIMITS_CACHE=${DAILY_LIMITS_CACHE:-${XDG_RUNTIME_DIR:-/tmp}/daily-limits.json}
RENDER_CACHE=${DAILY_LIMITS_RENDER_CACHE:-${XDG_RUNTIME_DIR:-/tmp}/i3blocks-shutdown.render}
readonly STALE_AFTER_SECONDS=180
# Left-click: open the daily-limits popup (a fork only on click).
if [[ ${BLOCK_BUTTON:-0} -eq 1 ]] && command -v daily-limits >/dev/null 2>&1; then
daily-limits --gui >/dev/null 2>&1 &
# Left-click opens the popup, by path: i3blocks' PATH has no ~/.local/bin.
readonly DAILY_LIMITS_BIN=${DAILY_LIMITS_BIN:-$HOME/.local/bin/daily-limits}
if [[ ${BLOCK_BUTTON:-0} -eq 1 && -x $DAILY_LIMITS_BIN ]]; then
setsid -f "$DAILY_LIMITS_BIN" --gui >/dev/null 2>&1
elif [[ ${BLOCK_BUTTON:-0} -eq 1 ]]; then
notify-send -u critical 'daily-limits' "not installed: $DAILY_LIMITS_BIN" || true
fi
# Function to show error state in i3blocks and exit

View File

@ -133,4 +133,23 @@ touch "$CACHE"
PATH="$TMP_DIR/bin:$PATH" run_block >/dev/null
assert_eq '2' "$(wc -l <"$TMP_DIR/jq.calls")" 'a rewritten cache is re-parsed'
printf 'Checking a left-click opens the popup without ~/.local/bin on PATH...\n'
mkdir -p "$TMP_DIR/click-bin"
printf '#!/bin/bash\necho "gui $*" >>"%s/clicks"\n' "$TMP_DIR" >"$TMP_DIR/daily-limits-stub"
printf '#!/bin/bash\necho "notify $*" >>"%s/clicks"\n' "$TMP_DIR" >"$TMP_DIR/click-bin/notify-send"
chmod +x "$TMP_DIR/daily-limits-stub" "$TMP_DIR/click-bin/notify-send"
# i3blocks' PATH has no ~/.local/bin: the launcher must be found by its path.
BLOCK_BUTTON=1 DAILY_LIMITS_BIN="$TMP_DIR/daily-limits-stub" PATH="$TMP_DIR/click-bin:/usr/bin:/bin" run_block >/dev/null
for _ in 1 2 3 4 5 6 7 8 9 10; do
[[ -s "$TMP_DIR/clicks" ]] && break
sleep 0.1
done
assert_eq 'gui --gui' "$(cat "$TMP_DIR/clicks" 2>/dev/null)" 'left-click runs daily-limits --gui'
rm -f "$TMP_DIR/clicks"
# A missing launcher says so instead of a silent no-op.
BLOCK_BUTTON=1 DAILY_LIMITS_BIN="$TMP_DIR/absent" PATH="$TMP_DIR/click-bin:/usr/bin:/bin" run_block >/dev/null
assert_eq "notify -u critical daily-limits not installed: $TMP_DIR/absent" "$(cat "$TMP_DIR/clicks" 2>/dev/null)" \
'a missing launcher raises a notification'
rm -f "$TMP_DIR/clicks"
printf 'All gaming_budget checks passed.\n'

View File

@ -105,4 +105,23 @@ printf 'not json\n' >"$CACHE"
rm -f "$RENDER"
assert_eq '⏻ 20:00 ⏱!' "$(first_line 1200)" 'unreadable cache'
printf 'Checking a left-click opens the popup without ~/.local/bin on PATH...\n'
mkdir -p "$TMP_DIR/click-bin"
printf '#!/bin/bash\necho "gui $*" >>"%s/clicks"\n' "$TMP_DIR" >"$TMP_DIR/daily-limits-stub"
printf '#!/bin/bash\necho "notify $*" >>"%s/clicks"\n' "$TMP_DIR" >"$TMP_DIR/click-bin/notify-send"
chmod +x "$TMP_DIR/daily-limits-stub" "$TMP_DIR/click-bin/notify-send"
# i3blocks' PATH has no ~/.local/bin: the launcher must be found by its path.
BLOCK_BUTTON=1 DAILY_LIMITS_BIN="$TMP_DIR/daily-limits-stub" PATH="$TMP_DIR/click-bin:/usr/bin:/bin" first_line 1200 >/dev/null
for _ in 1 2 3 4 5 6 7 8 9 10; do
[[ -s "$TMP_DIR/clicks" ]] && break
sleep 0.1
done
assert_eq 'gui --gui' "$(cat "$TMP_DIR/clicks" 2>/dev/null)" 'left-click runs daily-limits --gui'
rm -f "$TMP_DIR/clicks"
# A missing launcher says so instead of a silent no-op.
BLOCK_BUTTON=1 DAILY_LIMITS_BIN="$TMP_DIR/absent" PATH="$TMP_DIR/click-bin:/usr/bin:/bin" first_line 1200 >/dev/null
assert_eq "notify -u critical daily-limits not installed: $TMP_DIR/absent" "$(cat "$TMP_DIR/clicks" 2>/dev/null)" \
'a missing launcher raises a notification'
rm -f "$TMP_DIR/clicks"
printf 'All shutdown hint tests passed.\n'

View File

@ -6,7 +6,7 @@
add-trailing-comma==4.0.0
aiohttp==3.14.4
anthropic==1.11.0
anthropic==1.12.1
autoflake==2.4.0
autopep8==2.3.2
bandit==1.9.4
@ -60,7 +60,7 @@ pre-commit==4.6.2
prospector==1.19.1
pycodestyle==2.15.0
pydocstyle==6.3.0
pyflakes==4.0.2
pyflakes==4.0.3
pygame==2.6.1
pylint==4.1.2
pyright==1.1.414