@@ -195,23 +195,67 @@ const ResearchApproachOutputSchema = z.object({
195195 recommendation : z . string ( )
196196} ) ;
197197
198+ function pickStructuredOutput < T > ( rawOutput : T , expectedKeys : string [ ] ) : any {
199+ const envelopeCandidates = [
200+ ( rawOutput as any ) ?. output ,
201+ ( rawOutput as any ) ?. finalOutput ,
202+ ( rawOutput as any ) ?. processedResult ,
203+ ( rawOutput as any ) ?. result ,
204+ ] . filter ( ( candidate ) => candidate && typeof candidate === 'object' ) ;
205+ const candidates = [
206+ rawOutput ,
207+ ...envelopeCandidates ,
208+ ] ;
209+ const match = candidates . find ( ( candidate ) =>
210+ candidate &&
211+ typeof candidate === 'object' &&
212+ expectedKeys . some ( ( key ) => Object . prototype . hasOwnProperty . call ( candidate , key ) )
213+ ) ;
214+ return match || envelopeCandidates [ 0 ] || rawOutput ;
215+ }
216+
217+ function normalizeResearchApproachOutput (
218+ rawOutput : z . infer < typeof ResearchApproachOutputSchema >
219+ ) : z . infer < typeof ResearchApproachOutputSchema > {
220+ const output = pickStructuredOutput ( rawOutput , [ 'approach' ] ) ;
221+ const approach = output ?. approach && typeof output . approach === 'object' ? output . approach : { } ;
222+ return {
223+ approach : {
224+ methodology : typeof approach . methodology === 'string' ? approach . methodology : '' ,
225+ phases : Array . isArray ( approach . phases ) ? approach . phases : [ ] ,
226+ tools : Array . isArray ( approach . tools ) ? approach . tools : [ ] ,
227+ estimatedEffort : typeof approach . estimatedEffort === 'string' ? approach . estimatedEffort : '' ,
228+ } ,
229+ alternatives : Array . isArray ( output ?. alternatives ) ? output . alternatives : [ ] ,
230+ risks : Array . isArray ( output ?. risks ) ? output . risks : [ ] ,
231+ recommendation : typeof output ?. recommendation === 'string' ? output . recommendation : '' ,
232+ } ;
233+ }
234+
198235export function applyResearchApproachSemanticMirrors (
199- output : z . infer < typeof ResearchApproachOutputSchema >
236+ rawOutput : z . infer < typeof ResearchApproachOutputSchema >
200237) : z . infer < typeof ResearchApproachOutputSchema > {
238+ const output = normalizeResearchApproachOutput ( rawOutput ) ;
201239 return {
202240 ...output ,
203241 approach : {
204242 ...output . approach ,
205- phases : output . approach . phases . map ( ( phase ) => ( {
206- ...phase ,
207- writtenAssets :
208- phase . writtenAssets ??
209- phase . assetPackSynthesisArtifacts ??
210- phase . shippables ,
211- assetPackSynthesisArtifacts :
212- phase . assetPackSynthesisArtifacts ??
213- phase . writtenAssets ,
214- } ) ) ,
243+ phases : output . approach . phases . map ( ( phase ) => {
244+ const normalizedPhase : any =
245+ phase && typeof phase === 'object'
246+ ? phase
247+ : { name : String ( phase || '' ) , description : '' } ;
248+ return {
249+ ...normalizedPhase ,
250+ writtenAssets :
251+ normalizedPhase . writtenAssets ??
252+ normalizedPhase . assetPackSynthesisArtifacts ??
253+ normalizedPhase . shippables ,
254+ assetPackSynthesisArtifacts :
255+ normalizedPhase . assetPackSynthesisArtifacts ??
256+ normalizedPhase . writtenAssets ,
257+ } ;
258+ } ) ,
215259 } ,
216260 } ;
217261}
@@ -327,9 +371,41 @@ const PlanImplementationOutputSchema = z.object({
327371 readSatisfactionCriteria : z . array ( z . string ( ) ) . optional ( )
328372} ) ;
329373
374+ function normalizePlanImplementationOutput (
375+ rawOutput : z . infer < typeof PlanImplementationOutputSchema >
376+ ) : z . infer < typeof PlanImplementationOutputSchema > {
377+ const output = pickStructuredOutput ( rawOutput , [ 'implementationPlan' ] ) ;
378+ const implementationPlan =
379+ output ?. implementationPlan && typeof output . implementationPlan === 'object'
380+ ? output . implementationPlan
381+ : { } ;
382+ const testingStrategy =
383+ output ?. testingStrategy && typeof output . testingStrategy === 'object'
384+ ? output . testingStrategy
385+ : { } ;
386+ return {
387+ implementationPlan : {
388+ overview : typeof implementationPlan . overview === 'string' ? implementationPlan . overview : '' ,
389+ milestones : Array . isArray ( implementationPlan . milestones ) ? implementationPlan . milestones : [ ] ,
390+ dependencies : Array . isArray ( implementationPlan . dependencies ) ? implementationPlan . dependencies : [ ] ,
391+ } ,
392+ testingStrategy : {
393+ approach : typeof testingStrategy . approach === 'string' ? testingStrategy . approach : '' ,
394+ testTypes : Array . isArray ( testingStrategy . testTypes ) ? testingStrategy . testTypes : [ ] ,
395+ coverage : typeof testingStrategy . coverage === 'string' ? testingStrategy . coverage : '' ,
396+ } ,
397+ validationCriteria : Array . isArray ( output ?. validationCriteria ) ? output . validationCriteria : [ ] ,
398+ definitionOfRead : Array . isArray ( output ?. definitionOfRead ) ? output . definitionOfRead : undefined ,
399+ readSatisfactionCriteria : Array . isArray ( output ?. readSatisfactionCriteria )
400+ ? output . readSatisfactionCriteria
401+ : undefined ,
402+ } ;
403+ }
404+
330405export function applyPlanImplementationSemanticMirrors (
331- output : z . infer < typeof PlanImplementationOutputSchema >
406+ rawOutput : z . infer < typeof PlanImplementationOutputSchema >
332407) : z . infer < typeof PlanImplementationOutputSchema > {
408+ const output = normalizePlanImplementationOutput ( rawOutput ) ;
333409 return {
334410 ...output ,
335411 readSatisfactionCriteria : output . readSatisfactionCriteria ?? output . definitionOfRead ,
0 commit comments