@@ -48,14 +48,24 @@ interface YamlConfig {
4848
4949export function readYamlConfig ( filePath : string ) : YamlConfig | null {
5050 try {
51- let resolvedPath = filePath ;
52- // Only try workspace root resolution for relative paths that look like they should be relative to workspace
53- if ( ( filePath . startsWith ( './' ) || filePath . startsWith ( '../' ) ) && ! fs . existsSync ( filePath ) ) {
54- const currentDir = dirname ( fileURLToPath ( import . meta. url ) ) ;
55- const workspaceRoot = resolve ( currentDir , '..' , '..' , '..' ) ;
56- resolvedPath = resolve ( workspaceRoot , filePath ) ;
51+ // Prefer reading the path as-provided first. This ensures tests that spy on
52+ // fs.readFileSync(filePath) will be exercised. If that fails, try a
53+ // workspace-root-relative fallback for CLI invocations where paths are
54+ // relative to the repo root.
55+ let text : string ;
56+ try {
57+ text = fs . readFileSync ( filePath , "utf8" ) ;
58+ } catch ( err ) {
59+ // Only attempt workspace-root fallback for explicitly relative paths
60+ if ( filePath . startsWith ( "./" ) || filePath . startsWith ( "../" ) ) {
61+ const currentDir = dirname ( fileURLToPath ( import . meta. url ) ) ;
62+ const workspaceRoot = resolve ( currentDir , ".." , ".." , ".." ) ;
63+ const resolvedPath = resolve ( workspaceRoot , filePath ) ;
64+ text = fs . readFileSync ( resolvedPath , "utf8" ) ;
65+ } else {
66+ throw err ;
67+ }
5768 }
58- const text = fs . readFileSync ( resolvedPath , "utf8" ) ;
5969 const config = yaml . load ( text ) as YamlConfig ;
6070 return config || null ;
6171 } catch {
@@ -85,14 +95,22 @@ export function readNamesFromInputs(
8595 if ( v ) names . add ( v ) ;
8696 }
8797 } else {
88- // Fall back to plain text (one name per line)
89- let resolvedPath = filePath ;
90- if ( ( filePath . startsWith ( './' ) || filePath . startsWith ( '../' ) ) && ! fs . existsSync ( filePath ) ) {
91- const currentDir = dirname ( fileURLToPath ( import . meta. url ) ) ;
92- const workspaceRoot = resolve ( currentDir , '..' , '..' , '..' ) ;
93- resolvedPath = resolve ( workspaceRoot , filePath ) ;
98+ // Fall back to plain text (one name per line). Prefer reading the
99+ // provided path first (so tests can mock readFileSync), and only if
100+ // that fails attempt the workspace-root-relative fallback.
101+ let text : string ;
102+ try {
103+ text = fs . readFileSync ( filePath , "utf8" ) ;
104+ } catch ( err ) {
105+ if ( filePath . startsWith ( "./" ) || filePath . startsWith ( "../" ) ) {
106+ const currentDir = dirname ( fileURLToPath ( import . meta. url ) ) ;
107+ const workspaceRoot = resolve ( currentDir , ".." , ".." , ".." ) ;
108+ const resolvedPath = resolve ( workspaceRoot , filePath ) ;
109+ text = fs . readFileSync ( resolvedPath , "utf8" ) ;
110+ } else {
111+ throw err ;
112+ }
94113 }
95- const text = fs . readFileSync ( resolvedPath , "utf8" ) ;
96114 for ( const line of text . split ( / \r ? \n / ) ) {
97115 const t = line . trim ( ) . toLowerCase ( ) ;
98116 if ( t ) names . add ( t ) ;
@@ -265,7 +283,12 @@ export async function runChecks(
265283 ) ;
266284 parsed = p ;
267285 raw = r ?? "" ;
268- status = inferAvailability ( parsed , raw ) ;
286+ // If parsed object is empty and we didn't receive any raw text, be conservative
287+ if ( parsed && Object . keys ( parsed ) . length === 0 && ! raw ) {
288+ status = "unknown" ;
289+ } else {
290+ status = inferAvailability ( parsed , raw ) ;
291+ }
269292 } catch ( e : any ) {
270293 raw = String ( e ) ;
271294 status = "error" ;
0 commit comments