aboutsummaryrefslogtreecommitdiff
path: root/docs/design
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-23 22:38:43 -0400
committerCraig Jennings <c@cjennings.net>2026-06-23 22:38:43 -0400
commit27da1f1d3290314d32455eac4e049118b00a7a13 (patch)
tree900cd462338236f16b0ecae17f942dfb239e0eab /docs/design
parent6ad044254ee6e7504429b4aba0ef39a71242e599 (diff)
downloadrulesets-27da1f1d3290314d32455eac4e049118b00a7a13.tar.gz
rulesets-27da1f1d3290314d32455eac4e049118b00a7a13.zip
docs: inbox-consolidation spec + backlog filings
The inbox-workflow consolidation reached a Ready spec — one inbox.org engine with process/monitor/roam modes, plus "auto inbox zero" as the interactive recurring roam check (the fully-unattended cron pass deferred to vNext). Files the backlog surfaced while triaging the inbox: the wrap-it-up teardown proposal, the agent-source improvements, the consolidation task itself, and the deferred unattended-cron pass.
Diffstat (limited to 'docs/design')
-rw-r--r--docs/design/2026-06-23-wrap-teardown-shutdown-proposal.org124
1 files changed, 124 insertions, 0 deletions
diff --git a/docs/design/2026-06-23-wrap-teardown-shutdown-proposal.org b/docs/design/2026-06-23-wrap-teardown-shutdown-proposal.org
new file mode 100644
index 0000000..a47aa2d
--- /dev/null
+++ b/docs/design/2026-06-23-wrap-teardown-shutdown-proposal.org
@@ -0,0 +1,124 @@
+#+TITLE: Proposal — wrap-it-up teardown + "wrap it up and shutdown" variant
+
+* Source
+
+Raised by Craig in a home-project session, 2026-06-23, after talking the
+design through. Two related additions to =wrap-it-up.org=. Both touch the
+Claude-session lifecycle (workflow + hook + the =ai-term= buffer/tmux pair),
+so they're rulesets — with one companion piece that has to live in
+=.emacs.d/modules/ai-term.el= (flagged below). Originally floated as an
+archsetup task; archsetup owns the Hyprland/waybar layer, not the
+Claude-session lifecycle, so it was re-routed here.
+
+* Architecture this depends on (so the design is grounded)
+
+- =ai-term.el= (=.emacs.d=) is the in-Emacs launcher: a vertical-split vterm
+ buffer running a tmux session named =aiv-<project-basename>= (prefix
+ =aiv-=). Layering: =claude= process → tmux session =aiv-<proj>= → Emacs
+ vterm buffer.
+- Killing the tmux session takes the =claude= process with it, so "quit
+ Claude Code" is a *consequence* of killing =aiv-<proj>=, not a separate
+ step.
+- Hooks already exist under =~/.claude/hooks/= (e.g. =session-clear-resume.sh=,
+ =precompact-priorities.sh=) — the teardown trigger fits that pattern.
+- =sudo= is =NOPASSWD: ALL= on Craig's machines, so =sudo shutdown now= runs
+ unattended.
+
+* Item 1 — wrap-up also removes the buffer, quits Claude, removes the tmux session
+
+Recommend: yes, with one structural rule — the wrap-up runs *inside* the
+things it tears down, so teardown is self-terminating and must be the last,
+decoupled action, or the valediction may not flush before the session dies.
+
+Design:
+1. *Teardown lives in =ai-term.el=* (companion, see below): one function
+ =cj/ai-term-quit= that kills the =aiv-<proj>= tmux session (takes =claude=
+ with it), kills the vterm buffer, and restores the saved window geometry —
+ =ai-term.el= already owns the buffer↔session pair and the geometry logic.
+2. *Trigger from a Stop / SessionEnd hook, not inline.* Wrap-up does all its
+ git/archive work, delivers the valediction, then drops a sentinel (flag
+ file, e.g. =/tmp/ai-wrap-teardown-<session>=). The hook fires when Claude
+ finishes, sees the sentinel, and runs =cj/ai-term-quit= via =emacsclient=.
+ Decoupling guarantees the valediction lands before the session dies.
+3. *Gate on commit+push verified* — never tear down before the session record
+ is pushed (wrap-up's existing Step 4 / validation checklist already
+ enforces push; teardown is strictly after it).
+4. *Phrase split — teardown IS the default* (Craig's decision 2026-06-23).
+ Bare "wrap it up" does the full wrap AND removes the buffer/session/quits —
+ that's his typical case. The non-destructive variant gets the explicit
+ qualifier: "wrap it up with summary" summarizes + commits + pushes +
+ archives but keeps the buffer (no teardown), so the summary stays readable.
+ So: "wrap it up" → teardown; "wrap it up with summary" → no teardown;
+ "wrap it up and shutdown" → wrap + poweroff (supersedes teardown, Item 2).
+
+* Item 2 — "wrap it up and shutdown": 10-count then =sudo shutdown now=
+
+Recommend: yes, but the safety gate is load-bearing and the countdown has a
+rendering gotcha.
+
+Design:
+1. *"Only ai-term left" = hard blocking precondition*, evaluated BEFORE the
+ countdown. Count live sessions (=tmux ls | grep '^aiv-'= or
+ =pgrep -fc claude=). If more than this one is alive, ABORT the shutdown,
+ list what's running, and fall back to a normal wrap. Never power the box
+ off out from under another active Claude session. This is the most
+ important part of the item.
+2. *The live countdown can't run through Claude's tool output.* The Bash tool
+ buffers stdout until the command returns, so a =for i in $(seq 10 -1 1);
+ sleep 1= prints all ten at once at the end, not one per second. It has to
+ run detached or in Emacs:
+ - tty writer: =for i in $(seq 10 -1 1); do printf '\rShutting down in %2d…'
+ "$i" > /dev/tty; sleep 1; done; sudo shutdown now= (backgrounded), or
+ - an Emacs =run-at-time= timer printing 10→1 in the echo area, then
+ =(shell-command "sudo shutdown now")=.
+3. *Make it abort-able* (Ctrl-C / keypress cancels). A 10-second countdown's
+ whole purpose is a last-chance window; a non-cancellable one is just a
+ delay.
+4. *Sequencing.* "...and shutdown" supersedes Item 1's teardown — if the box
+ is powering off, killing the buffer/session first is moot. Wrap (commit +
+ push + archive) → session-count gate → countdown → =shutdown=.
+
+Packaging: a small rulesets bin script (e.g. =ai-wrap-shutdown=) doing the
+gate → abort-able countdown → shutdown, invoked by the workflow after the wrap
+commit/push. Countdown either in that script (tty) or handed to Emacs.
+
+* Companion — required change in =.emacs.d/modules/ai-term.el=
+
+Item 1's teardown function =cj/ai-term-quit= must live in =ai-term.el= (it
+owns =aiv-<proj>= session naming, the vterm buffer, and geometry restore).
+rulesets owns the workflow + hook + bin script that *call* it; =.emacs.d= owns
+the function itself. Spec for the =.emacs.d= side:
+
+- =cj/ai-term-quit (&optional project)= — resolve the =aiv-<basename>= session
+ for the current/!named project, =tmux kill-session= it, =kill-buffer= the
+ associated vterm buffer, restore saved geometry. Idempotent / no-op if the
+ session or buffer is already gone. Callable from =emacsclient -e= so the
+ Stop hook can invoke it headlessly.
+- (Optional) a count helper =cj/ai-term-live-count= so the Item-2 gate can ask
+ Emacs how many ai-term sessions are live, as an alternative to =tmux ls= /
+ =pgrep=.
+
+When rulesets builds the workflow/hook side, route this companion to
+=.emacs.d= (inbox-send) so the two land together.
+
+* Open decisions for Craig
+
+- Phrase set: DECIDED (2026-06-23) — "wrap it up" tears down (default);
+ "wrap it up with summary" wraps without teardown; "wrap it up and shutdown"
+ is the poweroff variant. Remaining nuance: confirm the exact non-destructive
+ qualifier wording is "with summary" (vs e.g. "and summarize").
+- Countdown home: tty-writer bin script vs Emacs timer. (Emacs timer reads
+ cleaner inside the vterm and is trivially abort-able.)
+- Session-count mechanism for the gate: =tmux ls=, =pgrep claude=, or
+ =cj/ai-term-live-count=.
+
+* Verify
+
+- Item 1: bare "wrap it up" → valediction renders fully, THEN buffer +
+ =aiv-<proj>= session + claude all gone, geometry restored; "wrap it up with
+ summary" → wrap completes but the buffer stays intact (no teardown).
+- Item 2 gate: with a second =aiv-*= session alive, "wrap it up and shutdown"
+ refuses, lists the other session, and does a normal wrap (no poweroff).
+- Item 2 happy path: sole session → 10→1 renders one-per-second, is
+ cancellable, then =shutdown= fires.
+- Teardown never runs before commit+push is verified.