feat(watch): --verbose flag for debugging empty boards#782
Conversation
… failures (#781) New --verbose / -v flag outputs diagnostic info: - Startup: repo, platform, auth account, agent-cmd, dispatch mode - Per-round: issues found with labels/assignees, PRs with review status - Execute: agent command, batch selection, dispatch classification - Timing: round duration - Warnings: unused positional args, auth failures Also warns when positional args are passed to watch (they're ignored). New file: verbose.ts — createVerboseLogger utility (log/warn/section/table) Closes #781 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🛫 PR Readiness Check
|
| Status | Check | Details |
|---|---|---|
| ❌ | Single commit | 7 commits — consider squashing before review |
| ✅ | Not in draft | Ready for review |
| ✅ | Branch up to date | Up to date with dev |
| ❌ | Copilot review | No Copilot review yet — it may still be processing |
| ✅ | Changeset present | Changeset file found |
| ✅ | Scope clean | No .squad/ or docs/proposals/ files |
| ✅ | No merge conflicts | No merge conflicts |
| ❌ | Copilot threads resolved | 1 unresolved Copilot thread(s) — fix and resolve before merging |
| ❌ | CI passing | 13 check(s) still running |
This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.
There was a problem hiding this comment.
Pull request overview
Adds a --verbose / -v diagnostics mode to squad watch to make “empty board” states debuggable by printing startup/round/board details and a warning about ignored positional args.
Changes:
- Introduces a small
createVerboseLogger()helper and wires it through watch + execute flows. - Extends watch config/context to carry a
verboseflag (CLI +.squad/config.json). - Adds additional verbose output for startup, issue/PR discovery, board counters, and execute batching.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/squad-cli/src/cli/commands/watch/verbose.ts | New verbose logger utility (log/warn/section/table). |
| packages/squad-cli/src/cli/commands/watch/types.ts | Adds verbose?: boolean to WatchContext. |
| packages/squad-cli/src/cli/commands/watch/index.ts | Wires verbose logging into startup + per-round checks and reporting. |
| packages/squad-cli/src/cli/commands/watch/config.ts | Adds verbose to config load/merge + reserved-key handling. |
| packages/squad-cli/src/cli/commands/watch/capabilities/execute.ts | Adds verbose diagnostics for execution batching/selection. |
| packages/squad-cli/src/cli-entry.ts | Parses --verbose/-v and adds positional-args warning. |
| .changeset/watch-verbose-mode.md | Changeset for releasing the new flag. |
packages/squad-cli/src/cli-entry.ts
Outdated
|
|
||
| // After parsing all flags, check for positional args that look like prompts | ||
| const watchArgStart = args.indexOf(cmd) + 1; | ||
| const positionalArgs = args.slice(watchArgStart).filter(a => !a.startsWith('--') && !a.startsWith('-')); |
There was a problem hiding this comment.
The positional-arg warning will produce false positives because it treats any token not starting with '-' as positional, including values for flags (e.g. --interval 5 makes 5 look positional). Consider tracking/stripping known option-value pairs (interval/timeout/max-concurrent/copilot-flags/agent-cmd/board-project, etc.) before checking for true positional args, so valid invocations don’t trigger the warning.
| const positionalArgs = args.slice(watchArgStart).filter(a => !a.startsWith('--') && !a.startsWith('-')); | |
| const knownValueFlags = new Set([ | |
| '--interval', | |
| '--copilot-flags', | |
| '--agent-cmd', | |
| '--max-concurrent', | |
| '--timeout', | |
| '--board-project', | |
| ]); | |
| const knownBooleanFlags = new Set([ | |
| '--execute', | |
| '--verbose', | |
| '-v', | |
| ...registry.all().flatMap((cap) => [`--${cap.name}`, `--no-${cap.name}`]), | |
| ]); | |
| const positionalArgs: string[] = []; | |
| const watchArgs = args.slice(watchArgStart); | |
| for (let i = 0; i < watchArgs.length; i++) { | |
| const arg = watchArgs[i]!; | |
| if (knownValueFlags.has(arg)) { | |
| i++; | |
| continue; | |
| } | |
| if (knownBooleanFlags.has(arg) || arg.startsWith('-')) { | |
| continue; | |
| } | |
| positionalArgs.push(arg); | |
| } |
| // Auth check (verbose) | ||
| if (adapter.type === 'github') { | ||
| try { | ||
| const authOut = execFileSync('gh', ['auth', 'status'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim(); | ||
| const activeAccount = authOut.match(/Logged in to .* account (\S+)/)?.[1]; | ||
| vlog.log(`Auth: ${activeAccount ?? 'unknown'}`); | ||
| } catch { | ||
| vlog.warn('gh auth status failed — API calls may fail silently'); | ||
| } | ||
| } |
There was a problem hiding this comment.
gh auth status is executed unconditionally (even when --verbose is off) because only the logging is gated. This adds a synchronous process spawn to every watch startup and can slow/hang startup. Gate the auth check itself behind config.verbose (or the vlog enabled state), and consider running it after confirming ghAvailable() to avoid calling gh before the availability check.
| vlog.section('Startup'); | ||
| vlog.table({ | ||
| repo: teamRoot, | ||
| platform: adapter.type, | ||
| verbose: true, | ||
| interval: `${config.interval}m`, | ||
| execute: config.execute ?? false, | ||
| agentCmd: config.agentCmd ?? '(default: gh copilot)', | ||
| dispatchMode: config.capabilities['wave-dispatch'] ? 'wave' : 'task', | ||
| maxConcurrent: config.maxConcurrent ?? 1, | ||
| }); |
There was a problem hiding this comment.
The startup verbose table hard-codes verbose: true, which can be misleading if the logger enablement logic changes (and is redundant since the table only prints when verbose is enabled). Prefer using config.verbose (or omitting this field entirely) so the diagnostic output reflects the actual configuration source-of-truth.
diberry
left a comment
There was a problem hiding this comment.
LGTM
Review Summary
Verdict: Approve
What's Good
- Solves real pain — 'Board is clear' with zero visibility into why. Verbose output covers startup, per-round issues/PRs, execute phase, board counters, and timing.
- Clean implementation — createVerboseLogger() is a simple factory returning no-ops when disabled. Zero overhead when --verbose is off.
- Good API surface — log, warn, section, table cover all formatting needs. [verbose] prefix makes output easy to grep.
- Covers all phases — Startup config dump, auth check, per-round issue details (labels + assignees), PR scan, execute batch, board counters, round timing.
- Positional arg warning — Smart catch for squad watch "Run tasks" where prompt gets silently ignored. Only warns in verbose mode.
- Config file support — verbose can be set in squad-watch.json too, not just CLI flag.
Suggestions (non-blocking)
- Consider dropping -v short flag (reserve for --version if CLI ever adds it)
- Add 2-3 basic tests for createVerboseLogger (enabled/disabled output)
- Future: derive vlog from WatchContext.verbose instead of threading parameter separately
- Gate gh auth status behind config.verbose (avoid unnecessary process spawn) - Fix startup table verbose: true → config.verbose - Fix positional args false-positive: skip values after known value-flags Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add clarifying comment explaining verbose:true is expected in startup table (table only renders when verbose mode is active) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add JSDoc to reportBoard() documenting default notifyLevel='important' - Include machine/repo context in 'Board is clear' message for all modes - Add comment noting verbose flag parsing is in PR #782 - Replace console.log direct mutation with vi.spyOn in tests - Update changeset to clarify attribution is in round headers and clear message Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Superseded by #830 — combined into a single watch next-gen PR for easier review. |
|
Closing — superseded by #830 (watch-next-gen combined PR) |
🟡 Impact Analysis — PR #782Risk tier: 🟡 MEDIUM 📊 Summary
🎯 Risk Factors
📦 Modules Affectedroot (1 file)
squad-cli (6 files)
|
Add
--verboseflag for debuggingsquad watchWhen watch says "Board is clear — Ralph is idling", users have zero visibility into why. This PR adds
--verbose/-vthat outputs diagnostic info at every step.Usage
What verbose shows
Example output
Also fixes
squad watch "Run scheduled tasks"now shows⚠️ Positional args ignored by watchin verbose mode (the prompt is NOT used by watch)Files changed
verbose.tscreateVerboseLogger()(log, warn, section, table)config.tsverbosefield in WatchConfigtypes.tsverbosein WatchContextcli-entry.ts--verbose/-vparsing + positional arg warningindex.tsexecute.tsCloses #781