Make crew picker linear: first slot, then "add another" · Entire

Make crew picker linear: first slot, then "add another"

ef60a7a→main·

dipree·1mo ago·1 file·+32 added/-97 removed

The Add/Remove/Done action menu was clunky. Replace it with a linear flow: configure a first worker (agent + model), print it, then ask "Add another worker?" — repeating until Done. The crew is always non-empty (a first slot is mandatory), so no empty-state handling, and duplicates still work (add the same agent again).

Removes the action-menu plumbing (promptCrewAction, crewSummary, promptCrewRemove, and the crewAction* consts); adds promptAddAnotherSlot. Slot removal is dropped — re-run entire review --configure to rebuild.

Sessions

8b762f4940ebView transcript

Changes

1

175 unmodified lines

// promptForReviewCrew builds the review crew as an explicit list of worker
// slots. It seeds one slot per launchable agent (default model) so pressing
// Done immediately reproduces the all-agents-on-defaults baseline, then lets
// the user add, remove, or duplicate slots freely — e.g. five Claude slots on
// different (or identical) models.
func promptForReviewCrew(ctx context.Context, out io.Writer, profileName string, launchable []string) (settings.ReviewProfileConfig, error) {
    slots := make([]crewSlot, 0, len(launchable))
    for _, name := range launchable {
        slots = append(slots, crewSlot{agent: name})
    }

fmt.Fprintln(out, "Build the review crew")
    fmt.Fprintln(out, "Each slot is one worker: an agent + model. Add as many as you like —")
    fmt.Fprintln(out, "including the same agent more than once, on different or identical models.")
    fmt.Fprintln(out, "Add one worker at a time — each is an agent + model. You can add the same")
    fmt.Fprintln(out, "agent more than once, on different or identical models.")
    fmt.Fprintln(out)

slots := make([]crewSlot, 0, len(launchable))
    for {
        action, err := promptCrewAction(ctx, slots)
        agentName, err := promptCrewAgent(ctx, launchable)
        if err != nil {
            return settings.ReviewProfileConfig{}, err
        }
        switch action {
        case crewActionAdd:
            agentName, err := promptCrewAgent(ctx, launchable)
            if err != nil {
                return settings.ReviewProfileConfig{}, err
            }
            model, err := promptCrewModel(ctx, agentName)
            if err != nil {
                return settings.ReviewProfileConfig{}, err
            }
            slots = append(slots, crewSlot{agent: agentName, model: model})
        case crewActionRemove:
            idx, err := promptCrewRemove(ctx, slots)
            if err != nil {
                return settings.ReviewProfileConfig{}, err
            }
            if idx >= 0 && idx < len(slots) {
                slots = append(slots[:idx], slots[idx+1:]...)
            }
        case crewActionDone:
            if len(slots) == 0 {
                fmt.Fprintln(out, "Add at least one slot before finishing.")
                continue
            }   
        }
    }
}

// promptCrewAction shows the current crew and asks what to do next. func promptCrewAction(ctx context.Context, slots []crewSlot) (string, error) { options := []huh.Option[string]{huh.NewOption("Add a slot", crewActionAdd)} if len(slots) > 0 { options = append(options, huh.NewOption("Remove a slot", crewActionRemove), huh.NewOption(fmt.Sprintf("Done — %d slot(s)", len(slots)), crewActionDone), ) } else { options = append(options, huh.NewOption("Done (no slots yet)", crewActionDone)) } picked := crewActionDone if len(slots) == 0 { picked = crewActionAdd } }

// promptAddAnotherSlot asks whether to add another worker. Defaults to Done, so // pressing enter finishes the crew. func promptAddAnotherSlot(ctx context.Context) (bool, error) { add := false form := newAccessibleForm(huh.NewGroup( huh.NewSelectstring. Title("Review crew"). Description(crewSummary(slots)). Options(options...). Height(reviewPickerHeight(len(options))). Value(&picked), huh.NewConfirm(). Title("Add another worker?"). Affirmative("Add another"). Negative("Done"). Value(&add), )) }

func crewSummary(slots []crewSlot) string { if len(slots) == 0 { return "No slots yet. Add at least one worker (agent + model)." } lines := make([]string, len(slots)) for i, s := range slots { lines[i] = fmt.Sprintf("%d. %s", i+1, slotLabel(s)) } return strings.Join(lines, "\n") }

func slotLabel(s crewSlot) string { return s.agent + " with model " + s.model }

// promptCrewRemove picks which slot to drop. Returns the slot index. func promptCrewRemove(ctx context.Context, slots []crewSlot) (int, error) { options := make([]huh.Option[int], 0, len(slots)) for i, s := range slots { options = append(options, huh.NewOption(fmt.Sprintf("%d. %s", i+1, slotLabel(s)), i)) } picked := 0 form := newAccessibleForm(huh.NewGroup( huh.NewSelectint. Title("Remove which slot?"). Options(options...). Height(reviewPickerHeight(len(options))). Value(&picked), )) }