refactor(FN-1353): simplify mission autopilot to single toggle

- Deprecate autoAdvance field in favor of autopilotEnabled as the sole control
- Remove autoAdvance guard logic from MissionAutopilot engine class
- Simplify MissionManager UI to use single autopilot toggle with visual state indicator
- Update MissionAutopilot tests to use autopilotEnabled instead of autoAdvance
- Update MissionManager component tests for simplified UI
- Update AGENTS.md documentation to reflect the simplified autopilot model
This commit is contained in:
gsxdsm
2026-04-09 13:45:19 -07:00
parent 4ef5d73ba1
commit e26321790c
7 changed files with 76 additions and 244 deletions

View File

@@ -1005,7 +1005,6 @@ describe("MissionAutopilot", () => {
ap.setScheduler(newScheduler);
// Now advanceToNextSlice should use the new scheduler
// (but will be blocked by autoAdvance guard since default mission has autoAdvance: true)
newScheduler.activateNextPendingSlice.mockResolvedValue(
createMockSlice({ id: "SL-002", status: "active" }),
);
@@ -1016,42 +1015,10 @@ describe("MissionAutopilot", () => {
});
});
// ── autoAdvance guard ────────────────────────────────────────────
// ── Slice Advancement ────────────────────────────────────────────
describe("autoAdvance guard", () => {
it("should not advance slice when autoAdvance is false", async () => {
const mission = createMockMission({ autoAdvance: false });
const store = createMockMissionStore([mission]);
const ap = new MissionAutopilot(taskStore as any, store as any, { scheduler });
ap.start();
ap.watchMission("M-TEST1");
await ap.advanceToNextSlice("M-TEST1");
// Should NOT call scheduler to activate next slice
expect(scheduler.activateNextPendingSlice).not.toHaveBeenCalled();
ap.stop();
});
it("should not advance slice when autoAdvance is undefined", async () => {
const mission = createMockMission({ autoAdvance: undefined });
const store = createMockMissionStore([mission]);
const ap = new MissionAutopilot(taskStore as any, store as any, { scheduler });
ap.start();
ap.watchMission("M-TEST1");
await ap.advanceToNextSlice("M-TEST1");
// Should NOT call scheduler to activate next slice
expect(scheduler.activateNextPendingSlice).not.toHaveBeenCalled();
ap.stop();
});
it("should advance slice when autoAdvance is true", async () => {
describe("slice advancement", () => {
it("should advance slice when autopilot is watching", async () => {
autopilot.watchMission("M-TEST1");
const activatedSlice = createMockSlice({ id: "SL-002", status: "active" });
scheduler.activateNextPendingSlice.mockResolvedValue(activatedSlice);
@@ -1060,5 +1027,12 @@ describe("MissionAutopilot", () => {
expect(scheduler.activateNextPendingSlice).toHaveBeenCalledWith("M-TEST1");
});
it("should not advance slice when mission is not being watched", async () => {
// Don't watch the mission
await autopilot.advanceToNextSlice("M-TEST1");
expect(scheduler.activateNextPendingSlice).not.toHaveBeenCalled();
});
});
});

View File

@@ -173,7 +173,6 @@ export class MissionAutopilot {
{
source: "watchMission",
missionStatus: mission.status,
autoAdvance: mission.autoAdvance ?? false,
},
);
autopilotLog.log(`Watching mission ${missionId} (${mission.title})`);
@@ -360,15 +359,6 @@ export class MissionAutopilot {
const state = this.watchedMissions.get(missionId);
if (!state) return;
// Respect the mission's autoAdvance setting — if the user opted for
// manual slice activation, autopilot should NOT auto-advance even when
// it is watching and enabled.
const mission = this.missionStore.getMission(missionId);
if (!mission?.autoAdvance) {
autopilotLog.log(`Mission ${missionId} has autoAdvance disabled — skipping slice activation`);
return;
}
try {
this.setAutopilotState(missionId, "activating");