Skip to content

Feature: session watch — JSONL change stream via polling + session_diff #99

Description

@6uclz1

Context

The protocol is strictly request/response; agents cannot react to session changes (playback position, tempo, clip states) without hand-rolled polling. src/ableton_cli/session_diff.py already implements a recursive snapshot diff (compute_session_diff). This issue adds a polling watch command emitting one JSON line per detected change. Push-based LOM listeners are explicitly deferred (would require protocol changes); polling + diff is the right first step.

Scope

  1. New CLI command session watch:
    • Options: --interval-ms (default 500, min 50), --scope song|tracks|transport|all (default all), --count N (stop after N emitted diffs; required for testability, default unlimited), --include-position/--no-include-position (playback position changes every poll while playing; default excluded to avoid noise).
    • Behavior: take snapshot via existing read commands for the scope → sleep interval → snapshot → compute_session_diff(prev, cur) → if non-empty, print one compact JSON line {"ts": <iso8601>, "diff": {...}} and flush → repeat. SIGINT exits with code 0.
  2. Snapshot assembly lives in a pure function build_watch_snapshot(client, scope) -> dict in a new src/ableton_cli/watch.py; filtering of position fields is a pure function strip_volatile(snapshot, include_position: bool).
  3. Read-only: side_effect metadata kind: "read". No new remote commands.

Non-goals

  • LOM listener push events, subscriptions over the TCP protocol, or protocol_version changes.
  • Sub-50ms latency (use batch stream for low-latency command loops instead; see SKILL.md).

TDD plan

  1. RED: tests/test_watch.py — fake client returning a scripted sequence of snapshots; assert: no output when consecutive snapshots equal; one JSONL line with correct diff shape when tempo changes; --count 2 stops after two diffs; position excluded by default and included with the flag.
  2. RED: interval validation (--interval-ms 10 → INVALID_ARGUMENT).
  3. GREEN, REFACTOR; regenerate snapshot/skill docs for the new CLI command.

Acceptance criteria

  • Deterministic tests with zero sleeping (inject a fake clock/sleep function).
  • Output is valid JSONL (one object per line, flushed), suitable for jq and agent consumption.
  • Harness layering clean (watch.py in core imports only client protocol types, not commands).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions