Skip to content

Commit 999ac55

Browse files
authored
ADE-35: Use autorresearch and computer use on missions tab
Ship ADE-35 missions tab autorresearch and computer-use updates.
1 parent ea7ea14 commit 999ac55

53 files changed

Lines changed: 6455 additions & 384 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/desktop/scripts/dev.cjs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,9 @@ async function main() {
293293
const electronEnv = { VITE_DEV_SERVER_URL: devServerUrl };
294294
const launchElectron = () => {
295295
const electronArgs = ["electron", `--remote-debugging-port=${remoteDebugPort}`];
296-
// Electron treats the first non-switch argument as the app path. Keep "."
297-
// before paired macOS process flags so their value is not parsed as the app.
298-
electronArgs.push(".");
296+
// Electron treats the first non-switch argument as the app path. Use the
297+
// absolute app root so macOS launches do not fall back to default_app.asar.
298+
electronArgs.push(projectRoot);
299299
if (process.platform === "darwin") {
300300
electronArgs.push("-ApplePersistenceIgnoreState", "YES");
301301
}

apps/desktop/src/main/main.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,9 +532,12 @@ async function createWindow(args: {
532532
icon = nativeImage.createEmpty();
533533
}
534534

535+
const defaultWindowBounds = isDev
536+
? { width: 1460, height: 880 }
537+
: { width: 1280, height: 820 };
538+
535539
const win = new BrowserWindow({
536-
width: 1280,
537-
height: 820,
540+
...defaultWindowBounds,
538541
icon,
539542
// Hide the native title bar but keep macOS traffic lights.
540543
titleBarStyle: "hiddenInset",

apps/desktop/src/main/services/missions/missionService.test.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,9 @@ describe("missionService lifecycle", () => {
860860
position: index,
861861
askQuestions: phase.phaseKey === "development"
862862
? { enabled: true, maxQuestions: 9 }
863-
: phase.askQuestions,
863+
: phase.phaseKey === "planning"
864+
? { ...phase.askQuestions, requiredBeforeExit: true }
865+
: phase.askQuestions,
864866
validationGate: phase.phaseKey === "planning"
865867
? { tier: "self", required: true, criteria: "Should be removed" }
866868
: phase.validationGate,
@@ -871,12 +873,67 @@ describe("missionService lifecycle", () => {
871873
const development = created.phaseConfiguration?.selectedPhases.find((phase) => phase.phaseKey === "development");
872874
expect(planning?.validationGate.tier).toBe("none");
873875
expect(planning?.validationGate.required).toBe(false);
876+
expect(planning?.askQuestions.requiredBeforeExit).toBe(true);
877+
expect(planning?.requiresApproval).toBe(true);
874878
expect(development?.askQuestions.enabled).toBe(false);
875879
expect(development?.askQuestions.maxQuestions).toBeUndefined();
876880

877881
dispose();
878882
});
879883

884+
it("preserves ask-question settings on custom phases", async () => {
885+
const { db, projectId, laneId, dispose } = await createDbWithProjectAndLane();
886+
const service = createMissionService({ db, projectId });
887+
const defaultProfile = service.listPhaseProfiles().find((profile) => profile.isDefault);
888+
if (!defaultProfile) throw new Error("Expected default profile");
889+
890+
const now = "2026-03-25T00:00:00.000Z";
891+
const customPhase: PhaseCard = {
892+
id: "custom:discovery",
893+
phaseKey: "discovery_requirements",
894+
name: "Discovery / Requirements",
895+
description: "Clarify requirements before development.",
896+
instructions: "Ask blocking questions, produce a requirements brief, and report risks before development.",
897+
model: defaultProfile.phases[0]!.model,
898+
budget: {},
899+
orderingConstraints: { mustFollow: ["planning"], mustPrecede: ["development"] },
900+
askQuestions: { enabled: true, maxQuestions: 5, requiredBeforeExit: true },
901+
validationGate: { tier: "none", required: false },
902+
isBuiltIn: false,
903+
isCustom: true,
904+
position: 1,
905+
createdAt: now,
906+
updatedAt: now,
907+
};
908+
const phaseOverride = [
909+
defaultProfile.phases.find((phase) => phase.phaseKey === "planning")!,
910+
customPhase,
911+
...defaultProfile.phases.filter((phase) => phase.phaseKey !== "planning"),
912+
].map((phase, index) => ({ ...phase, position: index }));
913+
914+
const created = service.create({
915+
prompt: "Build a launch dashboard after discovery.",
916+
laneId,
917+
phaseProfileId: defaultProfile.id,
918+
phaseOverride,
919+
});
920+
921+
const selected = created.phaseConfiguration?.selectedPhases ?? [];
922+
const persistedCustom = selected.find((phase) => phase.phaseKey === "discovery_requirements");
923+
expect(selected.map((phase) => phase.phaseKey).slice(0, 3)).toEqual([
924+
"planning",
925+
"discovery_requirements",
926+
"development",
927+
]);
928+
expect(persistedCustom?.askQuestions).toEqual({
929+
enabled: true,
930+
maxQuestions: 5,
931+
requiredBeforeExit: true,
932+
});
933+
934+
dispose();
935+
});
936+
880937
it("returns mission dashboard snapshots for active/recent/weekly views", async () => {
881938
const { db, projectId, laneId, dispose } = await createDbWithProjectAndLane();
882939
const service = createMissionService({ db, projectId });

apps/desktop/src/main/services/missions/missionService.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ function toPhaseCard(value: unknown, fallbackPosition = 0): PhaseCard | null {
507507
askQuestions: {
508508
enabled: coerceBoolean(askQuestions.enabled),
509509
maxQuestions: coerceNumber(askQuestions.maxQuestions),
510+
requiredBeforeExit: askQuestions.requiredBeforeExit === true ? true : undefined,
510511
},
511512
validationGate: {
512513
tier,
@@ -515,6 +516,7 @@ function toPhaseCard(value: unknown, fallbackPosition = 0): PhaseCard | null {
515516
evidenceRequirements: toEvidenceRequirements(validationGate.evidenceRequirements),
516517
capabilityFallback: toCapabilityFallback(validationGate.capabilityFallback),
517518
},
519+
requiresApproval: coerceBoolean(value.requiresApproval),
518520
isBuiltIn: coerceBoolean(value.isBuiltIn),
519521
isCustom: coerceBoolean(value.isCustom, true),
520522
position,
@@ -537,7 +539,10 @@ function normalizePhaseCards(phases: PhaseCard[]): PhaseCard[] {
537539
const phaseKey = String(phase.phaseKey ?? "").trim().toLowerCase();
538540
const planningPhase = phaseKey === "planning";
539541
const testingOrValidation = phaseKey === "testing" || phaseKey === "validation";
540-
const askQuestionsEnabled = planningPhase && phase.askQuestions.enabled !== false;
542+
const customPhase = phase.isCustom === true || phase.isBuiltIn !== true;
543+
const askQuestionsEnabled = planningPhase
544+
? phase.askQuestions.enabled !== false
545+
: customPhase && phase.askQuestions.enabled === true;
541546
const rawMaxQuestions = phase.askQuestions.maxQuestions;
542547
const askQuestions: PhaseCard["askQuestions"] = {
543548
...phase.askQuestions,
@@ -547,6 +552,7 @@ function normalizePhaseCards(phases: PhaseCard[]): PhaseCard[] {
547552
? null
548553
: Math.max(1, Math.min(10, Number(rawMaxQuestions) || 5))
549554
: undefined,
555+
requiredBeforeExit: askQuestionsEnabled && phase.askQuestions.requiredBeforeExit === true ? true : undefined,
550556
};
551557
const validationGate: PhaseCard["validationGate"] = planningPhase || phaseKey === "development"
552558
? {
@@ -4277,6 +4283,7 @@ export function createMissionService({
42774283
if (resolutionKind === "accept_defaults") return `${row.title} — user accepted defaults.`;
42784284
if (resolutionKind === "skip_question") return `${row.title} — user skipped the question.`;
42794285
if (resolutionKind === "cancel_run") return `${row.title} — user canceled the run.`;
4286+
if (resolutionKind === "stale_phase_approval") return `${row.title} — stale phase approval closed.`;
42804287
if (targetStatus === "dismissed") return `${row.title} — dismissed.`;
42814288
return `${row.title} — answer provided.`;
42824289
})();

0 commit comments

Comments
 (0)