---
name: ayf:context-router
description: |
  Read the current session context and proactively suggest the right ay-framework command.
allowed-tools:
  - Read
  - Bash
  - Glob
  - Grep
---

# /context-router -- Proactive Command Suggestion

Reads the session's context signals and surfaces the single most relevant
ay-framework command, so the human (or agent) never has to remember which
command fits the moment.

This command is **advisory only**. It never mutates state, never creates locks,
never edits the board. It reads, decides, and suggests. Acting on the suggestion
is always a separate, explicit step.

The agent should also apply these same heuristics automatically between turns —
see the **Proactive Triggers** section of `CLAUDE.md`. Running `/context-router`
is the on-demand version of that always-on behavior.

## Phase 1: Gather Signals

Collect the raw context. Do not interpret yet.

1. **Board state.** Read `.ay/tracking/BOARD.md`. Count tasks by status
   (BACKLOG / READY / IN PROGRESS / DONE / BLOCKED). Note the titles of any
   BLOCKED tasks and their `Blocked By` column.
2. **Active locks.** List `.ay/tracking/locks/*.lock`. For each, read the
   `started:` timestamp (or fall back to the file mtime).
3. **Lock age.** For each IN PROGRESS task with a lock, compute minutes elapsed:
   ```bash
   # minutes since a lock was created (portable: mtime-based fallback)
   now=$(date +%s)
   for f in .ay/tracking/locks/*.lock; do
     [ -f "$f" ] || continue
     mt=$(stat -f %m "$f" 2>/dev/null || stat -c %Y "$f")
     echo "$(basename "$f" .lock): $(( (now - mt) / 60 )) min"
   done
   ```
4. **Last action outcome.** Inspect the most recent tool result in this session.
   Did the last command exit non-zero, print a stack trace, or fail a test/build?
5. **Recently completed work.** Did the current task's deliverables just finish
   (build green, tests pass, sequence complete) without the board yet showing it
   DONE?

## Phase 2: Evaluate Rules (first match wins)

Walk the table top to bottom. Emit the suggestion for the **first** signal that
matches. Priority is deliberate: errors and blockers interrupt; routine
progress suggestions come last.

| # | Signal | Suggest | Why |
|---|--------|---------|-----|
| 1 | Last action errored (non-zero exit, stack trace, failed test/build) | **`/fix`** | Root-cause the failure before doing anything else |
| 2 | BOARD.md has a BLOCKED task | **Surface the blocker to the human** (name the task + what it is `Blocked By`) — do not auto-pick around it silently | A human decision usually unblocks faster than reshuffling |
| 3 | BOARD.md has zero tasks (no BACKLOG/READY/IN PROGRESS/DONE rows) | **`/go`** (First Contact) | Fresh install — bootstrap the project |
| 4 | Current task's work just completed (build/tests green, sequence done) but its board row is not yet DONE | **`/task-done {N}`** | Finalize: unlock, update board, cascade, log |
| 5 | A task is IN PROGRESS and its lock is older than 30 minutes | **`/go`** (continue the in-progress task) | Long-running or resumed work — pick the thread back up |
| 6 | 3 or more tasks are DONE (and not yet archived) | **Run the janitor** — archive completed tasks and prune stale/orphaned locks | Keep the board and `locks/` tidy so signals stay accurate |
| 7 | None of the above; READY tasks exist | **`/go`** (pick the next READY task) | Default forward motion |
| 8 | None of the above; no READY tasks | **`/pipeline-view`** | Nothing actionable — show the human the board |

Notes:
- Rule 6's "janitor" is the maintenance pass: it archives DONE task rows out of
  the active board, deletes locks with no matching IN PROGRESS task, and reclaims
  stale locks (older than 24h). If no janitor command is wired yet, suggest the
  manual equivalent: review with `/pipeline-view`, then clear finished locks.
- The 30-minute threshold in rule 5 is a heuristic, not a deadline. It catches
  resumed sessions and stalls, not active work.

## Phase 3: Surface the Suggestion

Emit **one** concise line — never a wall of text. Format:

```
Suggestion: {command}  —  {one-clause reason} ({the signal that triggered it})
```

Examples:
```
Suggestion: /fix  —  last test run failed (2 failing in bin/ayf-test)
Suggestion: /task-done 63  —  build green + sequence complete, board still IN PROGRESS
Suggestion: /go  —  task 66 in progress, lock is 47 min old
Blocker: task 61 is BLOCKED by 60 — needs your call before I can proceed
```

Rules for the output:
- Exactly one suggestion (the first matching rule). Do not list all rules.
- If the winning rule is #2 (blocker), surface it as a `Blocker:` line, not a
  `Suggestion:` line — it needs a human, not a command.
- Never run the suggested command automatically. Suggest; the human or the
  calling flow decides.

## Rules

- Read-only. This command must not create locks, edit the board, or write files.
- One suggestion per invocation — the highest-priority matching signal.
- If signals conflict, the table order is the tie-breaker (lower # wins).
- If no `.ay/` exists, say the framework is not initialized and stop.
