@@ -233,7 +233,11 @@ async function runSemantic(sql: string, file: string, schemaPath?: string): Prom
233233 }
234234}
235235
236- async function runGrade ( sql : string , file : string , schemaPath ?: string ) : Promise < Finding [ ] > {
236+ async function runGrade (
237+ sql : string ,
238+ file : string ,
239+ schemaPath ?: string ,
240+ ) : Promise < { findings : Finding [ ] ; grade ?: string ; score ?: number } > {
237241 try {
238242 const result = await Dispatcher . call ( "altimate_core.grade" , {
239243 sql,
@@ -243,7 +247,7 @@ async function runGrade(sql: string, file: string, schemaPath?: string): Promise
243247 const issues = ( result . data . issues ?? result . data . findings ?? result . data . recommendations ?? [ ] ) as Array <
244248 Record < string , unknown >
245249 >
246- return issues . map ( ( f ) => ( {
250+ const findings = issues . map ( ( f ) => ( {
247251 file,
248252 line : f . line as number | undefined ,
249253 column : f . column as number | undefined ,
@@ -253,9 +257,13 @@ async function runGrade(sql: string, file: string, schemaPath?: string): Promise
253257 message : ( f . message ?? f . description ?? "" ) as string ,
254258 suggestion : f . suggestion as string | undefined ,
255259 } ) )
260+ // Preserve the primary A-F grade value from the backend
261+ const grade = ( result . data . grade ?? result . data . letter_grade ) as string | undefined
262+ const score = ( result . data . score ?? result . data . numeric_score ) as number | undefined
263+ return { findings, grade, score }
256264 } catch ( e ) {
257265 console . error ( `[grade] error processing ${ file } : ${ e instanceof Error ? e . message : String ( e ) } ` )
258- return [ dispatcherErrorFinding ( "grade" , file , e ) ]
266+ return { findings : [ dispatcherErrorFinding ( "grade" , file , e ) ] }
259267 }
260268}
261269
@@ -321,18 +329,21 @@ export const CheckCommand = cmd({
321329 } )
322330 if ( checks . length === 0 ) {
323331 console . error ( "Error: no valid checks specified." )
324- process . exit ( 1 )
332+ process . exitCode = 1
333+ return
325334 }
326335
327336 // 2. Validate policy requirement
328337 if ( checks . includes ( "policy" ) ) {
329338 if ( ! args . policy ) {
330339 console . error ( "Error: --policy is required when running the policy check." )
331- process . exit ( 1 )
340+ process . exitCode = 1
341+ return
332342 }
333343 if ( ! existsSync ( args . policy ) ) {
334344 console . error ( `Error: policy file not found: ${ args . policy } ` )
335- process . exit ( 1 )
345+ process . exitCode = 1
346+ return
336347 }
337348 }
338349
@@ -366,7 +377,7 @@ export const CheckCommand = cmd({
366377
367378 if ( files . length === 0 ) {
368379 console . error ( "No SQL files found to check." )
369- process . exit ( 0 )
380+ return
370381 }
371382
372383 console . error ( `Found ${ files . length } SQL file(s) to check with [${ checks . join ( ", " ) } ]` )
@@ -379,13 +390,16 @@ export const CheckCommand = cmd({
379390 policyJson = readFileSync ( args . policy , "utf-8" )
380391 } catch ( e ) {
381392 console . error ( `Error reading policy file: ${ e instanceof Error ? e . message : String ( e ) } ` )
382- process . exit ( 1 )
393+ process . exitCode = 1
394+ return
383395 }
384396 }
385397
386398 // 5. Run checks on all files in batches of 10
387399 const BATCH_SIZE = 10
388400 const allResults : Record < string , Finding [ ] > = { }
401+ let gradeValue : string | undefined
402+ let gradeScore : number | undefined
389403 for ( const check of checks ) {
390404 allResults [ check ] = [ ]
391405 }
@@ -425,9 +439,13 @@ export const CheckCommand = cmd({
425439 case "semantic" :
426440 findings = await runSemantic ( sql , relFile , schemaPath )
427441 break
428- case "grade" :
429- findings = await runGrade ( sql , relFile , schemaPath )
442+ case "grade" : {
443+ const gradeResult = await runGrade ( sql , relFile , schemaPath )
444+ findings = gradeResult . findings
445+ if ( gradeResult . grade ) gradeValue = gradeResult . grade
446+ if ( gradeResult . score != null ) gradeScore = gradeResult . score
430447 break
448+ }
431449 }
432450 allResults [ check ] . push ( ...findings )
433451 }
@@ -452,7 +470,13 @@ export const CheckCommand = cmd({
452470 results [ check ] = toCategoryResult ( filterBySeverity ( findings , minSeverity ) )
453471 }
454472
455- // 8. Build output using the helper
473+ // 8. Attach grade metadata if available
474+ if ( results . grade ) {
475+ if ( gradeValue ) results . grade . grade = gradeValue
476+ if ( gradeScore != null ) results . grade . score = gradeScore
477+ }
478+
479+ // 9. Build output using the helper
456480 const output = buildCheckOutput ( {
457481 filesChecked : files . length ,
458482 checksRun : checks ,
@@ -463,7 +487,7 @@ export const CheckCommand = cmd({
463487 // Override pass with our pre-computed value from unfiltered findings
464488 output . summary . pass = pass
465489
466- // 9 . Output
490+ // 10 . Output
467491 const duration = Date . now ( ) - startTime
468492 if ( args . format === "json" ) {
469493 process . stdout . write ( JSON . stringify ( output , null , 2 ) + "\n" )
@@ -472,9 +496,10 @@ export const CheckCommand = cmd({
472496 }
473497 console . error ( `Completed in ${ duration } ms` )
474498
475- // 10. Exit code
499+ // 11. Exit code — use process.exitCode instead of process.exit() to allow
500+ // the outer finally block in index.ts to run Telemetry.shutdown().
476501 if ( ! pass ) {
477- process . exit ( 1 )
502+ process . exitCode = 1
478503 }
479504 } ,
480505} )
0 commit comments