From 529e49fe9803622f734974d46fec71ccb4de4d55 Mon Sep 17 00:00:00 2001 From: Paul O'Reilly Date: Sun, 29 Mar 2026 09:38:00 +1300 Subject: [PATCH] Add reflected memory files and update git-status-report Adds gotchas-wezterm and updates gotchas-bash from recent reflections. Prunes old reflected log. Updates MEMORY.md index. Co-Authored-By: Claude Opus 4.6 (1M context) --- .reflection-state.json | 6 +++--- MEMORY.md | 3 ++- memory/gotchas-bash.md | 4 ++++ memory/gotchas-wezterm.md | 9 +++++++++ memory/log/2026-03-13.111440.md | 29 ----------------------------- scripts/git-status-report | 2 +- 6 files changed, 19 insertions(+), 34 deletions(-) create mode 100644 memory/gotchas-wezterm.md delete mode 100644 memory/log/2026-03-13.111440.md diff --git a/.reflection-state.json b/.reflection-state.json index 22eebdc..40defce 100644 --- a/.reflection-state.json +++ b/.reflection-state.json @@ -1,10 +1,10 @@ { "version": 1, - "last_run": "2026-03-16T22:19:21Z", + "last_run": "2026-03-24T10:36:46Z", "processed": { - "log/2026-03-13.111440.md": "01d9e37a3340506255d87e0100b33ef1", "log/2026-03-17.095436.md": "253f75f7ae43fb2547cd3377afb8d3b2", "log/2026-03-17.105314.md": "9c81013e9ab545527a363f525eff93e3", - "log/2026-03-17.110414.md": "5ad1a211737b604f33e31e9ce754be74" + "log/2026-03-17.110414.md": "5ad1a211737b604f33e31e9ce754be74", + "log/2026-03-23.123551.md": "6c9560f5348b0625abb5c4e52b1e0464" } } diff --git a/MEMORY.md b/MEMORY.md index f1efca6..0e84ccf 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -3,8 +3,9 @@ ## Gotchas -- [Bash Gotchas](memory/gotchas-bash.md) — `set -e` silent failures, `((var++))` with zero, grep flag parsing, `local` scope, binary detection with `file` command +- [Bash Gotchas](memory/gotchas-bash.md) — `set -e` silent failures, `((var++))` with zero, grep flag parsing, `local` scope, binary detection with `file` command, test harness `set -e` abort - [Skills Gotchas](memory/gotchas-skills.md) — Non-ASCII frontmatter silently breaks loading, per-profile independent skills directories +- [WezTerm Gotchas](memory/gotchas-wezterm.md) — Flatpak CLI not in PATH, proportional split math for equal panes ## Decisions - [Decisions](memory/decisions.md) — OpenSpec format, mandatory dryrun, `set -uo pipefail` policy, dirty-state definitions, skynet org hosting diff --git a/memory/gotchas-bash.md b/memory/gotchas-bash.md index 5c8b6c0..3926e11 100644 --- a/memory/gotchas-bash.md +++ b/memory/gotchas-bash.md @@ -20,6 +20,10 @@ Using `local` in the main script body (e.g., inside a `for` loop that isn't wrap Arithmetic expressions like `((PASS++))` return the *pre-increment* value. When PASS=0, the result is 0 (falsy), which `set -e` treats as a failure and silently exits the script. Use `PASS=$((PASS + 1))` instead — assignments always succeed regardless of the computed value. +## `set -e` in test harnesses aborts on expected failures + +Test scripts with `set -euo pipefail` silently abort when an assertion helper runs a command expected to fail (non-zero exit). The test runner exits before reporting results. Use `set -uo pipefail` (no `-e`) in test harness scripts and check exit codes explicitly in assertion functions. + ## `file` command marks shell scripts as "executable" The `file` command returns strings like "Bourne-Again shell script, Unicode text, UTF-8 text executable" for shell scripts. Grepping for `executable` to detect binaries will false-positive on text scripts. Instead, grep for `binary|image|archive` and additionally check that the output does NOT contain `text`. diff --git a/memory/gotchas-wezterm.md b/memory/gotchas-wezterm.md new file mode 100644 index 0000000..5c7bc14 --- /dev/null +++ b/memory/gotchas-wezterm.md @@ -0,0 +1,9 @@ +# WezTerm Gotchas + +## Flatpak-installed WezTerm CLI not in PATH + +`wezterm` CLI binary is not available in PATH when WezTerm is installed via Flatpak. Must invoke as `flatpak run org.wezfurlong.wezterm cli ...`. Scripts should auto-detect both native (`command -v wezterm`) and Flatpak installations. + +## Proportional split math for equal-sized panes + +To split a pane into N equal parts, each split i (0-indexed) uses `percent = (N-1-i)*100/(N-i)`. Example for 3 equal parts: first split at 66%, second at 50%. The `--horizontal` flag creates a column (pane to the right); `--bottom` creates a row (pane below). `wezterm cli split-pane` returns the new pane ID on stdout for subsequent splits. diff --git a/memory/log/2026-03-13.111440.md b/memory/log/2026-03-13.111440.md deleted file mode 100644 index 9a640cf..0000000 --- a/memory/log/2026-03-13.111440.md +++ /dev/null @@ -1,29 +0,0 @@ -# Session Log — 2026-03-13 - -## Summary -Created the `small-scripts` project — a spec-driven utility script collection with dryrun support and automated testing. Implemented the first script `git-status-report` which recursively scans directories for git repos and reports uncommitted changes with character-level diffs and remote sync status. - -## Decisions -- Decision: Use OpenSpec format for all script specifications — Rationale: Testing agent-driven development; specs define purpose, usage, behaviour, dryrun behaviour, edge cases, and examples -- Decision: Every script must support `--dryrun` / `-n` — Rationale: Enables testing via dryrun without side effects; tests validate spec compliance through dryrun output -- Decision: Removed `set -e` from git-status-report, kept `set -uo pipefail` — Rationale: `set -e` caused silent failures in complex pipeline/subshell chains; for a reporting tool, explicit error handling is safer than errexit -- Decision: "No remotes" and "detached HEAD" don't count as dirty — Rationale: These are informational states, not divergences; "(no remotes)" only shown when repo already has local changes -- Decision: Project hosted under `skynet` org on Gitea — Rationale: AI-focused project (agent-driven development testbed) - -## Gotchas Discovered -- **[bash]** Symptom: `set -euo pipefail` caused silent script termination with no output during complex loops with command substitutions and subshell calls — Fix: Removed `set -e`, kept `set -uo pipefail`. Reporting tools don't need errexit; explicit error handling is more predictable. -- **[bash]** Symptom: `grep -qF "$expected"` interpreted `--dryrun` as a grep flag — Fix: Use `grep -qF -- "$expected"` to prevent option-like strings from being parsed as flags -- **[bash]** Symptom: `local` keyword used outside a function in main loop body caused `local: can only be used in a function` error — Fix: Remove `local` qualifier for variables in the main script body -- **[bash]** Symptom: `set -e` in test script killed execution when capturing output from commands expected to exit non-zero (`output=$(cmd)` where cmd exits 1) — Fix: Use `output=$(cmd) && rc=$? || rc=$?` or `output=$(cmd) || true` pattern -- **[bash]** Symptom: `file` command on shell scripts returns "executable" which matched the binary detection grep `binary\|executable\|image\|archive` — Fix: Changed to `grep -qP "binary|image|archive"` with additional `! grep -q "text"` check to avoid false positives on text executables - -## Key Context -- Project structure: `specs/` (OpenSpec), `scripts/` (implementations), `tests/` (test scripts using dryrun) -- Scripts symlinked to `~/sbin` for PATH availability -- Test runner at `tests/run-all.sh` with colour pass/fail output -- First script `git-status-report` has 26 test assertions covering: help, no repos, dryrun, clean/dirty repos, untracked/deleted files, no remotes, ahead of remote, mixed repos, nested repo filtering, permission denied - -## Process Notes -- The `set -e` debugging consumed significant time — the script worked in isolated tests but failed silently on real repos. Future scripts should start without `set -e` for reporting/read-only tools. -- Test development caught real bugs (grep flag parsing, local keyword misuse) — the spec-driven approach with comprehensive tests works well. -- The `file` command for binary detection is unreliable for scripts; need a better heuristic (maybe `git diff --numstat` which shows `-` for binary files). diff --git a/scripts/git-status-report b/scripts/git-status-report index d368220..19dcd61 100755 --- a/scripts/git-status-report +++ b/scripts/git-status-report @@ -54,7 +54,7 @@ discover_repos() { while IFS= read -r -d '' gitdir; do repos+=("$(dirname "$gitdir")") - done < <(find -L "$dir" -name .git -type d -print0 2>/dev/null | sort -z) + done < <(find -L "$dir" -name .git -type d -not -path '*/customers/*' -print0 2>/dev/null | sort -z) # Filter out nested repos (a repo whose path is a subdirectory of another) local filtered=()