aboutsummaryrefslogtreecommitdiff
path: root/inbox/PROCESSED-2026-07-20-0847-from-archsetup-suspend.org
blob: 166f9c95974430419db5d40caa074a66a5e1afad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#+TITLE: Session Suspend Workflow
#+AUTHOR: Craig Jennings
#+DATE: 2026-06-28

* Overview

This workflow captures the live state of a session when Craig must leave
abruptly, so a future session resumes with nothing lost. It is the fast,
capture-only workflow for departure: it writes down where every thread stands,
notes any uncommitted work, then STOPS — no cleanup, no archive, no teardown.

Triggered by Craig saying "suspend the session," "suspend," "I need to go,"
"stick a pin in everything," or similar. "I need to go" is broad — if it reads
as a conversational aside rather than a request to suspend, confirm before
running.

* Where suspend sits among its neighbors

Three workflows touch the session anchor (=.ai/session-context.org=); keep them
straight:

- =flush= ([[file:../../flush/SKILL.md]] / =/flush=) — *stay and sharpen.*
  Refreshes the anchor in place, prompts Craig to type =/clear=, and a hook
  resumes the *same* logical session in a fresh context. Craig is still here.
- *suspend* (this workflow) — *leave.* Captures richly into the anchor, leaves
  the file in place, detaches the tmux client so the session parks in the
  re-attachable set, and Craig walks away. The next session is a cold startup
  that detects the present anchor and resumes from it — or Craig re-attaches the
  still-live session directly.
- =wrap-it-up= ([[file:wrap-it-up.org][wrap-it-up.org]]) — *end.* Writes the
  Summary, archives the anchor into =.ai/sessions/=, commits + pushes, and runs
  the phrase-dependent teardown.

Suspend and flush share one core — capture into the anchor, leave it in place.
They differ in the exit (leave vs clear-and-continue) and the resume path
(startup vs the =/clear= hook). Suspend reuses flush's capture discipline (its
Phase 1 anchor-refresh) rather than restating it, and adds a richer,
resume-weighted Session Log entry because it's written for a cold resume after a
gap, not a same-session reset.

* Suspend vs wrap-up — the one structural difference

=wrap-it-up= ARCHIVES =.ai/session-context.org= (renames it into
=.ai/sessions/=); its absence at the next startup is the signal that the last
session ended cleanly.

Suspend does the opposite: it LEAVES =.ai/session-context.org= in place. Its
presence at startup is exactly the signal that the previous session was
interrupted, so the startup workflow reads it and resumes. Suspend provides only
the *capture* half — startup's existing interrupted-session path (Phase A checks
for the anchor, Phase B reads it, Phase C offers to resume) is the *resume* half,
already built.

So: never archive, never rename the context file in a suspend. Capture into it
and leave it.

* What gets captured

The point is zero lost information, weighted toward RESUME. Into the
=* Session Log= of =.ai/session-context.org=, append one dated
=** YYYY-MM-DD ... — SUSPENDED= entry holding:

1. *Open threads — resume here.* For each active or pending thread: the topic,
   its status (ACTIVE / PINNED / SET ASIDE / DEFERRED), the immediate next
   step, and the pointers needed to act on it cold (files + line numbers,
   commit SHAs, the specific finding or decision). This is the core; spend the
   most words here. Order newest / most-active first.
2. *Pending decisions / open questions* awaiting Craig — anything blocked on
   his input, with enough context that the answer is actionable.
3. *Shipped this session* — a terse list of what landed, each with its commit
   SHA, so the resume knows what is already done and need not re-derive it.
4. *Uncommitted work* — anything modified on disk but not committed, named
   file by file, so the resume knows what state the tree is in.
5. *Key findings not yet recorded elsewhere* — anything learned this session
   that isn't already in a commit, a file, or memory, so it survives.
6. *Background work* — any running task, agent, or job, and how to check it.
7. *Resume hint* — the single most likely "start here" next action.

Also update the top of =* Summary= (Active Goal) with a one-line SUSPENDED
pointer to the entry, so startup reading the top sees the current state even
when the Summary body is from an earlier thread.

* Steps

1. *Write the SUSPENDED entry* into the Session Log, per "What gets captured"
   above. Timestamp with =date "+%Y-%m-%d %a @ %H:%M:%S %z"=.
2. *Update the Active Goal pointer* at the top of =* Summary=.
3. *Record uncommitted work, don't force-commit it.* A suspend records state, it
   does not tidy it. Name every uncommitted change in the SUSPENDED entry and
   leave the tree as it is — on an abrupt departure, a dirty tree (like any
   crash) is safer than a blind commit of arbitrary mid-work state. (If a
   project defines a standing always-commit set in its own workflow, commit only
   that set — but the default shared behavior is to leave the tree alone.)
4. *Leave =.ai/session-context.org= in place.* Do not archive it.
5. *Brief handoff* — one or two lines: what was captured, where the resume
   pointer is, the most-active thread. This is the last thing Craig sees before
   the view detaches (Step 6), so deliver it complete.
6. *Detach the tmux client.* As the final action, detach the client viewing the
   =aiv-<project>= session so it drops out of Craig's active view while staying
   alive in the background. This is a DETACH, not a teardown: the session and the
   agent process keep running, nothing is killed, no context is lost.

   #+begin_src bash
   sess=$(tmux display-message -p '#S' 2>/dev/null)
   [ -n "$sess" ] && tmux detach-client -s "$sess"
   #+end_src

   Run it as the very last tool call, after the handoff text has rendered — tmux
   preserves the pane, so Craig sees the full handoff when he re-attaches. Unlike
   wrap-up's teardown (which must defer to a =Stop= hook because it kills the
   session the agent runs in, which would cut off the valediction), detach runs
   inline: it disconnects the view but leaves the agent's session alive, so
   nothing is cut off. Degrade gracefully — if not inside tmux (=$TMUX= unset, no
   session), skip silently and the session simply stays attached.

   Why detach on every suspend: Craig cycles his live agent sessions in Emacs
   with alt-space, and rotates through everything — including re-attaching
   detached ai-term sessions — with shift+alt+space. A suspended session left
   attached clutters the active rotation; detaching parks it in the
   re-attachable set, which is what makes suspend-and-walk-away work. Re-attach
   is one keystroke (shift+alt+space) or =tmux attach -t aiv-<project>=.

* What suspend does NOT do

Speed over completeness. A suspend deliberately skips everything wrap-it-up
does beyond capture:

- No =* Summary= rewrite beyond the one-line Active Goal pointer.
- No todo.org cleanup / archive-done.
- No KB / memory promotion sweep.
- No Linear / board reconciliation.
- No session-record archive (the file stays live).
- No teardown. Suspend DETACHES the tmux client (Step 6) but never kills the
  session: the =aiv-<project>= session and the agent process stay alive in the
  background, only the view disconnects. It drops no =Stop=-hook teardown
  sentinel, so the wrap-teardown hook stays dormant. Teardown — killing the
  session — is wrap-it-up's job, not suspend's; detach is the lighter move that
  parks a still-live session.
- No blind commit of working files (step 3).
- No valediction. A suspend is a pause, not a goodbye.

If Craig later wants the clean end, he runs wrap-it-up, which picks up the
captured state and finishes the job.