Skip to content

feat(cli): hooks-friendly mm session start primitives (RFC Phase 1)#541

Merged
memtomem merged 1 commit intomainfrom
feat/hooks-session-cli
Apr 29, 2026
Merged

feat(cli): hooks-friendly mm session start primitives (RFC Phase 1)#541
memtomem merged 1 commit intomainfrom
feat/hooks-session-cli

Conversation

@memtomem
Copy link
Copy Markdown
Owner

Summary

Phase 1 of the hooks-session-cli RFC (memtomem-docs#24): adds the CLI
primitives a SessionStart hook needs without orphaning prior
sessions.

  • mm session start --idempotent returns the active session for
    the same --agent-id instead of creating a new one. Cross-agent
    collisions auto-end the previous session.
  • mm session start --auto-end-stale=<duration> (e.g. 24h,
    7d) closes any active session older than the duration before
    resolving idempotency. Opt-in only.
  • mm session start --json emits {"session_id": ..., "resumed": bool, "stale_ended": [...]} for hook parsing.

Storage backing: find_stale_active_sessions(started_before)
filters on ended_at IS NULL AND started_at < ? — a dedicated
method instead of forcing every caller to load list_sessions and
filter in Python.

Why this is Phase 1 only

The plugin's hooks.json SessionStart entry, the docs example in
docs/guides/integrations/claude-code.md, and the
TestPluginHooksDocsParity extension all ship in a follow-up PR.
Decoupling lets reviewers gate the CLI contract before the hook
surface depends on it. PR #536 documented the same staging.

Verification

  • 6 unit tests on mm session start covering RFC §Verification's
    five behaviours (same-agent idempotent, cross-agent end+new, manual
    end then fresh, auto-end-stale, JSON shape) plus an
    invalid-duration guard.
  • 1 storage test on find_stale_active_sessions against real
    SQLite — avoids the AsyncMock-hides-SQL-bugs trap when the filter
    predicate is non-trivial.
  • ruff check, ruff format --check, mypy (advisory) all
    green on the changed files.

Open questions decided in this PR (§ in RFC)

  • Q1 same-agent semantics → return existing (recommended)
  • Q2 cross-agent collision → end old, start new (recommended)
  • Q4 caller identification → --agent-id literal (recommended)
  • Q5 race window → no advisory lock (recommended)
  • Q6 manually-ended state file → treat as advisory, create fresh (recommended)

Q3 (default stale duration) is a docs decision, defers to Phase 2.

Test plan

  • Reviewer: confirm the JSON output keys match RFC §Implementation
    sketch (session_id, resumed, stale_ended)
  • Reviewer: confirm --auto-end-stale parses 24h/7d/
    30m/45s and rejects garbage with a Click error
  • Reviewer: confirm Phase 2 (docs + plugin hooks.json) staying in
    a follow-up PR matches the project's preferred cadence

🤖 Generated with Claude Code

Add the SessionStart hook primitives requested by the RFC at
``memtomem-docs/memtomem/planning/hooks-session-cli-rfc.md``:

- ``--idempotent`` returns the active session for the same agent_id
  instead of creating a new one (RFC §Q1 recommendation a). On a
  cross-agent collision the old session is auto-ended (§Q2 a). When
  the state file points to an already-ended session, treat it as
  advisory and create fresh (§Q6 a).
- ``--auto-end-stale=<duration>`` ends active sessions whose
  ``started_at`` is older than the parsed duration before resolving
  idempotency (§Q3). Opt-in only — humans don't pay this cost.
- ``--json`` emits one structured line carrying ``session_id``,
  ``resumed``, and ``stale_ended``, the contract the eventual
  hooks.json entry will parse.

The plugin's ``hooks.json`` SessionStart entry, the docs example, and
the parity-test extension are explicit Phase 2 work and ship in a
follow-up PR — that lets reviewers gate on the CLI contract before
the hook surface depends on it.

Storage backing: ``find_stale_active_sessions(started_before)`` selects
``ended_at IS NULL AND started_at < ?``. Tested directly against real
SQLite (``test_sessions.py``) to avoid the AsyncMock-hides-SQL-bugs
trap.

Closes prerequisite for PR #536's deferred SessionStart hook (memtomem-docs#24).

Co-Authored-By: Claude <[email protected]>
@memtomem memtomem merged commit a430d08 into main Apr 29, 2026
7 checks passed
@memtomem memtomem deleted the feat/hooks-session-cli branch April 29, 2026 04:39
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants