Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .claude/gh-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,9 @@ jump to the item's tab (the worker's, or the PM's for a queued or done item),
`a` toggle the overview, `q` quit. `t` stays inside the monitor's own zellij
session, and goes to a tab only while the tab at the recorded id still bears the
item's name, the check `task-done` makes before closing one (#260). It holds no
task-force logic: every value is a snapshot field. Build it from the task-force
checkout with `cargo build --release --manifest-path monitor/Cargo.toml`
(`install.sh` does not build it yet; #277). Its Next section is the queue the
task-force logic: every value is a snapshot field. A loadout's
`install.sh` builds and links it when `cargo` is on PATH, and skips it with one
line when not (#277). Its Next section is the queue the
PM writes with `task-monitor-queue`, below, else the tracker's backlog.

`task-monitor-queue` — the PM's short-term queue, the board's **Next** (#275)
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

### Added

- **`install.sh` builds and links `task-monitor` (#277, part of #272).** Every loadout's installer now runs `cargo build --release --locked` on `monitor/`, so it builds exactly the committed `Cargo.lock` as CI does, when `cargo` is on `PATH` and links `~/.local/bin/task-monitor`. Without cargo it prints one line, `Skipped: task-monitor (no cargo on PATH; install Rust >= 1.88 from https://rustup.rs and re-run this installer)`, and carries on: `task-monitor-snapshot` and the other bash commands install either way. A failed build warns with the command to retry and does not fail the install. The binary's path is read off cargo's JSON output rather than assumed, so a `CARGO_TARGET_DIR` or `build.target-dir` is honoured; when that puts the binary outside the checkout, where it cannot find `bin/task-monitor-snapshot` beside itself, the installer says to export `TASK_MONITOR_SNAPSHOT`. The logic is `lib/monitor-install.sh`, called from the drift-guarded shared install stanza, so all seven loadouts get it. `install.sh all` runs the build seven times; after the first, cargo finds it up to date. Prebuilt binaries remain out of scope. Docs: the README's `task-monitor` section, `.claude/gh-workflow.md` and the seven steering templates no longer say `install.sh` does not build it. `tests/install_symlinks.bats` puts a stub `cargo` on `PATH` for every installer test, so none runs a real build, and adds five tests: the build arguments and the link to the reported executable, the one-line skip with no cargo anywhere on `PATH`, a failed build, a reported executable that is missing, and the outside-the-checkout hint. Six mutations of the helper each turned at least one of them red. **Upgrading: re-run the loadout's `install.sh`** to build and link the monitor, and again after a `git pull` that changes `monitor/`. No `task-init` re-run is needed; the steering template edit only touches the description, so re-run `task-init <loadout>` only if you want the refreshed workflow doc.

- **`task-monitor`: the board, live in the terminal (#276, epic #272 4/6).** A Rust + ratatui front end in `monitor/` over `task-monitor-snapshot --json`, with the two screens the epic drew. The **repo view** shows In flight (number, title, status word with its PR, the plain description, the `▶` / `⏸` / `❓` activity icon with the time since the session was last heard from, and how many reviewers are on it), Next (the PM queue or the tracker backlog, with notes) and Done (PR, short merge SHA, age, and the two-line summary). The **overview** (`a`, or `--all`, and the default outside a repo) has one row per repo: the attention light, the signals in words, the in-flight count, and the zellij session it runs in. Keys: `↑↓` move, `⏎` expands an item in place (a done item to its full PR body, scrollable) or enters a repo, `o` opens the PR or issue, `t` jumps to the item's tab, `a` toggles the overview, `q` quits.
- **Real time, and never waiting on GitHub.** Filesystem events under `$TASK_FORCE_HOME/radio` (except its `log`), `$TASK_FORCE_HOME/monitor` and each repo's worktree base (`.<slug>.info` sidecars only) trigger a `--local` snapshot, debounced on the trailing edge at 400ms and capped at 2s. One local run at a time; an event during a run reruns it afterwards. A full run, the only one that calls `gh`, runs at start and then 45s after the previous one finished (`--poll SECS`, 30-600). Both run off the UI thread, with timeouts (20s / 180s) that kill a hung collector. A result never replaces one from a run that started later, with one exception: a full result replaces local data even when the local run started after it, since a local run cannot ask the forge. Heartbeats rewrite session files constantly, so a local run landing mid-full-run is the normal case, and without the exception every full result would be dropped. The full result's disk state is then older than what it replaced, so a local rerun is scheduled at once. A failed run marks the screen stale under the same rule, so an old run's timeout cannot mark a fresh screen stale.
- **Never blank.** A failed or timed-out snapshot keeps the last good one on screen; the header turns to `stale <age>` and the footer gives the collector's own last stderr line. `forge <age>` marks a repo whose PR state is from the last full run.
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,9 @@ A ref is whatever the tracker uses: an issue number, a Jira key, a Notion page U
- **`t` stays in this zellij session.** Each overview row names its repo's zellij session; `zellij action` cannot switch sessions, so a tab elsewhere is named, not attempted. Within the session, `t` goes to the recorded `TAB_ID` only while that tab still bears the item's name, the check `task-done` makes before it closes a tab (#260).
- **No task-force logic in Rust.** Every word comes from the snapshot; status words are a lookup of its `status` field.

Build it from the task-force checkout with `cargo build --release --manifest-path monitor/Cargo.toml` and run `monitor/target/release/task-monitor`; it finds `bin/task-monitor-snapshot` beside it, and `$TASK_MONITOR_SNAPSHOT` overrides that. `install.sh` does not build or link it yet (#277). It needs Rust 1.88 or newer; CI builds, tests and lints it on Linux and macOS.
**Installing.** Every loadout's `install.sh` builds it (`cargo build --release --locked`, so exactly the committed `Cargo.lock`) and links `~/.local/bin/task-monitor` when `cargo` is on `PATH`. Without cargo it prints one line saying so and skips the monitor; `task-monitor-snapshot` and the rest of the bash commands install either way. A failed build warns, leaves the monitor unlinked and lets the install finish. It needs Rust 1.88 or newer ([rustup.rs](https://rustup.rs)); install Rust and re-run the installer to add the monitor later. Re-running the installer is also how to pick up a newer monitor after a `git pull`, since the link points at the built binary, not at source. There are no prebuilt binaries yet.

The binary finds `bin/task-monitor-snapshot` beside its real path in the checkout, and `$TASK_MONITOR_SNAPSHOT` overrides that. A `CARGO_TARGET_DIR` (or `build.target-dir`) outside the checkout breaks that lookup, so the installer reads the binary's path from cargo and, when it lands elsewhere, says to export `TASK_MONITOR_SNAPSHOT`. To build by hand: `cargo build --release --manifest-path monitor/Cargo.toml`, then run `monitor/target/release/task-monitor`. CI builds, tests and lints it on Linux and macOS.

---

Expand Down
5 changes: 5 additions & 0 deletions claude-gh/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ ln -sf "$SCRIPT_DIR/../bin/task-monitor-snapshot" ~/.local/bin/task-monitor-snap
echo " ✓ Script: task-monitor-snapshot (canonical)"; sleep 0.05
ln -sf "$SCRIPT_DIR/../bin/task-monitor-queue" ~/.local/bin/task-monitor-queue
echo " ✓ Script: task-monitor-queue (canonical)"; sleep 0.05
# task-monitor is the one compiled command (#277): built here when cargo is on
# PATH, skipped with one line when it is not.
# shellcheck source=lib/monitor-install.sh
source "$SCRIPT_DIR/../lib/monitor-install.sh"
aw_install_monitor "$SCRIPT_DIR/.."
# endregion:install-shared-symlinks
ln -sf "$SCRIPT_DIR/../bin/task-reviewer" ~/.local/bin/task-reviewer
echo " ✓ Script: task-reviewer (canonical + kiro routing)"; sleep 0.05
Expand Down
6 changes: 3 additions & 3 deletions claude-gh/steering/gh-workflow.example.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ jump to the item's tab (the worker's, or the PM's for a queued or done item),
`a` toggle the overview, `q` quit. `t` stays inside the monitor's own zellij
session, and goes to a tab only while the tab at the recorded id still bears the
item's name, the check `task-done` makes before closing one (#260). It holds no
task-force logic: every value is a snapshot field. Build it from the task-force
checkout with `cargo build --release --manifest-path monitor/Cargo.toml`
(`install.sh` does not build it yet; #277). Its Next section is the queue the
task-force logic: every value is a snapshot field. A loadout's
`install.sh` builds and links it when `cargo` is on PATH, and skips it with one
line when not (#277). Its Next section is the queue the
PM writes with `task-monitor-queue`, below, else the tracker's backlog.

`task-monitor-queue` — the PM's short-term queue, the board's **Next** (#275)
Expand Down
5 changes: 5 additions & 0 deletions claude-jira/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ ln -sf "$SCRIPT_DIR/../bin/task-monitor-snapshot" ~/.local/bin/task-monitor-snap
echo " ✓ Script: task-monitor-snapshot (canonical)"; sleep 0.05
ln -sf "$SCRIPT_DIR/../bin/task-monitor-queue" ~/.local/bin/task-monitor-queue
echo " ✓ Script: task-monitor-queue (canonical)"; sleep 0.05
# task-monitor is the one compiled command (#277): built here when cargo is on
# PATH, skipped with one line when it is not.
# shellcheck source=lib/monitor-install.sh
source "$SCRIPT_DIR/../lib/monitor-install.sh"
aw_install_monitor "$SCRIPT_DIR/.."
# endregion:install-shared-symlinks
ln -sf "$SCRIPT_DIR/../bin/task-reviewer" ~/.local/bin/task-reviewer
echo " ✓ Script: task-reviewer (canonical + kiro routing)"; sleep 0.05
Expand Down
6 changes: 3 additions & 3 deletions claude-jira/steering/jira-workflow.example.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ jump to the item's tab (the worker's, or the PM's for a queued or done item),
`a` toggle the overview, `q` quit. `t` stays inside the monitor's own zellij
session, and goes to a tab only while the tab at the recorded id still bears the
item's name, the check `task-done` makes before closing one (#260). It holds no
task-force logic: every value is a snapshot field. Build it from the task-force
checkout with `cargo build --release --manifest-path monitor/Cargo.toml`
(`install.sh` does not build it yet; #277). Its Next section is the queue the
task-force logic: every value is a snapshot field. A loadout's
`install.sh` builds and links it when `cargo` is on PATH, and skips it with one
line when not (#277). Its Next section is the queue the
PM writes with `task-monitor-queue`, below, else the tracker's backlog.

`task-monitor-queue` — the PM's short-term queue, the board's **Next** (#275)
Expand Down
5 changes: 5 additions & 0 deletions claude-local/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ ln -sf "$SCRIPT_DIR/../bin/task-monitor-snapshot" ~/.local/bin/task-monitor-snap
echo " ✓ Script: task-monitor-snapshot (canonical)"; sleep 0.05
ln -sf "$SCRIPT_DIR/../bin/task-monitor-queue" ~/.local/bin/task-monitor-queue
echo " ✓ Script: task-monitor-queue (canonical)"; sleep 0.05
# task-monitor is the one compiled command (#277): built here when cargo is on
# PATH, skipped with one line when it is not.
# shellcheck source=lib/monitor-install.sh
source "$SCRIPT_DIR/../lib/monitor-install.sh"
aw_install_monitor "$SCRIPT_DIR/.."
# endregion:install-shared-symlinks
ln -sf "$SCRIPT_DIR/../bin/task-reviewer" ~/.local/bin/task-reviewer
echo " ✓ Script: task-reviewer (canonical + kiro routing)"; sleep 0.05
Expand Down
6 changes: 3 additions & 3 deletions claude-local/steering/local-workflow.example.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,9 @@ jump to the item's tab (the worker's, or the PM's for a queued or done item),
`a` toggle the overview, `q` quit. `t` stays inside the monitor's own zellij
session, and goes to a tab only while the tab at the recorded id still bears the
item's name, the check `task-done` makes before closing one (#260). It holds no
task-force logic: every value is a snapshot field. Build it from the task-force
checkout with `cargo build --release --manifest-path monitor/Cargo.toml`
(`install.sh` does not build it yet; #277). Its Next section is the queue the
task-force logic: every value is a snapshot field. A loadout's
`install.sh` builds and links it when `cargo` is on PATH, and skips it with one
line when not (#277). Its Next section is the queue the
PM writes with `task-monitor-queue`, below, else the tracker's backlog.

`task-monitor-queue` — the PM's short-term queue, the board's **Next** (#275)
Expand Down
5 changes: 5 additions & 0 deletions claude-notion/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ ln -sf "$SCRIPT_DIR/../bin/task-monitor-snapshot" ~/.local/bin/task-monitor-snap
echo " ✓ Script: task-monitor-snapshot (canonical)"; sleep 0.05
ln -sf "$SCRIPT_DIR/../bin/task-monitor-queue" ~/.local/bin/task-monitor-queue
echo " ✓ Script: task-monitor-queue (canonical)"; sleep 0.05
# task-monitor is the one compiled command (#277): built here when cargo is on
# PATH, skipped with one line when it is not.
# shellcheck source=lib/monitor-install.sh
source "$SCRIPT_DIR/../lib/monitor-install.sh"
aw_install_monitor "$SCRIPT_DIR/.."
# endregion:install-shared-symlinks
ln -sf "$SCRIPT_DIR/../bin/task-reviewer" ~/.local/bin/task-reviewer
echo " ✓ Script: task-reviewer (canonical + kiro routing)"; sleep 0.05
Expand Down
6 changes: 3 additions & 3 deletions claude-notion/steering/notion-workflow.example.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,9 @@ jump to the item's tab (the worker's, or the PM's for a queued or done item),
`a` toggle the overview, `q` quit. `t` stays inside the monitor's own zellij
session, and goes to a tab only while the tab at the recorded id still bears the
item's name, the check `task-done` makes before closing one (#260). It holds no
task-force logic: every value is a snapshot field. Build it from the task-force
checkout with `cargo build --release --manifest-path monitor/Cargo.toml`
(`install.sh` does not build it yet; #277). Its Next section is the queue the
task-force logic: every value is a snapshot field. A loadout's
`install.sh` builds and links it when `cargo` is on PATH, and skips it with one
line when not (#277). Its Next section is the queue the
PM writes with `task-monitor-queue`, below, else the tracker's backlog.

`task-monitor-queue` — the PM's short-term queue, the board's **Next** (#275)
Expand Down
5 changes: 5 additions & 0 deletions kiro-gh/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ ln -sf "$SCRIPT_DIR/../bin/task-monitor-snapshot" ~/.local/bin/task-monitor-snap
echo " ✓ Script: task-monitor-snapshot (canonical)"; sleep 0.05
ln -sf "$SCRIPT_DIR/../bin/task-monitor-queue" ~/.local/bin/task-monitor-queue
echo " ✓ Script: task-monitor-queue (canonical)"; sleep 0.05
# task-monitor is the one compiled command (#277): built here when cargo is on
# PATH, skipped with one line when it is not.
# shellcheck source=lib/monitor-install.sh
source "$SCRIPT_DIR/../lib/monitor-install.sh"
aw_install_monitor "$SCRIPT_DIR/.."
# endregion:install-shared-symlinks
ln -sf "$SCRIPT_DIR/../bin/task-reviewer" ~/.local/bin/task-reviewer
echo " ✓ Script: task-reviewer (canonical + kiro routing)"; sleep 0.05
Expand Down
6 changes: 3 additions & 3 deletions kiro-gh/steering/gh-workflow.example.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,9 @@ jump to the item's tab (the worker's, or the PM's for a queued or done item),
`a` toggle the overview, `q` quit. `t` stays inside the monitor's own zellij
session, and goes to a tab only while the tab at the recorded id still bears the
item's name, the check `task-done` makes before closing one (#260). It holds no
task-force logic: every value is a snapshot field. Build it from the task-force
checkout with `cargo build --release --manifest-path monitor/Cargo.toml`
(`install.sh` does not build it yet; #277). Its Next section is the queue the
task-force logic: every value is a snapshot field. A loadout's
`install.sh` builds and links it when `cargo` is on PATH, and skips it with one
line when not (#277). Its Next section is the queue the
PM writes with `task-monitor-queue`, below, else the tracker's backlog.

`task-monitor-queue` — the PM's short-term queue, the board's **Next** (#275)
Expand Down
5 changes: 5 additions & 0 deletions kiro-local/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ ln -sf "$SCRIPT_DIR/../bin/task-monitor-snapshot" ~/.local/bin/task-monitor-snap
echo " ✓ Script: task-monitor-snapshot (canonical)"; sleep 0.05
ln -sf "$SCRIPT_DIR/../bin/task-monitor-queue" ~/.local/bin/task-monitor-queue
echo " ✓ Script: task-monitor-queue (canonical)"; sleep 0.05
# task-monitor is the one compiled command (#277): built here when cargo is on
# PATH, skipped with one line when it is not.
# shellcheck source=lib/monitor-install.sh
source "$SCRIPT_DIR/../lib/monitor-install.sh"
aw_install_monitor "$SCRIPT_DIR/.."
# endregion:install-shared-symlinks

# Ensure ~/.local/bin is on PATH
Expand Down
6 changes: 3 additions & 3 deletions kiro-local/steering/local-workflow.example.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,9 @@ jump to the item's tab (the worker's, or the PM's for a queued or done item),
`a` toggle the overview, `q` quit. `t` stays inside the monitor's own zellij
session, and goes to a tab only while the tab at the recorded id still bears the
item's name, the check `task-done` makes before closing one (#260). It holds no
task-force logic: every value is a snapshot field. Build it from the task-force
checkout with `cargo build --release --manifest-path monitor/Cargo.toml`
(`install.sh` does not build it yet; #277). Its Next section is the queue the
task-force logic: every value is a snapshot field. A loadout's
`install.sh` builds and links it when `cargo` is on PATH, and skips it with one
line when not (#277). Its Next section is the queue the
PM writes with `task-monitor-queue`, below, else the tracker's backlog.

`task-monitor-queue` — the PM's short-term queue, the board's **Next** (#275)
Expand Down
5 changes: 5 additions & 0 deletions kiro-notion/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ ln -sf "$SCRIPT_DIR/../bin/task-monitor-snapshot" ~/.local/bin/task-monitor-snap
echo " ✓ Script: task-monitor-snapshot (canonical)"; sleep 0.05
ln -sf "$SCRIPT_DIR/../bin/task-monitor-queue" ~/.local/bin/task-monitor-queue
echo " ✓ Script: task-monitor-queue (canonical)"; sleep 0.05
# task-monitor is the one compiled command (#277): built here when cargo is on
# PATH, skipped with one line when it is not.
# shellcheck source=lib/monitor-install.sh
source "$SCRIPT_DIR/../lib/monitor-install.sh"
aw_install_monitor "$SCRIPT_DIR/.."
# endregion:install-shared-symlinks

# Ensure ~/.local/bin is on PATH
Expand Down
6 changes: 3 additions & 3 deletions kiro-notion/steering/notion-workflow.example.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,9 @@ jump to the item's tab (the worker's, or the PM's for a queued or done item),
`a` toggle the overview, `q` quit. `t` stays inside the monitor's own zellij
session, and goes to a tab only while the tab at the recorded id still bears the
item's name, the check `task-done` makes before closing one (#260). It holds no
task-force logic: every value is a snapshot field. Build it from the task-force
checkout with `cargo build --release --manifest-path monitor/Cargo.toml`
(`install.sh` does not build it yet; #277). Its Next section is the queue the
task-force logic: every value is a snapshot field. A loadout's
`install.sh` builds and links it when `cargo` is on PATH, and skips it with one
line when not (#277). Its Next section is the queue the
PM writes with `task-monitor-queue`, below, else the tracker's backlog.

`task-monitor-queue` — the PM's short-term queue, the board's **Next** (#275)
Expand Down
Loading
Loading