# Talking Stick 0.1.0-alpha.2

Date: 2026-04-26

Incremental alpha. Additive features and reliability fixes; no breaking
changes to the protocol or stored schema beyond an additive `notes`
table migration.

## New features

### Non-owner notes

Members of a room can now leave durable async observations for the current
owner and successors without holding the stick.

- New tools: `add_note`, `list_notes`.
- New CLI: `tt notes add <body> [--turn N] [--path DIR] [--stdin]` and
  `tt notes list [--all] [--after ID] [--limit N] [--path DIR]`.
- Notes are room-scoped by default or attached to a specific `turn_id`.
  Plain text body, ≤ 16 KB, append-only. Resolution is documented but
  out of scope for v1.
- Skill guidance updated: notes are observations and pointers, not
  permission for parallel edits. Run `list_notes` when you take the
  stick so you see what the room left for you.

### `wait_for_turn` owner-idempotency and richer `not_yet`

- Calling `wait_for_turn` while you already hold the stick returns
  `your_turn` (reason `already_owner`) with your existing `turn_id` /
  `lease_id` instead of falling through to `not_yet`. Stale-lease owners
  still fall through so they cannot keep using a dead lease.
- `not_yet` payload now carries `turn_id`, `current_owner`,
  `reserved_for`, `lease_expires_at`, and `claim_expires_at`. Harnesses
  and the CLI no longer need a follow-up `get_room_state` to describe
  the room.
- Removed the unused `cursor` parameter and field; resumable event
  replay belongs to `get_room_events`.
- `tt wait` short-circuits to the recorded session on `already_owner`
  and verifies the recorded guardian via a trim-tolerant liveness check
  before reporting it as still active. If the guardian is gone, a
  replacement is spawned.

### Human-readable `tt` CLI by default

- `tt wait` / `tt try`: when your turn arrives with a real handoff,
  status, next action, artifacts, open questions, and do-not entries
  render as indented sections instead of being hidden behind `--json`.
- `tt notes list`: bulleted rows with short note id, author, relative
  time (`13m ago` / `in 14m`), scope, and first-line preview.
- `tt state`: room path / state header, owner or reserved line with
  relative deadline, and a member list with `last seen` time and a
  `← you` marker.
- `tt events`: grouped per turn with relative time and
  `from → to (reason)` arrows.
- `--json` is auto-selected when invoked from a harness (same
  `TT_HARNESS_EXPORT` / `TT_HARNESS_AGENT_ID` gate the identity resolver
  uses; only `1`/`true` enable export). `--text` forces human mode even
  in a harness.
- `tt release` and `tt pass` accept JSON handoffs on stdin via
  `--stdin`, mirroring the `tt notes add --stdin` convention.

## Reliability fixes

### Liveness hardening

- `createDefaultProcessLivenessChecker` returns `unknown` instead of
  `gone` on a live pid with `process_started_at` drift; both sides are
  trim-normalized. Pure ESRCH still returns `gone`.
- `inspectRoom` / `inspectRoomForMutation` now gate `owner_gone` on a
  `2 * heartbeatIntervalMs` silence-grace window. A momentary `gone`
  reading no longer voids an active lease. `recipient_gone` is a
  diagnostic label only — actual takeover is gated on
  `claim_expires_at`.
- Read RPCs (`get_room_state`, `get_room_events`, `list_notes`) now
  refresh joined-member presence via `touchKnownMember` so a
  legitimately-busy reader cannot accidentally trip the silence grace.

### Windows installer hardening

- `tt install` resolves the executable from the configured env/platform
  PATH and, on Windows, routes `.cmd`/`.bat` wrappers through
  `cmd.exe /d /s /c`. Spawn errors become structured `InstallResult`
  failures rather than crashing the CLI.
- Args containing cmd metacharacters (`& | < > ^ % "`) are rejected
  before launch.

### Installer skips absent harnesses

- `tt install --all` no longer fails when a harness isn't present, and
  no longer creates `~/.claude`, `~/.codex`, or `~/.opencode` just to
  drop a skill in. New `SkipAction` kind, `MissingHarnessError`, and
  per-harness config-dir resolvers carry the absent signal end to end.

### CLI session preservation on join refresh

- `tt wait` / `tt try` no longer overwrite the existing CLI session's
  `lease_id` / `turn_id` / `guardian_pid` when re-joining the room.
  The new `upsertJoinedCliSession` helper merges join-time fields onto
  whatever lease/guardian state was already there.

## Known alpha boundaries

- No human override / admin model yet.
- No full daemon / push transport; waiting still uses bounded polling
  (now amortized via `ScheduleWakeup`-style pacing in skill guidance).
- Ambient presence remained design-only; its obsolete design sketch was later retired.

## Verification

- `npm run typecheck`
- `npm test` (165 tests across 13 files)
- `npm run build`
