docs(FN-808): document nested model menu and add regression tests
- Document nested model menu behavior in QuickEntryBox in AGENTS.md - Add README section describing the model selection nested menu pattern - Add regression tests for nested model menu submenu open/close behavior
This commit is contained in:
@@ -585,7 +585,7 @@ Both components provide the same task creation experience with the following opt
|
||||
|
||||
- **Description input** — Type the task description. Press Enter to create immediately, or use the action buttons for AI-assisted creation.
|
||||
- **Deps button** — Add task dependencies before creation.
|
||||
- **Models button** — Override the default AI models for this task (executor and validator).
|
||||
- **Models button** — Opens a nested menu with Plan, Executor, and Validator roles. Each role opens a submenu with a model dropdown for per-task overrides.
|
||||
- **Plan button** (Lightbulb icon) — Opens the AI Planning Mode modal with the current description pre-filled. This allows refining the task through an interactive Q&A before creation.
|
||||
- **Subtask button** (ListTree icon) — Opens the subtask breakdown dialog with the current description pre-filled. The dialog generates 2–5 AI-suggested subtasks, lets the user edit titles, descriptions, sizes, and dependencies, and then creates all subtasks in one action.
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -339,6 +339,18 @@ When creating tasks, the AI can refine your description:
|
||||
- Suggests appropriate file scopes and steps
|
||||
- Available in both Quick Entry and planning mode
|
||||
|
||||
### Quick Entry Model Selection
|
||||
|
||||
The quick entry box provides a **Models** button (🧠) that opens a nested menu for overriding AI models on a per-task basis:
|
||||
|
||||
1. Click the **Models** button (🧠) to open the top-level menu
|
||||
2. Choose a role: **Plan**, **Executor**, or **Validator**
|
||||
3. Select a specific model from the dropdown submenu
|
||||
4. Press **Back** or Escape to return to the role selector
|
||||
5. The menu shows "Using default" for roles without an override and highlights roles with a custom selection
|
||||
|
||||
The selected executor and validator models are included in the task creation payload. Planning model overrides apply only during task specification (triage).
|
||||
|
||||
### Manual Plan Approval
|
||||
|
||||
Enable `requirePlanApproval` in settings for manual review of AI-generated specifications:
|
||||
|
||||
@@ -646,6 +646,95 @@ describe("QuickEntryBox", () => {
|
||||
expect(screen.getByTestId("model-menu-validator")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("Escape from submenu returns to top-level menu without closing it", () => {
|
||||
renderQuickEntryBox({});
|
||||
expandQuickEntry();
|
||||
const textarea = screen.getByTestId("quick-entry-input");
|
||||
|
||||
fireEvent.change(textarea, { target: { value: "Task with models" } });
|
||||
fireEvent.click(screen.getByTestId("quick-entry-models-button"));
|
||||
fireEvent.click(screen.getByTestId("model-menu-executor"));
|
||||
|
||||
// Should be in submenu — back button visible
|
||||
expect(screen.getByTestId("model-submenu-back")).toBeTruthy();
|
||||
|
||||
// Press Escape — should go back to top-level, not close the entire menu
|
||||
fireEvent.keyDown(textarea, { key: "Escape" });
|
||||
|
||||
// Top-level menu items should be visible again
|
||||
expect(screen.getByTestId("model-menu-plan")).toBeTruthy();
|
||||
expect(screen.getByTestId("model-menu-executor")).toBeTruthy();
|
||||
expect(screen.getByTestId("model-menu-validator")).toBeTruthy();
|
||||
// Submenu should not be visible
|
||||
expect(screen.queryByTestId("model-submenu-back")).toBeNull();
|
||||
});
|
||||
|
||||
it("selecting Plan model updates the Plan menu item value", () => {
|
||||
renderQuickEntryBox({});
|
||||
expandQuickEntry();
|
||||
const textarea = screen.getByTestId("quick-entry-input");
|
||||
|
||||
fireEvent.change(textarea, { target: { value: "Task with models" } });
|
||||
fireEvent.click(screen.getByTestId("quick-entry-models-button"));
|
||||
fireEvent.click(screen.getByTestId("model-menu-plan"));
|
||||
|
||||
// Select a model via mocked dropdown
|
||||
fireEvent.click(screen.getByTestId("dropdown-select-plan model"));
|
||||
|
||||
// Go back to top-level menu
|
||||
fireEvent.click(screen.getByTestId("model-submenu-back"));
|
||||
|
||||
// Plan menu item should show the selected model, not "Using default"
|
||||
const planItem = screen.getByTestId("model-menu-plan");
|
||||
expect(planItem.textContent).toContain("anthropic/claude-sonnet-4-5");
|
||||
expect(planItem.textContent).not.toContain("Using default");
|
||||
// Should have active class
|
||||
expect(planItem.classList.contains("model-menu-item--active")).toBe(true);
|
||||
});
|
||||
|
||||
it("selecting Validator model updates the Validator menu item value", () => {
|
||||
renderQuickEntryBox({});
|
||||
expandQuickEntry();
|
||||
const textarea = screen.getByTestId("quick-entry-input");
|
||||
|
||||
fireEvent.change(textarea, { target: { value: "Task with models" } });
|
||||
fireEvent.click(screen.getByTestId("quick-entry-models-button"));
|
||||
fireEvent.click(screen.getByTestId("model-menu-validator"));
|
||||
|
||||
// Select a model via mocked dropdown
|
||||
fireEvent.click(screen.getByTestId("dropdown-select-validator model"));
|
||||
|
||||
// Go back to top-level menu
|
||||
fireEvent.click(screen.getByTestId("model-submenu-back"));
|
||||
|
||||
// Validator menu item should show the selected model
|
||||
const validatorItem = screen.getByTestId("model-menu-validator");
|
||||
expect(validatorItem.textContent).toContain("anthropic/claude-sonnet-4-5");
|
||||
expect(validatorItem.classList.contains("model-menu-item--active")).toBe(true);
|
||||
});
|
||||
|
||||
it("clearing Plan model returns menu item to default state", () => {
|
||||
renderQuickEntryBox({});
|
||||
expandQuickEntry();
|
||||
const textarea = screen.getByTestId("quick-entry-input");
|
||||
|
||||
fireEvent.change(textarea, { target: { value: "Task with models" } });
|
||||
fireEvent.click(screen.getByTestId("quick-entry-models-button"));
|
||||
fireEvent.click(screen.getByTestId("model-menu-plan"));
|
||||
|
||||
// Select then clear model
|
||||
fireEvent.click(screen.getByTestId("dropdown-select-plan model"));
|
||||
fireEvent.click(screen.getByTestId("dropdown-clear-plan model"));
|
||||
|
||||
// Go back to top-level menu
|
||||
fireEvent.click(screen.getByTestId("model-submenu-back"));
|
||||
|
||||
// Plan menu item should show "Using default" and no active class
|
||||
const planItem = screen.getByTestId("model-menu-plan");
|
||||
expect(planItem.textContent).toContain("Using default");
|
||||
expect(planItem.classList.contains("model-menu-item--active")).toBe(false);
|
||||
});
|
||||
|
||||
it("selects dependencies and includes them in submit payload", async () => {
|
||||
const { props } = renderQuickEntryBox({});
|
||||
expandQuickEntry();
|
||||
|
||||
Reference in New Issue
Block a user