@@ -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 } ) ;
0 commit comments