aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--todo.org16
1 files changed, 14 insertions, 2 deletions
diff --git a/todo.org b/todo.org
index 116f881..da2366b 100644
--- a/todo.org
+++ b/todo.org
@@ -208,9 +208,21 @@ auto inbox zero. Take up only if the interactive shape proves too narrow.
** TODO [#C] ai launcher hardening — bug hunt + refactor pass :refactor:solo:
:PROPERTIES:
:CREATED: [2026-07-13 Mon]
-:LAST_REVIEWED: 2026-07-13
+:LAST_REVIEWED: 2026-07-19
:END:
-From the roam inbox (2026-07-13): find bugs in =bin/ai= until no more are visible, then refactor until no worthwhile opportunities remain. The launcher gained =--runtime= + =--print-launch= + 6 bats tests today (04c3b29); this pass extends coverage over the legacy paths (multi_mode, sort_windows, git prep, window sorting) and cleans as it goes. The runtime-selection asks from the same capture are tracked on the generic-agent-runtime parent (claude/codex shipped; ollama/qwen pending the model-floor eval); an interactive runtime picker is fair game here if it stays lightweight.
+Harden =claude-templates/bin/ai= (the agent-session launcher, 540 lines, 22 functions). Origin: roam inbox 2026-07-13, phrased open-endedly ("find bugs until none visible, refactor until nothing worthwhile remains"). Rescoped 2026-07-19 with measurable acceptance criteria per =todo-format.md='s "Making an open-ended task measurable," which is what makes it =:solo:=. The four moves:
+
+1. *Bound the surface.* The 22 functions are the done-set. *Covered* (behaviorally, via =scripts/tests/ai-launcher-runtime.bats=, 9 tests over the runtime path): =resolve_agent_cmd=, =build_runtime_choices=, =pick_runtime=, =build_instructions=, the print modes. *Uncovered* (the 17 to bring under test): =usage=, =check_deps=, =attach_session=, =create_window=, =maybe_add_candidate=, =build_candidates=, =fetch_candidates=, =git_status_indicator=, =annotate_candidates=, =auto_pull_if_clean=, =read_selections=, =sort_windows=, =find_window_id=, =prep_git_single=, =attach_mode=, =single_mode=, =multi_mode=, =print_launch_mode=.
+
+2. *Net the behavior.* Characterization tests (Normal/Boundary/Error per unit, per =testing.md=) over the uncovered surface. The pure/near-pure ones take the category set directly: =git_status_indicator=, =maybe_add_candidate= (dedup), =annotate_candidates= (formatting), =read_selections= (selection parse), =usage=. The =tmux=/=git=-coupled ones (=sort_windows='s ordering, =create_window=, =attach_session=, =find_window_id=, =prep_git_single=, =auto_pull_if_clean=) get their pure decision logic extracted into helpers that take plain inputs and return plain results — that extraction *is* the hardening — with the I/O calls left as thin wrappers.
+
+3. *Disposition every finding.* (a) A bash-footgun audit per function, each cell fixed / n-a / filed: unquoted expansions + word-splitting, =set -euo pipefail= gaps and where errexit is intentionally off, subshell state loss, exit-code propagation, ordering/races in =sort_windows= + window creation, and the git-prep error paths (=prep_git_single= / =auto_pull_if_clean= on a dirty tree, detached HEAD, no upstream). (b) A =/refactor= pass, each finding applied (tests green) or declined with a one-line reason.
+
+4. *Objective floor.* =shellcheck= clean, =shfmt=-consistent, =make test= green before and after, and every uncovered function above has its characterization set (a per-function checklist — =kcov= isn't installed; install it if a single coverage number is wanted). Plus ~3 functional tests over the launch pipelines (=single_mode=, =multi_mode=, =attach_mode=) against a throwaway =tmux= session, for the composition bugs no per-function unit can see.
+
+*Qualifying answer:* a dispositioned report — surface split covered/uncovered, tests before → after, =shellcheck=/=shfmt= result, the footgun matrix fully dispositioned, the =/refactor= findings fully dispositioned, all green. Not "no bugs remain" (unprovable) — "every enumerated path passes its characterization set and clears the audit."
+
+*Out of this task's =:solo:= scope:* an interactive runtime picker. It's a feature carrying a design/preference call (does Craig want it, what shape), which is deliberation, not hardening — file it separately if wanted. The runtime-selection arc (claude/codex shipped; ollama/qwen pending the model-floor eval) stays on the generic-agent-runtime parent.
** TODO [#B] Extend ui-prototyping rule with build-to-prototype :feature:
:PROPERTIES: