Skip to content

feat(cli): Add human review board subcommands #3

@Fatih0234

Description

@Fatih0234

Problem

The orchestrator-owned pipeline spec intentionally stops at in_review:

"Success means in_review, not done. done is a human decision."

However, the minimal implementation provides no tooling for the human to complete this loop. Today, a reviewer who wants to approve or reject an issue must:

  1. Manually inspect the workspace and run records
  2. Edit JSON files by hand (summary.json, decision.json)
  3. Use git directly to merge or discard work
  4. Run ad-hoc scripts to move the issue state on the board

This is a chore. Adding a small CLI surface for review operations makes the human gate ergonomic and closes the lifecycle gap.

Goals

  • Add a contrabass board subcommand group for human review operations
  • Provide read-only inspection commands (list, show)
  • Provide state-transition commands (approve, reject, retry)
  • Operate on both the local board and (eventually) external trackers via the IssueTracker interface
  • Keep the CLI simple — no interactive prompts, just flags and args

Non-Goals

  • Interactive TUI for review (the Bubble Tea TUI already shows the review queue)
  • Automatic merge / push to origin (the human decides when and how to merge)
  • Code review diff rendering in the terminal (use git diff or your editor)
  • Email / Slack notifications

Command Specification

contrabass board list [flags]

List issues by state.

# List all issues in review
contrabass board list --state in_review

# List all issues
contrabass board list --all

# List with retry queue
contrabass board list --state retry_queued

Output format (tabular, terminal-friendly):

ID      STATE       TITLE                      BRANCH           ATTEMPTS  READY
CB-1    in_review   Fix login bug              opencode/CB-1    2         12m ago
CB-2    retry_queued  Add OAuth flow           -                3         -
CB-3    todo        Refactor auth middleware   -                -         -

Flags:

  • --state — filter by state (todo, in_progress, retry_queued, in_review, done)
  • --all — show all states
  • --config — path to WORKFLOW.md (reuses existing global flag)

contrabass board show <issue-id>

Display the full review package for an issue.

contrabass board show CB-1

Output:

Issue: CB-1
Title: Fix login bug
State: in_review
Branch: opencode/CB-1
Workspace: /path/to/.worktrees/CB-1
Attempts: 2
Ready: 12m ago

Stages:
  ✓ plan     (attempt #1, 2m 15s)
  ✓ execute  (attempt #1, 5m 30s, commit: a1b2c3d)
  ✓ verify   (attempt #2, 3m 10s)

Review handoff:
  All stages completed for CB-1.
  Workspace: /path/to/.worktrees/CB-1
  Branch: opencode/CB-1

Run records:
  .contrabass/projects/<project>/runs/CB-1/

This command reads from:

  • internal/tracker/local.go (or whichever tracker is configured) for issue metadata
  • internal/diagnostics/recorder.go for attempt history, stage results, and handoff notes
  • Git state in the workspace for branch/commit info

contrabass board approve <issue-id> [flags]

Approve an issue and mark it as done.

contrabass board approve CB-1
contrabass board approve CB-1 --message "LGTM, merged manually"

Actions:

  1. Fetch the issue from the tracker
  2. Verify it is in in_review state (fail fast otherwise)
  3. Write a review/decision.json artifact via the diagnostics recorder:
    {
      "decision": "approved",
      "reviewed_by": "human",
      "reviewed_at": "2026-04-25T12:00:00Z",
      "notes": "LGTM, merged manually",
      "follow_up_state": "done"
    }
  4. Update the tracker state to done
  5. Print confirmation with workspace path and branch name (reminding the user to merge if they haven't)

Flags:

  • --message — optional review note

contrabass board reject <issue-id> [flags]

Reject an issue and return it to todo.

contrabass board reject CB-1
contrabass board reject CB-1 --message "Needs tests for edge cases"

Actions:

  1. Fetch the issue
  2. Verify it is in in_review state
  3. Write review/decision.json with "decision": "rejected"
  4. Update tracker state to todo
  5. Optionally clean up the workspace? No — the human may want to inspect the rejected work. Print the workspace path instead.

Flags:

  • --message — required? No, but strongly encouraged. Empty string is allowed.

contrabass board retry <issue-id>

Manually retry a failed or rejected issue immediately.

contrabass board retry CB-1

Actions:

  1. Fetch the issue
  2. Verify it is in retry_queued or todo state
  3. Update tracker state to todo (ensures orchestrator will pick it up on next poll)
  4. Print confirmation

This is a convenience command for "I fixed the environment, retry this now" without waiting for backoff.

Implementation Plan

Phase 1: Core command scaffolding

  • Add cobra (or stick with flag if you want to keep deps minimal)
  • The reference Contrabass uses spf13/cobra for subcommands. Adding it is reasonable.
  • Create cmd/contrabass/board.go with the subcommand definitions
  • Wire the same config → tracker → recorder initialization that main.go already does

Phase 2: Read commands (list, show)

  • list: Query tracker, format as table using text/tabwriter
  • show: Query tracker + recorder, format multi-line output

Phase 3: Write commands (approve, reject, retry)

  • approve / reject: Validate state, write decision artifact, update tracker
  • retry: Validate state, force to todo

Data Access

The board commands need access to:

  1. IssueTracker — for fetching and updating issues
  2. diagnostics.Recorder — for reading attempt history and writing decisions
  3. config.Config — for board directories and workspace paths

Refactor cmd/contrabass/main.go to extract a shared setup() function that returns (cfg, tracker, workspace, recorder) so both run() and the board commands can reuse it.

Edge Cases & Error Handling

Scenario Behavior
Approve an issue not in in_review Error: "CB-1 is in state 'todo', expected 'in_review'"
Reject with no message Warn: "No rejection note provided. Consider adding --message."
Show an issue that has no run records Print issue metadata, omit attempts/stages sections
Board command with missing WORKFLOW.md Same error behavior as main orchestrator
Tracker returns error on state update Surface error, do not write partial decision artifact

Existing Reference

The reference Contrabass has cmd/contrabass/board.go which implements contrabass board subcommands with Cobra. It supports list, show, create, move, comment, delete, sync, and reset. Use it for command structure inspiration, but keep the minimal version focused only on review lifecycle commands.

See also:

  • docs/references/contrabass/cmd/contrabass/board.go
  • docs/references/contrabass/cmd/contrabass/team_board.go (team-scoped board ops)

Files to Create / Modify

  • Create: cmd/contrabass/board.go — Cobra subcommands (list, show, approve, reject, retry)
  • Create: cmd/contrabass/board_test.go — unit tests with mock tracker and in-memory recorder
  • Modify: cmd/contrabass/main.go — extract shared setup into buildDeps() helper; add cobra root command
  • Modify: internal/diagnostics/stages.go — ensure RecordReviewDecision is exported and usable from CLI

Acceptance Criteria

  • contrabass board list --state in_review shows only issues awaiting review
  • contrabass board show CB-1 displays stage completion, branch, workspace, and handoff text
  • contrabass board approve CB-1 writes review/decision.json and moves issue to done
  • contrabass board reject CB-1 writes review/decision.json and moves issue to todo
  • contrabass board retry CB-1 moves a retry_queued issue back to todo
  • All state-transition commands fail fast if the issue is not in the expected state
  • go test ./cmd/contrabass/... passes with mock tracker coverage
  • README is updated with board command examples

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions