Skip to content

Commit 5c1f5db

Browse files
committed
Validate extraction output against poster_schema v0.2
Point validation.py at the full v0.2 poster_schema.json instead of the v0.1 extraction schema, and sync the local schema copy from the canonical poster-json-schema repo. The old v0.1 extraction schema only allowed string affiliations and so rejected the ROR affiliation objects the extractor now emits; the full v0.2 schema accepts them. Platform-owned fields that are filled in on the website (conference, publicationYear) surface as non-blocking warnings rather than errors, so validation never rejects an extraction. publisher null is now valid after the sync. The v0.1 extraction schema file is kept as version history.
1 parent 70e7240 commit 5c1f5db

2 files changed

Lines changed: 119 additions & 104 deletions

File tree

poster_schema.json

Lines changed: 105 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,11 @@
258258
"uniqueItems": true
259259
},
260260
"publisher": {
261-
"type": "object",
262-
"description": "The entity that hosts, archives, publishes, prints, distributes, releases, issues, or produces the resource. This property will be used to formulate the citation, so consider the prominence of the role.",
261+
"type": [
262+
"object",
263+
"null"
264+
],
265+
"description": "The entity that hosts, archives, publishes, prints, distributes, releases, issues, or produces the resource. This property will be used to formulate the citation, so consider the prominence of the role. May be null as a placeholder when it is filled downstream by the hosting platform.",
263266
"properties": {
264267
"name": {
265268
"type": "string",
@@ -420,63 +423,7 @@
420423
"minLength": 1
421424
},
422425
"dateType": {
423-
"type": "string",
424-
"description": "The type of date of the item.",
425-
"minLength": 1,
426-
"oneOf": [
427-
{
428-
"const": "Accepted",
429-
"description": "The date that the publisher accepted the resource into their system."
430-
},
431-
{
432-
"const": "Available",
433-
"description": "The date the resource is made publicly available. May be a range."
434-
},
435-
{
436-
"const": "Copyrighted",
437-
"description": "The specific, documented date at which the resource receives a copyrighted status, if applicable."
438-
},
439-
{
440-
"const": "Collected",
441-
"description": "The date or date range in which the resource content was collected."
442-
},
443-
{
444-
"const": "Coverage",
445-
"description": "The date or date range during which the resource is available."
446-
},
447-
{
448-
"const": "Created",
449-
"description": "The date the resource itself was put together; this could refer to a timeframe in ancient history, a date range, or a single date for a final component, e.g., the finalised file with all the data."
450-
},
451-
{
452-
"const": "Issued",
453-
"description": "The date that the resource is published or distributed, e.g., to a data centre"
454-
},
455-
{
456-
"const": "Submitted",
457-
"description": "The date the creator submits the resource to the publisher. This could be different from Accepted if the publisher then applies a selection process."
458-
},
459-
{
460-
"const": "Updated",
461-
"description": "The date of the last update to the resource, when the resource is being added to. May be a range."
462-
},
463-
{
464-
"const": "Valid",
465-
"description": "The date or date range during which the dataset or resource is accurate."
466-
},
467-
{
468-
"const": "Withdrawn",
469-
"description": "The date the resource is removed."
470-
},
471-
{
472-
"const": "Presented",
473-
"description": "POSTER-SPECIFIC EXTENSION: The date the resource was presented, such as at a conference. NOTE: For DataCite Metadata Schema compatibility, consider using 'Issued' instead with the dateInformation sub-property to provide context (e.g., 'Presented at [Conference Name]'). This ensures consistent dateTypes across different resource types."
474-
},
475-
{
476-
"const": "Other",
477-
"description": "Date type not defined elsewhere."
478-
}
479-
]
426+
"$ref": "#/definitions/dateType"
480427
},
481428
"dateInformation": {
482429
"type": [
@@ -716,7 +663,7 @@
716663
},
717664
"descriptions": {
718665
"type": "array",
719-
"description": "Free text descriptions of the poster content. Typically includes an abstract summarizing the research, methods used, or technical details.",
666+
"description": "Free text descriptions of the poster content. Use descriptionType 'Abstract' for user-provided formal abstracts and 'Other' for auto-generated summaries. A poster may have both.",
720667
"items": {
721668
"type": "object",
722669
"additionalProperties": false,
@@ -731,34 +678,7 @@
731678
]
732679
},
733680
"descriptionType": {
734-
"type": "string",
735-
"description": "The type of the 'description'. Must be from controlled list.",
736-
"oneOf": [
737-
{
738-
"const": "Abstract",
739-
"description": "A brief description of the resource and the context in which the resource was created"
740-
},
741-
{
742-
"const": "Methods",
743-
"description": "The methodology employed for the study or research."
744-
},
745-
{
746-
"const": "SeriesInformation",
747-
"description": "Information about the series to which the resource belongs."
748-
},
749-
{
750-
"const": "TableOfContents",
751-
"description": "A table of contents for the resource."
752-
},
753-
{
754-
"const": "TechnicalInfo",
755-
"description": "Detailed information that may be associated with design, implementation, operation, use, and/or maintenance of a process or system."
756-
},
757-
{
758-
"const": "Other",
759-
"description": "Other description information that does not fit into an existing category."
760-
}
761-
]
681+
"$ref": "#/definitions/descriptionType"
762682
}
763683
},
764684
"required": [
@@ -815,6 +735,15 @@
815735
"https://www.crossref.org/services/funder-registry/"
816736
]
817737
},
738+
"awardTitle": {
739+
"type": "string",
740+
"minLength": 1,
741+
"description": "The human readable title or name of the award (grant)",
742+
"examples": [
743+
"The awesome project of XYZ",
744+
"Socioenvironmental Monitoring of the Amazon Basin and Xingu"
745+
]
746+
},
818747
"awardNumber": {
819748
"type": "string",
820749
"minLength": 1,
@@ -833,15 +762,6 @@
833762
"https://www.moore.org/grants/list/GBMF3859.01",
834763
"https://doi.org/10.35802/221400"
835764
]
836-
},
837-
"awardTitle": {
838-
"type": "string",
839-
"minLength": 1,
840-
"description": "The human readable title or name of the award (grant)",
841-
"examples": [
842-
"The awesome project of XYZ",
843-
"Socioenvironmental Monitoring of the Amazon Basin and Xingu"
844-
]
845765
}
846766
},
847767
"required": [
@@ -1284,6 +1204,94 @@
12841204
}
12851205
]
12861206
},
1207+
"descriptionType": {
1208+
"type": "string",
1209+
"description": "The type of the description. Use 'Abstract' for user-provided formal abstracts and 'Other' for auto-generated summaries.",
1210+
"oneOf": [
1211+
{
1212+
"const": "Abstract",
1213+
"description": "A brief description of the resource and the context in which the resource was created"
1214+
},
1215+
{
1216+
"const": "Methods",
1217+
"description": "The methodology employed for the study or research."
1218+
},
1219+
{
1220+
"const": "SeriesInformation",
1221+
"description": "Information about the series to which the resource belongs."
1222+
},
1223+
{
1224+
"const": "TableOfContents",
1225+
"description": "A table of contents for the resource."
1226+
},
1227+
{
1228+
"const": "TechnicalInfo",
1229+
"description": "Detailed information that may be associated with design, implementation, operation, use, and/or maintenance of a process or system."
1230+
},
1231+
{
1232+
"const": "Other",
1233+
"description": "Other description information that does not fit into an existing category, including auto-generated poster summaries."
1234+
}
1235+
]
1236+
},
1237+
"dateType": {
1238+
"type": "string",
1239+
"description": "The type of date of the item.",
1240+
"oneOf": [
1241+
{
1242+
"const": "Accepted",
1243+
"description": "The date that the publisher accepted the resource into their system."
1244+
},
1245+
{
1246+
"const": "Available",
1247+
"description": "The date the resource is made publicly available. May be a range."
1248+
},
1249+
{
1250+
"const": "Copyrighted",
1251+
"description": "The specific, documented date at which the resource receives a copyrighted status, if applicable."
1252+
},
1253+
{
1254+
"const": "Collected",
1255+
"description": "The date or date range in which the resource content was collected."
1256+
},
1257+
{
1258+
"const": "Coverage",
1259+
"description": "The date or date range during which the resource is available."
1260+
},
1261+
{
1262+
"const": "Created",
1263+
"description": "The date the resource itself was put together; this could refer to a timeframe in ancient history, a date range, or a single date for a final component, e.g., the finalised file with all the data."
1264+
},
1265+
{
1266+
"const": "Issued",
1267+
"description": "The date that the resource is published or distributed, e.g., to a data centre"
1268+
},
1269+
{
1270+
"const": "Submitted",
1271+
"description": "The date the creator submits the resource to the publisher. This could be different from Accepted if the publisher then applies a selection process."
1272+
},
1273+
{
1274+
"const": "Updated",
1275+
"description": "The date of the last update to the resource, when the resource is being added to. May be a range."
1276+
},
1277+
{
1278+
"const": "Valid",
1279+
"description": "The date or date range during which the dataset or resource is accurate."
1280+
},
1281+
{
1282+
"const": "Withdrawn",
1283+
"description": "The date the resource is removed."
1284+
},
1285+
{
1286+
"const": "Presented",
1287+
"description": "POSTER-SPECIFIC EXTENSION: The date the resource was presented, such as at a conference. NOTE: For DataCite Metadata Schema compatibility, consider using 'Issued' instead with the dateInformation sub-property to provide context (e.g., 'Presented at [Conference Name]'). This ensures consistent dateTypes across different resource types."
1288+
},
1289+
{
1290+
"const": "Other",
1291+
"description": "Date type not defined elsewhere."
1292+
}
1293+
]
1294+
},
12871295
"identifierType": {
12881296
"type": "string",
12891297
"oneOf": [

validation.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
"""
22
Poster extraction validation
33
4-
Validates LLM output against the extraction schema.
4+
Validates LLM output against the poster schema (v0.2).
55
Reports warnings for any schema violations.
66
7+
Raw extraction is validated against the full poster_schema.json. The
8+
platform-owned fields (conference, publicationYear) are filled in downstream
9+
on the website, so they surface here as non-blocking warnings rather than
10+
errors; validation never rejects an extraction.
11+
712
NOTE: Format normalization (caption structure, creator fields, affiliations)
813
is handled by the poster2json library (poster2json.extract) before this
914
module runs. This module only validates and reports - it does not modify the
@@ -22,11 +27,13 @@
2227

2328
# Schema file path
2429
SCHEMA_DIR = Path(__file__).parent
25-
EXTRACTION_SCHEMA_PATH = SCHEMA_DIR / "poster_extraction_schema.json"
30+
# Validate against the full poster schema (v0.2). The v0.1 extraction schema
31+
# is retained only as version history and is no longer used at runtime.
2632
FULL_SCHEMA_PATH = SCHEMA_DIR / "poster_schema.json"
33+
EXTRACTION_SCHEMA_PATH = SCHEMA_DIR / "poster_extraction_schema.json" # kept for history
2734

2835
# Schema version for tracking
29-
SCHEMA_VERSION = "extraction-v0.1"
36+
SCHEMA_VERSION = "poster-schema-v0.2"
3037

3138
# Cache the schema in memory after first load
3239
_SCHEMA_CACHE: Optional[dict] = None
@@ -45,11 +52,11 @@ def to_dict(self) -> Dict[str, Any]:
4552
return asdict(self)
4653

4754

48-
def load_extraction_schema() -> dict:
49-
"""Load the extraction schema, using cached version if available."""
55+
def load_schema() -> dict:
56+
"""Load the full poster schema (v0.2), using the cached copy if available."""
5057
global _SCHEMA_CACHE
5158
if _SCHEMA_CACHE is None:
52-
with open(EXTRACTION_SCHEMA_PATH) as f:
59+
with open(FULL_SCHEMA_PATH) as f:
5360
_SCHEMA_CACHE = json.load(f)
5461
return _SCHEMA_CACHE
5562

@@ -150,7 +157,7 @@ def validate_and_fix_extraction(
150157
return result, []
151158

152159
# Schema validation
153-
schema = load_extraction_schema()
160+
schema = load_schema()
154161
validator = Draft202012Validator(schema)
155162

156163
# Collect all schema errors as warnings

0 commit comments

Comments
 (0)