agnes-the-ai-analyst/cli
ZdenekSrotyr 8d0bb43b06
release: 0.46.4 — detach SessionEnd push so it survives claude -p SIGTERM (#222)
## Summary

`claude -p` (headless mode) gives SessionEnd hook subprocesses ~1 second before SIGTERM, regardless of work in progress. `agnes push` for a typical workspace takes 5-30s. The current synchronous SessionEnd hook (`agnes push --quiet 2>/dev/null || true`) was therefore being killed mid-first-upload — `|| true` masks the SIGTERM as exit 0, so this regression was invisible until I traced it via a wrapper script and Claude's `~/.claude/debug/<sid>.txt` log.

Fix: wrap SessionEnd push in `bash -c "( nohup agnes push --quiet </dev/null >/dev/null 2>&1 & ) ; true"`. The subshell exits immediately, orphaning the upload child to init so it survives the hook subprocess kill. Same `bash -c` pattern as the existing `refresh-marketplace` SessionStart entry (for Windows compatibility).

End-to-end verified against production: claude exited in 5s, detached child completed the upload, file `491e3a23-...jsonl` landed on the server within 30s with mtime 14:30 UTC.

## Test plan

- [x] `pytest tests/test_lib_hooks.py` — added `test_session_end_push_is_detached` regression test asserting `nohup`, `&`, `</dev/null` are all present.
- [x] `pytest tests/test_setup_hooks_template.py` — assertions loosened from `==` to `in` where necessary.
- [x] Verified end-to-end against production with the detached wrapper before opening this PR (manual probe).
<!-- devin-review-badge-begin -->

---

<a href="https://app.devin.ai/review/keboola/agnes-the-ai-analyst/pull/222" target="_blank">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
    <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open in Devin Review">
  </picture>
</a>
<!-- devin-review-badge-end -->
2026-05-07 17:59:27 +02:00
..
commands release: 0.46.2 — friendlier hint on missing-table errors for remote tables (#219) 2026-05-07 17:24:10 +02:00
lib release: 0.46.4 — detach SessionEnd push so it survives claude -p SIGTERM (#222) 2026-05-07 17:59:27 +02:00
skills chore(docs): replace stale da verbs and vendor-specific install paths 2026-05-04 21:22:19 +02:00
__init__.py feat: add Docker, CLI tool, scheduler, and agent skills 2026-03-27 15:30:03 +01:00
client.py release: 0.45.0 — easy-wins bundle (#84 #164 #177 #178 #203 #204) 2026-05-07 11:43:16 +02:00
config.py fix(devin-review): stale-token override + status sessions counter + lock comment 2026-05-04 21:26:30 +02:00
error_render.py chore(cli-rename): replace stale da verbs in active code paths 2026-05-04 21:10:43 +02:00
main.py feat(marketplace): clone-based plugin setup + auto-refresh SessionStart hook 2026-05-07 06:59:13 +02:00
snapshot_meta.py chore(cli-rename): replace stale da verbs in active code paths 2026-05-04 21:10:43 +02:00
update_check.py chore: rename stale 'da' references to 'agnes' + CHANGELOG 2026-05-06 23:23:59 +02:00
v2_client.py feat(store): bundle export/import + agnes store update + agnes admin store push 2026-05-05 11:51:31 +02:00