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
cmd/entire/cli/review
Mpicker.go+32/-97
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), )) }