aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-15 08:44:03 -0500
committerCraig Jennings <c@cjennings.net>2026-06-15 08:44:03 -0500
commitb0503dfe7028af1fab3bfb77b474b1b57c801e7e (patch)
treeb80710fd2949e412bd282745699f2fc22e58b082
parentbef1d6658aa1a48256b3325c5c3fee3688121fca (diff)
downloadrulesets-b0503dfe7028af1fab3bfb77b474b1b57c801e7e.tar.gz
rulesets-b0503dfe7028af1fab3bfb77b474b1b57c801e7e.zip
chore(ai): archive session record, note helper-instance resume plan
-rw-r--r--.ai/sessions/2026-06-15-08-43-czsusp-epoch-helper-instance-slices.org61
-rw-r--r--todo.org17
2 files changed, 70 insertions, 8 deletions
diff --git a/.ai/sessions/2026-06-15-08-43-czsusp-epoch-helper-instance-slices.org b/.ai/sessions/2026-06-15-08-43-czsusp-epoch-helper-instance-slices.org
new file mode 100644
index 0000000..7d150d5
--- /dev/null
+++ b/.ai/sessions/2026-06-15-08-43-czsusp-epoch-helper-instance-slices.org
@@ -0,0 +1,61 @@
+#+TITLE: Session Context
+#+DATE: 2026-06-14
+
+* Summary
+
+** Active Goal
+
+Fix an accidental C-z that suspended Claude, clear two interrupted 2026-06-13 session anchors, document the helper-agent epoch-id convention, then start the helper-instance support feature (#B) — shipping its first two slices.
+
+** Decisions
+
+- C-z suspend: scope the disable to ai-launched panes only (stty susp undef in the launcher), not globally. Keybindings.json can't touch it — C-z is raw tty SIGTSTP, not a Claude Code keybinding.
+- Helper-agent id uniqueness: epoch lives in AI_AGENT_ID, baked in by the spawner, convention-only. It can't be minted inside session-context-path (the resolver must return the same path across many calls per session).
+- For the rest of the session: commit and push together, don't hold pushes (Craig).
+- Helper-instance build order: agent-roster first (the detection primitive), then helper-mode.org (the contract); both inert. The behavior-changing wiring stays behind the spec's bats→drills→pilot gate.
+- agent-roster exit codes 0=alone / 1=others / 2=unavailable; pgrep-absent hardened to exit 2 (never silent-alone) after a review Minor.
+
+** Data Collected / Findings
+
+- Real terminal is foot → tmux → Claude (not "ghostel"; ghostel is the separate Emacs-native terminal, per the spec).
+- agent-roster live-verified against 4 concurrent real sessions: alone in rulesets (own session excluded via ancestry, 3 out-of-project claudes excluded by cwd), not-alone in ~/.emacs.d (2 agents listed).
+- helper-mode.org orphan-drift wrinkle solved by a triggerless INDEX catalog entry (startup.org's existing pattern) — no integrity-checker or startup.org change.
+
+** Files Modified
+
+- claude-templates/bin/ai — LAUNCH_PREFIX="stty susp undef; " at the three launch sites (C-z fix). Commit dedbca3.
+- .ai/sessions/2026-06-13-* (x2) + notes.org marker — archived yesterday's interrupted anchors. Commit 16e64fb.
+- protocols.org + wrap-it-up.org + session-context-path header — epoch-on-tail convention. Commit e0f914d.
+- .ai/scripts/agent-roster + tests (canonical+mirror) — detection primitive, 11 bats. Commit f8bdf30.
+- .ai/workflows/helper-mode.org (new) + INDEX.org + protocols.org pointer — helper contract. Commit 0b681dc.
+- todo.org — helper-instance DOING + resume note + Craig's open question. Commits 25bde1f-era flip, bef1d66, and wrap.
+
+** Next Steps
+
+Helper-instance is the big item next session. Re-orient on what it is/does/why before building (resume note in the helper-instance task body). Answer Craig's open question first: does helper-instance depend on the generic-agent-runtime work, or is Phase 1.5 genuinely independent of phases 2-6? Then the gated wiring: startup roster branch, wrap-it-up helper branch, ai --helper launcher (+ Emacs surface via .emacs.d handoff), hygiene live-helper gate, todo-cleanup.el /tmp backstop — all behind the drill rig.
+
+KB: promoted 0 / consulted no
+
+* Session Log
+
+** 2026-06-14 Sun @ 17:52 CDT — Startup, then disable C-z suspend in ai-launched Claude panes
+
+New session (2026-06-14). Startup found two un-wrapped 2026-06-13 anchors (the main session-context.org + session-context.d/codex.org) with all work already pushed; offered cleanup but Craig pivoted to a live problem: he accidentally hit C-z during the session, suspending Claude to the shell. Wants C-z's suspend disabled but scoped, not nuked machine-wide.
+
+Diagnosed the layers: foot (terminal) → tmux → Claude Code. tmux has no root C-z binding, so C-z passes through to the pane's tty, which generates SIGTSTP. Confirmed via the keybindings skill that ctrl+z is NOT a Claude Code keybinding action — it's listed under Reserved Shortcuts as Unix SIGTSTP, no action mapped — so keybindings.json can't touch it. Fix has to be at the tty layer (stty susp undef).
+
+Craig picked launcher-scoped over global zshrc. Edited claude-templates/bin/ai: added a commented LAUNCH_PREFIX="stty susp undef; " var after CLAUDE_CMD, prepended it at all three tmux send-keys launch sites (lines ~76, ~321, ~381). Scopes the disable to exactly the ai-launched Claude pane; C-z keeps working everywhere else. Verified: bash -n clean, all three sites carry the prefix, stty susp undef in a real pty leaves susp = <undef>. Live now via the ~/.local/bin/ai symlink, but only for NEW ai-launched sessions — the current running session keeps its old tty setting. /review-code Approve, /voice personal walk, committed dedbca3 (unpushed). Note: with susp undef the 0x1a byte now reaches Claude as input (no binding → expected to be ignored).
+
+Then Craig's task order: (2) commit the C-z fix [done, dedbca3], (3) clean up yesterday's two un-wrapped anchors, (1) return to the epoch-suffix thread. Cleanup: split yesterday's shipped 12:11 session out of this anchor into .ai/sessions/2026-06-13-12-11-inbox-zero-build-and-session-title.org (Summary populated), archived the codex sub-session to .ai/sessions/2026-06-13-15-29-codex-inbox-ack.org and removed session-context.d/codex.org, reset this anchor to today only.
+
+Then the epoch thread (task 1). Lost the original design in the crash, so reconstructed from code and surfaced the determinism constraint (session-context-path is called many times per session and must return the same path, so it can't mint date +%s; the Bash tool also drops env between calls, so the agent can't export once). Craig picked option 1: epoch baked into AI_AGENT_ID by the spawner, convention-only, no resolver change. Documented the convention in three canonical spots (protocols.org Agent-scoped path, wrap-it-up.org recommended-shape note, session-context-path header comment), with the 2026-06-13 codex collision as the worked example. sync-check --fix paired the mirror; session-context-path.bats still 5/5 green (comment-only). /review-code Approve, /voice personal walk, committed e0f914d.
+
+Session commits: dedbca3 (C-z fix), 16e64fb (archive yesterday's two anchors + inbox marker), e0f914d (epoch convention docs). Pushed bbd07b6..e0f914d. Craig then set "commit and push together for the rest of this session."
+
+Then started the helper-instance task (#B, DOING) via start-work, first slice only: the agent-roster detection script. Built claude-templates/.ai/scripts/agent-roster + tests/agent-roster.bats (11 tests), synced to mirror. Algorithm per spec: pgrep -x claude, /proc cwd resolution, cwd-within-root filter, self-ancestry exclusion. Exit 0 alone / 1 others / 2 unavailable. pgrep + /proc + self-pid injectable (ROSTER_PGREP/PROC/SELF_PID) so bats run the real filter against fixtures, no agents spawned. TDD red→green. Live-verified against the real process tree: alone in rulesets (own session excluded via ancestry, 3 out-of-project claudes excluded by cwd, exit 0), not-alone against ~/.emacs.d (2 live agents listed, exit 1). /review-code flagged one Minor (pgrep-absent read as silent-alone, violating the spec's never-silent-alone invariant); hardened it with a command -v guard → exit 2 (TDD red→green, 11th test). make test exit 0 (180 ok). Committed f8bdf30, pushed e0f914d..f8bdf30. todo task stays DOING (epic; slice 1 of ~7 done).
+
+Slice 2: helper-mode.org workflow contract (the spec's "single canonical home" of helper rules). Authored claude-templates/.ai/workflows/helper-mode.org — Overview + subagent boundary, When-to-Use (no trigger, three routing paths), Identity (helper-<rand4>, self-assign, recorded as first line of .d/ file), four read/write tiers, four data-integrity rules + inbox-send slug nit, Light Startup, Helper Wrap-Up (orphaned-helper lifts git ban), Status (wiring gated/not-live). Solved the orphan-drift-check wrinkle via a triggerless INDEX catalog entry (startup.org's pattern) — no integrity-checker or startup.org change. Added protocols.org one-paragraph pointer. Synced mirror. workflow-integrity OK (45 workflows), make test exit 0 (180 ok), /review-code Approve. Committed 0b681dc, pushed f8bdf30..0b681dc.
+
+Remaining slices, all behind the spec's bats→drills→pilot gate (change live session behavior in synced paths): startup roster-detection branch, wrap-it-up helper branch, ai --helper launcher (+ ai-term.el via .emacs.d handoff), hygiene-pass live-helper gate, todo-cleanup.el /tmp backstop.
+
+Stopped here for the session (Craig's call). Durable resume note filed in the helper-instance task body in todo.org — what it is/does/why plus done-vs-next — flagged to re-orient on the feature's purpose before picking it up as the big item next session. The wiring is the gated, drill-rig half. Not a full wrap-up; this anchor stays live.
diff --git a/todo.org b/todo.org
index 4525e0c..0cd0ebe 100644
--- a/todo.org
+++ b/todo.org
@@ -82,6 +82,8 @@ What's next — the WIRING, all behind the spec's three-ring gate (bats → sand
Stand up a drill rig before the gated work; build against it, don't touch synced paths until the live drill passes.
+OPEN QUESTION to answer first (Craig, 2026-06-15): doesn't helper-instance support depend on generic agent runtime support? Resolve before treating the wiring as unblocked. Starting point: the spec frames this work as Phase 1.5, "Independent of the spec's phases 2-6 (runtime-neutral refactor), which stay gated on their own go/no-go," and the body claims it sits only on the already-shipped session-context split. The separate =Generic agent runtime support — Codex spec v0= task (#C, below) is that phases-2-6 arc. So the spec's stated answer is "no, 1.5 is independent" — but confirm that's actually true for every wiring slice (does ai --helper, the roster branch, or helper-mode routing secretly assume any runtime-manifest / multi-runtime machinery from 2-6?), or whether helper-instance should be sequenced after, or merged into, the generic-runtime task. Don't build the gated wiring until this is settled.
+
** DOING [#C] Check that memories are sync'd across machines via git :spec:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-12
@@ -1077,14 +1079,6 @@ Codex ran the spec-review workflow. Outcome: the combined spec is =Not ready= be
*** 2026-06-12 Fri @ 02:39:38 -0500 Second review after response pass
Codex re-ran spec-review after the dispositions were folded in. Outcome by arc: Phase 1.5 helper instances =Ready with caveats=; phases 2-5 remain =Not ready= behind the explicit decisions/reverification gate. No new blocking findings for the helper slice. Review file updated in place: [[file:docs/design/2026-05-28-generic-agent-runtime-spec-review.org]].
-** DONE [#C] Session title hostname-project, no space :feature:quick:
-CLOSED: [2026-06-13 Sat]
-:PROPERTIES:
-:CREATED: [2026-06-13 Sat]
-:LAST_REVIEWED: 2026-06-13
-:END:
-Routed from the roam global inbox via inbox-zero 2026-06-13. The SessionStart hook (=hooks/session-title.sh=) emitted =<host> <project>= with a space; Craig wanted =<host>-<project>= with a hyphen and no space. Changed the =sessionTitle= join to ="$host-$project"= plus the header comments, and updated the three =session-title-hook.bats= expectations (test-first; 6/6 green).
-
* Rulesets Resolved
** DONE [#C] Fix =cj-scan= false positives on cj fences nested inside other =#+begin_*= blocks :bug:
CLOSED: [2026-05-15 Fri]
@@ -2722,3 +2716,10 @@ CLOSED: [2026-06-12 Fri]
Observed at the 2026-06-12 wrap: the pass relocated closed subtrees from Open Work to Resolved while printing "todo-cleanup --archive-done: 0 subtree(s) moved".
CANCELLED 2026-06-12 — cannot reproduce. =todo-cleanup.el= is unchanged since the wrap that logged this, and =tc-archived= is incremented inline with each move and read straight in the report, so no move can go uncounted. Running the exact pre-archive state (=b6d286f:todo.org=) through the tool reports the right count (3 moved, all listed). The "0 moved" was a correct second-run report: =open-tasks.org= Phase A runs =--archive-done= after wrap-it-up already archived, so the second pass finds nothing to move and prints 0 next to the first pass's git diff. Not a code defect.
+** DONE [#C] Session title hostname-project, no space :feature:quick:
+CLOSED: [2026-06-13 Sat]
+:PROPERTIES:
+:CREATED: [2026-06-13 Sat]
+:LAST_REVIEWED: 2026-06-13
+:END:
+Routed from the roam global inbox via inbox-zero 2026-06-13. The SessionStart hook (=hooks/session-title.sh=) emitted =<host> <project>= with a space; Craig wanted =<host>-<project>= with a hyphen and no space. Changed the =sessionTitle= join to ="$host-$project"= plus the header comments, and updated the three =session-title-hook.bats= expectations (test-first; 6/6 green).