Nebenbefund aus #60 (PR #68). Dieselbe Ursache, anderer Konsument: Der bash-Job-Pfad geht davon aus, dass ein headless Lauf keine Session hat — das stimmt seit 25dfef6 („session names, continue, context breakdown") nicht mehr.
Verifiziert
smith run --yes mit einem Background-Job (Stub-Provider, isoliertes SMITH_HOME), danach das Home-Verzeichnis:
~/sessions/session-1787759268-750667
~/sessions/session-1787759268-750667/bash <- das Log liegt hier
Kein smith-bash-<pid> im Temp-Verzeichnis. (Die smith-bash-*-Verzeichnisse, die man dort trotzdem findet, stammen aus crystal spec: Tools::Bash#initialize legt sich einen eigenen BashJobs an, wenn keiner injiziert wird — src/smith/tools/bash.cr:21. Das ist ein anderer, unkritischer Pfad.)
Ist-Zustand
@session_id ist mit "headless" vorbelegt (src/smith/cli.cr:48), und daran hängen zwei Zweige:
private def bash_jobs_dir : String
return File.join(@session_store.session_dir(@session_id), "bash") unless @session_id == "headless"
File.join(Dir.tempdir, "smith-bash-#{Process.pid}")
end
FileUtils.rm_rf(jobs.dir) if @session_id == "headless" && Dir.exists?(jobs.dir)
bash_jobs_dir wird ausschließlich aus build_agent heraus aufgerufen (src/smith/cli.cr:589, lazy über @bash_jobs ||=). Alle vier build_agent-Aufrufstellen setzen @session_id vorher auf die echte Session-Id:
| Aufrufstelle |
@session_id gesetzt in |
run_headless (Z. 743) |
Z. 741, direkt davor |
resume_headless (Z. 860) |
Z. 858, direkt davor |
run_plain_loop (Z. 892) |
start_session_loop, Z. 877 |
run_tui_loop (Z. 955) |
start_session_loop, Z. 877 |
Damit ist @session_id == "headless" zum Zeitpunkt beider Prüfungen nie wahr. Der Temp-Zweig und die Aufräumzeile sind toter Code.
Was falsch dokumentiert ist
README, Abschnitt „Background Commands":
Output is written to ~/.smith/sessions/<id>/bash/<job>.log rather than kept in memory, so a chatty job cannot grow without bound. A headless run has no session, so its jobs use a per-process temporary directory that is removed with them.
Der zweite Satz beschreibt Verhalten, das es nicht gibt. Dasselbe Muster wie die beiden Sätze, die #60 korrigiert hat — der Body von #60 hat diesen Satz sogar als Vorbild für ein temporäres Checkpoint-Verzeichnis zitiert, das sich dann als unnötig herausstellte.
Gewünschtes Verhalten
Eine Entscheidung, kein Zwischending:
- Toten Code entfernen.
bash_jobs_dir gibt immer das Session-Verzeichnis zurück, @session_id braucht keinen "headless"-Sentinel mehr (falls ihn nichts anderes benutzt — Hooks::Runner bekommt ihn in Z. 469, das ist zu prüfen), die rm_rf-Zeile in shutdown_bash_jobs entfällt, der README-Satz wird gestrichen.
- Oder: es gibt einen Grund, warum irgendein Einstieg ohne Session laufen können soll — dann muss der Zweig erreichbar gemacht werden, statt unerreichbar dazustehen.
Aus heutiger Sicht spricht alles für (1): Jeder Lauf legt eine Session an, und seit #60 hängen auch die Checkpoints daran.
Akzeptanzkriterien
Nicht-Ziele
Tools::Bash#initialize und sein Default-BashJobs (anderer Pfad, betrifft nur Specs und direkte Benutzung der Klasse)
- Änderungen an der Lebensdauer oder Terminierung von Jobs
Nebenbefund aus #60 (PR #68). Dieselbe Ursache, anderer Konsument: Der
bash-Job-Pfad geht davon aus, dass ein headless Lauf keine Session hat — das stimmt seit 25dfef6 („session names, continue, context breakdown") nicht mehr.Verifiziert
smith run --yesmit einem Background-Job (Stub-Provider, isoliertesSMITH_HOME), danach das Home-Verzeichnis:Kein
smith-bash-<pid>im Temp-Verzeichnis. (Diesmith-bash-*-Verzeichnisse, die man dort trotzdem findet, stammen auscrystal spec:Tools::Bash#initializelegt sich einen eigenenBashJobsan, wenn keiner injiziert wird —src/smith/tools/bash.cr:21. Das ist ein anderer, unkritischer Pfad.)Ist-Zustand
@session_idist mit"headless"vorbelegt (src/smith/cli.cr:48), und daran hängen zwei Zweige:bash_jobs_dirwird ausschließlich ausbuild_agentheraus aufgerufen (src/smith/cli.cr:589, lazy über@bash_jobs ||=). Alle vierbuild_agent-Aufrufstellen setzen@session_idvorher auf die echte Session-Id:@session_idgesetzt inrun_headless(Z. 743)resume_headless(Z. 860)run_plain_loop(Z. 892)start_session_loop, Z. 877run_tui_loop(Z. 955)start_session_loop, Z. 877Damit ist
@session_id == "headless"zum Zeitpunkt beider Prüfungen nie wahr. Der Temp-Zweig und die Aufräumzeile sind toter Code.Was falsch dokumentiert ist
README, Abschnitt „Background Commands":
Der zweite Satz beschreibt Verhalten, das es nicht gibt. Dasselbe Muster wie die beiden Sätze, die #60 korrigiert hat — der Body von #60 hat diesen Satz sogar als Vorbild für ein temporäres Checkpoint-Verzeichnis zitiert, das sich dann als unnötig herausstellte.
Gewünschtes Verhalten
Eine Entscheidung, kein Zwischending:
bash_jobs_dirgibt immer das Session-Verzeichnis zurück,@session_idbraucht keinen"headless"-Sentinel mehr (falls ihn nichts anderes benutzt —Hooks::Runnerbekommt ihn in Z. 469, das ist zu prüfen), dierm_rf-Zeile inshutdown_bash_jobsentfällt, der README-Satz wird gestrichen.Aus heutiger Sicht spricht alles für (1): Jeder Lauf legt eine Session an, und seit #60 hängen auch die Checkpoints daran.
Akzeptanzkriterien
bash_jobs_dirhat keinen unerreichbaren Zweig mehr"headless"-Sentinel in@session_idist entfernt oder seine verbleibenden Konsumenten sind benannt und begründetcrystal specgrün,crystal tool formatsauberNicht-Ziele
Tools::Bash#initializeund sein Default-BashJobs(anderer Pfad, betrifft nur Specs und direkte Benutzung der Klasse)