@@ -32,7 +32,10 @@ const pathOpt = z
3232 * 13. *.spm.json 14. *.spm.md 15. *.spm/
3333 * 16. *.sysprom.json 17. *.sysprom.md 18. *.sysprom/
3434 *
35- * All matching is case-insensitive. Glob tiers must have exactly one match.
35+ * Matching is case-insensitive for base names and directory matches.
36+ * Files like .SysProM.json, .sysprom.json, and .SYSPROM.JSON are treated
37+ * as equivalent and all match the .SysProM.json priority tier.
38+ * Glob tiers must have exactly one match.
3639 * @param input - Explicit document path, or undefined for auto-detection.
3740 * @param cwd - Working directory to search from (defaults to `.`).
3841 * @returns The resolved document path.
@@ -47,7 +50,6 @@ export function resolveInput(input?: string, cwd?: string): string {
4750
4851 const dir = resolve ( cwd ?? "." ) ;
4952
50- // Exact names to check, in priority order (case-insensitive)
5153 const exactNames = [
5254 ".SysProM.json" ,
5355 ".SysProM.md" ,
@@ -62,12 +64,35 @@ export function resolveInput(input?: string, cwd?: string): string {
6264
6365 const entries = readdirSync ( dir ) ;
6466
67+ // Phase 1: Try exact case-sensitive matches first
6568 for ( const name of exactNames ) {
6669 const isDirSuffix =
6770 name . endsWith ( ".SysProM" ) ||
6871 name . endsWith ( ".spm" ) ||
6972 name . endsWith ( ".sysprom" ) ;
70- const found = entries . filter ( ( e ) => e . toLowerCase ( ) === name ) ;
73+ const found = entries . filter ( ( e ) => e === name ) ;
74+ if ( found . length === 1 ) {
75+ const candidate = join ( dir , found [ 0 ] ) ;
76+ if ( isDirSuffix ) {
77+ try {
78+ if ( statSync ( candidate ) . isDirectory ( ) ) return candidate ;
79+ } catch {
80+ /* skip */
81+ }
82+ } else {
83+ return candidate ;
84+ }
85+ }
86+ }
87+
88+ // Phase 2: Try case-insensitive matches (supports case variations like .SPM.JSON)
89+ for ( const name of exactNames ) {
90+ const isDirSuffix =
91+ name . endsWith ( ".SysProM" ) ||
92+ name . endsWith ( ".spm" ) ||
93+ name . endsWith ( ".sysprom" ) ;
94+ const nameLower = name . toLowerCase ( ) ;
95+ const found = entries . filter ( ( e ) => e . toLowerCase ( ) === nameLower ) ;
7196 if ( found . length > 1 ) {
7297 throw new Error (
7398 `Multiple SysProM documents found: ${ found . join ( ", " ) } . Specify one explicitly.` ,
@@ -103,10 +128,17 @@ export function resolveInput(input?: string, cwd?: string): string {
103128 for ( const suffix of globSuffixes ) {
104129 const isDirSuffix =
105130 suffix === ".SysProM" || suffix === ".spm" || suffix === ".sysprom" ;
131+ const suffixLower = suffix . toLowerCase ( ) ;
106132 const matches = entries
107133 . filter ( ( e ) => {
108134 const lower = e . toLowerCase ( ) ;
109- return lower . endsWith ( suffix ) && lower !== suffix ;
135+ // Match files ending with this suffix (case-insensitive) that don't start with "."
136+ // and are not exact matches (those were already checked)
137+ return (
138+ lower . endsWith ( suffixLower ) &&
139+ lower !== suffixLower &&
140+ ! e . startsWith ( "." )
141+ ) ;
110142 } )
111143 . map ( ( e ) => join ( dir , e ) )
112144 . filter ( ( p ) => {
0 commit comments