# Talking Stick 0.1.0-alpha.3

Date: 2026-04-26

Incremental alpha. Operator-experience and ergonomics. No breaking
protocol changes; the schema gains an additive `last_wait_at` column
on `room_members`.

## New features

### Operator-friendly takeover

`tt take` is the new human-facing entrypoint for "I want this room
now." For human CLI invocations it is reason-optional — the operator
can step into a stuck reserved or owned room without composing a
formal reason string. Harness-aware CLI takeovers still require
`--reason` unless invoked with `--operator-requested`, which is the
sanctioned override path.

`tt takeover` is now an alias for `tt take`. The skill (`§6 Takeover
is explicit`) documents the operator-override path.

### Explicit `tt assign`

`tt pass [path]` no longer treats its first positional as a target —
it now consistently means "pass/end my turn" and lets the server pick
the next fair waiter. To address a handoff to a specific named
member, use the new `tt assign <target|next> [path]`. This makes the
release-by-default rule unambiguous at the CLI surface.

### Automatic skill sync on human CLI startup

Ordinary `tt` invocations from a human CLI now silently refresh
already-installed Claude Code, Codex, and OpenCode skill copies (or
relink stale symlinks) from the bundled skill, so copied installs do
not drift after a Talking Stick update. Missing harness roots and
missing skill installs are skipped — no `~/.claude` / `~/.codex` /
`~/.opencode` directory is created just to sync. Gemini remains
managed via the explicit `tt install-skill gemini` command.

### `tt self-update`

New subcommand that detects how `tt` was installed and runs the
right global-update command:

| Detected source | Command |
|---|---|
| npm (including Homebrew node, mise, asdf, nvm, volta) | `npm install -g talking-stick@latest` |
| pnpm | `pnpm install -g talking-stick@latest` |
| yarn classic | `yarn global add talking-stick@latest` |
| bun | `bun add -g talking-stick@latest` |

Pass `--print` to see the inferred command without running it; pass
`--manager` to override detection. Running `tt self-update` from a
development checkout (where `tt` resolves outside
`node_modules/talking-stick`) refuses with a clear message pointing
at `git pull && npm install && npm run build`.

## Behavior changes

### Fair release selection

`release_stick` no longer picks the next active sequence member by
join-order. Instead it picks the next *fair* waiter:

- Tracks `last_wait_at` on every `wait_for_turn` call so the server
  knows who is actively waiting versus who only joined.
- Prefers a recent waiter that is new to the rotation, or that has
  gone longest without holding the stick.
- Falls back to join order when no recent waiters are tracked.
- A short `policy.waiterGraceMs` window keeps the turn briefly
  claimable instead of pinning it to a less-fair claimant when the
  best-known candidate is between wait polls.

The net effect: a human (or any other member) who joins late and
calls `wait_for_turn` is no longer locked behind agent-to-agent
ping-pong.

### Skill handoff guidance

Skill `§7` is rewritten. The default after a turn is
`release_stick`; `pass_stick` is reserved for the specific cases
(unique context, capability, explicit operator addressing). Two AIs
ping-ponging `pass_stick` between themselves is called out as the
antipattern this change prevents — it locks humans out of their own
room.

The skill also documents the sanctioned operator-override CLI path
(`tt take --operator-requested`) so agents have a clear answer when
the operator says "take it now" despite a live owner or reservation.

## Schema

Migration `004_room_member_wait_presence` adds a nullable
`last_wait_at TEXT` column to `room_members`. Additive only; no
back-fill required.

## Verification

- `npm run typecheck`
- `npm test` — 192 tests across 14 files
- `npm run build`
