@@ -1296,21 +1296,33 @@ function parsePrefixedBatchInput(input: string, types: EncodingTypeDef[]): Parse
12961296 const title = first . split ( / \s + / ) . length <= 12
12971297 ? first
12981298 : first . split ( / \s + / ) . slice ( 0 , 8 ) . join ( " " ) + "..." ;
1299- artifacts . push ( {
1299+ const untagged : ParsedArtifact = {
13001300 type : pick . letter ,
13011301 typeName : pick . name ,
13021302 fields : [ pick . letter , title , para ] ,
13031303 title,
13041304 body : para ,
1305- } ) ;
1305+ } ;
1306+ if ( pick . facet ) untagged . facet = pick . facet ;
1307+ artifacts . push ( untagged ) ;
13061308 }
13071309 }
13081310
13091311 return artifacts ;
13101312}
13111313
13121314function parseStructuredInput ( input : string , types : EncodingTypeDef [ ] ) : ParsedArtifact [ ] {
1313- const typeMap = new Map ( types . map ( ( t ) => [ t . letter , t . name ] ) ) ;
1315+ // TSV has no facet column, so a bare letter must resolve to the no-facet
1316+ // peer (closed Observation for "O"). A naive letter→name Map collides when
1317+ // peers share a letter (Observation + Open both letter "O") — last-write
1318+ // wins under alphabetical canon ordering put "Open" on the "O" key. Prefer
1319+ // the no-facet entry; fall back to the first registered name when no
1320+ // no-facet entry exists. Per E0008.4 Phase 2 Item 2.
1321+ const typeMap = new Map < string , string > ( ) ;
1322+ for ( const t of types ) {
1323+ const existing = typeMap . get ( t . letter ) ;
1324+ if ( existing === undefined || ! t . facet ) typeMap . set ( t . letter , t . name ) ;
1325+ }
13141326 return input . split ( "\n" ) . filter ( ( l ) => l . trim ( ) . length > 0 ) . map ( ( line ) => {
13151327 const fields = line . split ( "\t" ) ;
13161328 const letter = fields [ 0 ] ?. trim ( ) || "D" ;
@@ -1341,15 +1353,19 @@ function parseUnstructuredInput(input: string, types: EncodingTypeDef[]): Parsed
13411353 if ( matchesStemmedPhrases ( t . stemmedPhrases , inputStems ) ) {
13421354 const first = para . split ( / [ . ! ? \n ] / ) [ 0 ] ?. trim ( ) || para . slice ( 0 , 60 ) ;
13431355 const title = first . split ( / \s + / ) . length <= 12 ? first : first . split ( / \s + / ) . slice ( 0 , 8 ) . join ( " " ) + "..." ;
1344- artifacts . push ( { type : t . letter , typeName : t . name , fields : [ t . letter , title , para . trim ( ) ] , title, body : para . trim ( ) } ) ;
1356+ const a : ParsedArtifact = { type : t . letter , typeName : t . name , fields : [ t . letter , title , para . trim ( ) ] , title, body : para . trim ( ) } ;
1357+ if ( t . facet ) a . facet = t . facet ;
1358+ artifacts . push ( a ) ;
13451359 matched = true ;
13461360 }
13471361 }
13481362 if ( ! matched ) {
13491363 const first = para . split ( / [ . ! ? \n ] / ) [ 0 ] ?. trim ( ) || para . slice ( 0 , 60 ) ;
13501364 const title = first . split ( / \s + / ) . length <= 12 ? first : first . split ( / \s + / ) . slice ( 0 , 8 ) . join ( " " ) + "..." ;
13511365 const fallback = types [ 0 ] || { letter : "D" , name : "Decision" } ;
1352- artifacts . push ( { type : fallback . letter , typeName : fallback . name , fields : [ fallback . letter , title , para . trim ( ) ] , title, body : para . trim ( ) } ) ;
1366+ const a : ParsedArtifact = { type : fallback . letter , typeName : fallback . name , fields : [ fallback . letter , title , para . trim ( ) ] , title, body : para . trim ( ) } ;
1367+ if ( fallback . facet ) a . facet = fallback . facet ;
1368+ artifacts . push ( a ) ;
13531369 }
13541370 }
13551371 return artifacts ;
0 commit comments