Add game data capture vertical slice
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# Game Data Capture Contracts
|
||||
|
||||
RG-1 freezes contract version 1 for the taxonomy, workflow states, evidence model, archive manifest, and ISAC handoff boundary.
|
||||
|
||||
## Files
|
||||
|
||||
- `domain-contract-v1.json` lists every family/view pair, record type, Gear slot, abstention reason, state, and allowed transition.
|
||||
- `screenshot-classification.schema.json` validates one hierarchical screen classification.
|
||||
- `evidence-archive-manifest-v1.schema.json` validates a private evidence archive manifest.
|
||||
- `isac-handoff-v1.schema.json` validates a bounded draft handoff for authenticated ISAC intake.
|
||||
- `examples/classification/` contains one valid and one invalid classification for each family, including explicit `unknown` abstention.
|
||||
- `examples/archive/` and `examples/handoff/` exercise each versioned document schema.
|
||||
|
||||
The schemas use JSON Schema Draft 2020-12, internal `$ref` values, standard formats, and no implementation-specific keywords. Python `jsonschema` and TypeScript validators such as Ajv can compile the files without model conversion. Consumers must reject a document unless `schema_version` equals the schema's `const` value. Consumers must also run semantic reference validation because JSON Schema cannot prove that an ID points to an item in another array.
|
||||
|
||||
## Evidence Rules
|
||||
|
||||
Capture workers store source text, a normalized value, confidence, engine identity, an image digest, a bounded region, and append-only correction history for each evidence value. A null normalized value requires a `missing_reason`. A present normalized value requires a null `missing_reason`. Each correction's `before` state must match the preceding `after` state. Timestamps must increase, and the final `after` state must match the current evidence value.
|
||||
|
||||
Workers record the configured item shown on screen under `observed_instances`, including its visible level, quality, tier, upgrade state, and values. Workers place proposed reusable definitions under `canonical_candidates` and handoff `records`. A worker must not copy an observed roll, relationship, mechanic, range endpoint, or option list into a canonical candidate unless evidence establishes that canonical claim.
|
||||
|
||||
## Trust Boundary
|
||||
|
||||
Archive and handoff documents contain content hashes and logical artifact IDs. They exclude host paths and credentials. The handoff declares `mutation_authority: "none"`. Importing or inspecting it grants no permission and performs no mutation. An authenticated ISAC action must revalidate each draft and preserve contributor moderation and audit behavior.
|
||||
|
||||
Archive images and handoff images allow at most 64 MiB. Private archive videos allow at most 16 GiB, matching the configured capture ceiling. Schema validation enforces media-specific byte limits. Semantic validation enforces unique entity and correction IDs, local references, evidence artifact hashes, correction chains, and normalized image bounds.
|
||||
|
||||
The contracts assign explicit states or reasons to cancellation, resource exhaustion, ambiguous classification, unsupported content, and extraction failure. Recovery requires a listed transition. Unknown transitions and future schema versions fail closed.
|
||||
@@ -0,0 +1,143 @@
|
||||
{
|
||||
"contract_version": 1,
|
||||
"families": {
|
||||
"weapon": {
|
||||
"gear_slot": false,
|
||||
"views": {
|
||||
"detail": ["weapon", "weapon_talent"],
|
||||
"blueprint": ["weapon", "weapon_talent"],
|
||||
"crafting": ["weapon"],
|
||||
"stat_range": ["weapon"],
|
||||
"talent_grid": ["weapon_talent"],
|
||||
"augmentation": ["weapon_augmentation_profile"]
|
||||
}
|
||||
},
|
||||
"gear": {
|
||||
"gear_slot": true,
|
||||
"views": {
|
||||
"detail": ["gear", "brand_set"],
|
||||
"blueprint": ["gear", "brand_set"],
|
||||
"talent": ["gear_talent"],
|
||||
"augmentation": ["gear_augmentation_profile"]
|
||||
}
|
||||
},
|
||||
"skill_chip": {
|
||||
"gear_slot": false,
|
||||
"views": {
|
||||
"detail": ["skill_chip_set", "skill_chip_roll_pool"],
|
||||
"set_bonus": ["skill_chip_set_bonus"],
|
||||
"talent": ["skill_chip_talent"]
|
||||
}
|
||||
},
|
||||
"os_protocol": {
|
||||
"gear_slot": false,
|
||||
"views": {
|
||||
"detail": ["os_protocol"],
|
||||
"secondary_profile": ["os_protocol_secondary_profile"],
|
||||
"talent": ["os_protocol_talent"]
|
||||
}
|
||||
},
|
||||
"specialization": {
|
||||
"gear_slot": false,
|
||||
"views": {
|
||||
"overview": ["specialization"],
|
||||
"details": ["specialization"],
|
||||
"ability": ["specialization_ability"],
|
||||
"focus_details": ["specialization_focus"],
|
||||
"focus_tree": ["specialization_focus", "specialization_tree_node"],
|
||||
"rank_details": ["specialization_tree_rank"]
|
||||
}
|
||||
},
|
||||
"unknown": {
|
||||
"gear_slot": false,
|
||||
"views": {"unknown": []}
|
||||
}
|
||||
},
|
||||
"gear_slots": ["Mask", "Gloves", "Backpack", "Body Armor", "Holster", "Knee Pads"],
|
||||
"abstention_reasons": [
|
||||
"low_confidence",
|
||||
"ambiguous_family",
|
||||
"ambiguous_view",
|
||||
"unsupported_family",
|
||||
"unsupported_view",
|
||||
"insufficient_visual_evidence",
|
||||
"occluded",
|
||||
"corrupt_image",
|
||||
"resource_limit",
|
||||
"cancelled"
|
||||
],
|
||||
"missing_reasons": [
|
||||
"not_visible",
|
||||
"occluded",
|
||||
"unreadable",
|
||||
"not_present_on_screen",
|
||||
"unsupported",
|
||||
"ambiguous",
|
||||
"extraction_failed",
|
||||
"not_applicable",
|
||||
"redacted"
|
||||
],
|
||||
"states": {
|
||||
"capture": {
|
||||
"received": ["spooling", "deduplicated", "failed", "cancelled"],
|
||||
"spooling": ["stored", "failed", "cancelled"],
|
||||
"stored": ["queued", "failed"],
|
||||
"deduplicated": [],
|
||||
"queued": [],
|
||||
"failed": ["spooling", "cancelled"],
|
||||
"cancelled": []
|
||||
},
|
||||
"job": {
|
||||
"queued": ["running", "cancelled"],
|
||||
"running": ["succeeded", "retry_wait", "failed", "cancelled"],
|
||||
"retry_wait": ["queued", "failed", "cancelled"],
|
||||
"succeeded": [],
|
||||
"failed": ["queued"],
|
||||
"cancelled": []
|
||||
},
|
||||
"extraction": {
|
||||
"pending": ["local_processing", "cancelled"],
|
||||
"local_processing": ["candidate_ready", "fallback_pending", "abstained", "failed", "cancelled"],
|
||||
"fallback_pending": ["fallback_processing", "cancelled"],
|
||||
"fallback_processing": ["candidate_ready", "abstained", "failed", "cancelled"],
|
||||
"candidate_ready": [],
|
||||
"abstained": [],
|
||||
"failed": ["pending"],
|
||||
"cancelled": []
|
||||
},
|
||||
"grouping": {
|
||||
"ungrouped": ["proposed", "cancelled"],
|
||||
"proposed": ["grouped", "rejected", "cancelled"],
|
||||
"grouped": ["split", "superseded"],
|
||||
"split": ["superseded"],
|
||||
"superseded": [],
|
||||
"rejected": ["ungrouped"],
|
||||
"cancelled": []
|
||||
},
|
||||
"review": {
|
||||
"pending": ["in_review", "cancelled"],
|
||||
"in_review": ["changes_requested", "approved", "rejected", "cancelled"],
|
||||
"changes_requested": ["in_review", "rejected", "cancelled"],
|
||||
"approved": ["in_review"],
|
||||
"rejected": ["in_review"],
|
||||
"cancelled": []
|
||||
},
|
||||
"export": {
|
||||
"not_requested": ["queued"],
|
||||
"queued": ["building", "cancelled"],
|
||||
"building": ["ready", "failed", "cancelled"],
|
||||
"ready": ["expired"],
|
||||
"failed": ["queued", "cancelled"],
|
||||
"cancelled": [],
|
||||
"expired": ["queued"]
|
||||
},
|
||||
"error": {
|
||||
"open": ["retryable", "terminal", "dismissed"],
|
||||
"retryable": ["retrying", "terminal", "dismissed"],
|
||||
"retrying": ["recovered", "retryable", "terminal"],
|
||||
"recovered": [],
|
||||
"terminal": ["dismissed"],
|
||||
"dismissed": []
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://shd.build/schemas/game-data-capture/evidence-archive-manifest-v1.json",
|
||||
"title": "Game data capture evidence archive manifest v1",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version", "archive_id", "created_at", "generator", "artifacts", "captures",
|
||||
"screens", "jobs", "extractions", "groups", "reviews", "exports", "errors",
|
||||
"evidence_values", "observed_instances", "canonical_candidates"
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": {"const": 1},
|
||||
"archive_id": {"$ref": "#/$defs/id"},
|
||||
"created_at": {"$ref": "#/$defs/timestamp"},
|
||||
"generator": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["name", "version", "policy_version"],
|
||||
"properties": {
|
||||
"name": {"type": "string", "minLength": 1, "maxLength": 100},
|
||||
"version": {"type": "string", "minLength": 1, "maxLength": 50},
|
||||
"policy_version": {"type": "string", "minLength": 1, "maxLength": 50}
|
||||
}
|
||||
},
|
||||
"artifacts": {"type": "array", "maxItems": 10000, "items": {"$ref": "#/$defs/artifact"}},
|
||||
"captures": {"type": "array", "maxItems": 10000, "items": {"$ref": "#/$defs/capture"}},
|
||||
"screens": {"type": "array", "maxItems": 10000, "items": {"$ref": "#/$defs/screen"}},
|
||||
"jobs": {"type": "array", "maxItems": 20000, "items": {"$ref": "#/$defs/job"}},
|
||||
"extractions": {"type": "array", "maxItems": 20000, "items": {"$ref": "#/$defs/extraction"}},
|
||||
"groups": {"type": "array", "maxItems": 10000, "items": {"$ref": "#/$defs/group"}},
|
||||
"reviews": {"type": "array", "maxItems": 10000, "items": {"$ref": "#/$defs/review"}},
|
||||
"exports": {"type": "array", "maxItems": 1000, "items": {"$ref": "#/$defs/export"}},
|
||||
"errors": {"type": "array", "maxItems": 20000, "items": {"$ref": "#/$defs/error"}},
|
||||
"evidence_values": {"type": "array", "maxItems": 100000, "items": {"$ref": "#/$defs/evidenceValue"}},
|
||||
"observed_instances": {"type": "array", "maxItems": 20000, "items": {"$ref": "#/$defs/observedInstance"}},
|
||||
"canonical_candidates": {"type": "array", "maxItems": 20000, "items": {"$ref": "#/$defs/canonicalCandidate"}}
|
||||
},
|
||||
"$defs": {
|
||||
"id": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"},
|
||||
"sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
|
||||
"timestamp": {"type": "string", "format": "date-time", "maxLength": 40},
|
||||
"family": {"enum": ["weapon", "gear", "skill_chip", "os_protocol", "specialization", "unknown"]},
|
||||
"recordType": {"enum": [
|
||||
"weapon", "weapon_talent", "weapon_augmentation_profile", "gear", "brand_set",
|
||||
"gear_talent", "gear_augmentation_profile", "skill_chip_set", "skill_chip_set_bonus",
|
||||
"skill_chip_roll_pool", "skill_chip_talent", "os_protocol", "os_protocol_secondary_profile",
|
||||
"os_protocol_talent", "specialization", "specialization_focus", "specialization_ability",
|
||||
"specialization_tree_node", "specialization_tree_rank"
|
||||
]},
|
||||
"missingReason": {"enum": [
|
||||
"not_visible", "occluded", "unreadable", "not_present_on_screen", "unsupported",
|
||||
"ambiguous", "extraction_failed", "not_applicable", "redacted"
|
||||
]},
|
||||
"jsonValue": {
|
||||
"oneOf": [
|
||||
{"type": "null"}, {"type": "boolean"}, {"type": "number"},
|
||||
{"type": "string", "maxLength": 8192},
|
||||
{"type": "array", "maxItems": 500, "items": {"$ref": "#/$defs/jsonValue"}},
|
||||
{"type": "object", "maxProperties": 500, "additionalProperties": {"$ref": "#/$defs/jsonValue"}}
|
||||
]
|
||||
},
|
||||
"sourceEngine": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["kind", "engine_id", "engine_version"],
|
||||
"properties": {
|
||||
"kind": {"enum": ["local_ocr", "openai_vision", "classifier", "manual", "video_decoder"]},
|
||||
"engine_id": {"type": "string", "minLength": 1, "maxLength": 100},
|
||||
"engine_version": {"type": "string", "minLength": 1, "maxLength": 100}
|
||||
}
|
||||
},
|
||||
"region": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["coordinate_space", "x", "y", "width", "height"],
|
||||
"properties": {
|
||||
"coordinate_space": {"const": "normalized"},
|
||||
"x": {"type": "number", "minimum": 0, "maximum": 1},
|
||||
"y": {"type": "number", "minimum": 0, "maximum": 1},
|
||||
"width": {"type": "number", "exclusiveMinimum": 0, "maximum": 1},
|
||||
"height": {"type": "number", "exclusiveMinimum": 0, "maximum": 1}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["coordinate_space", "x", "y", "width", "height"],
|
||||
"properties": {
|
||||
"coordinate_space": {"const": "pixels"},
|
||||
"x": {"type": "integer", "minimum": 0, "maximum": 100000},
|
||||
"y": {"type": "integer", "minimum": 0, "maximum": 100000},
|
||||
"width": {"type": "integer", "minimum": 1, "maximum": 100000},
|
||||
"height": {"type": "integer", "minimum": 1, "maximum": 100000}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"valueState": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["raw_text", "normalized_value", "missing_reason"],
|
||||
"properties": {
|
||||
"raw_text": {"type": ["string", "null"], "maxLength": 8192},
|
||||
"normalized_value": {"$ref": "#/$defs/jsonValue"},
|
||||
"missing_reason": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/missingReason"}]}
|
||||
},
|
||||
"oneOf": [
|
||||
{"properties": {"normalized_value": {"type": "null"}, "missing_reason": {"$ref": "#/$defs/missingReason"}}},
|
||||
{"properties": {"normalized_value": {"not": {"type": "null"}}, "missing_reason": {"type": "null"}}}
|
||||
]
|
||||
},
|
||||
"correction": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["correction_id", "corrected_at", "actor", "reason", "before", "after"],
|
||||
"properties": {
|
||||
"correction_id": {"$ref": "#/$defs/id"},
|
||||
"corrected_at": {"$ref": "#/$defs/timestamp"},
|
||||
"actor": {"enum": ["local_user", "system_reprocess"]},
|
||||
"reason": {"type": "string", "minLength": 1, "maxLength": 1000},
|
||||
"before": {"$ref": "#/$defs/valueState"},
|
||||
"after": {"$ref": "#/$defs/valueState"}
|
||||
}
|
||||
},
|
||||
"evidenceValue": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": [
|
||||
"evidence_id", "field_path", "raw_text", "normalized_value", "missing_reason",
|
||||
"confidence", "source_engine", "image_artifact_id", "image_sha256", "region", "correction_history"
|
||||
],
|
||||
"properties": {
|
||||
"evidence_id": {"$ref": "#/$defs/id"},
|
||||
"field_path": {"type": "string", "pattern": "^[A-Za-z0-9_.-]{1,256}$"},
|
||||
"raw_text": {"type": ["string", "null"], "maxLength": 8192},
|
||||
"normalized_value": {"$ref": "#/$defs/jsonValue"},
|
||||
"missing_reason": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/missingReason"}]},
|
||||
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
|
||||
"source_engine": {"$ref": "#/$defs/sourceEngine"},
|
||||
"image_artifact_id": {"$ref": "#/$defs/id"},
|
||||
"image_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"region": {"$ref": "#/$defs/region"},
|
||||
"correction_history": {"type": "array", "maxItems": 100, "items": {"$ref": "#/$defs/correction"}}
|
||||
},
|
||||
"oneOf": [
|
||||
{"properties": {"normalized_value": {"type": "null"}, "missing_reason": {"$ref": "#/$defs/missingReason"}}},
|
||||
{"properties": {"normalized_value": {"not": {"type": "null"}}, "missing_reason": {"type": "null"}}}
|
||||
]
|
||||
},
|
||||
"fieldClaim": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["path", "value", "missing_reason", "evidence_refs", "uncertainty_note"],
|
||||
"properties": {
|
||||
"path": {"type": "string", "pattern": "^[A-Za-z0-9_.-]{1,256}$"},
|
||||
"value": {"$ref": "#/$defs/jsonValue"},
|
||||
"missing_reason": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/missingReason"}]},
|
||||
"evidence_refs": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"uncertainty_note": {"type": ["string", "null"], "maxLength": 2000}
|
||||
},
|
||||
"oneOf": [
|
||||
{"properties": {"value": {"type": "null"}, "missing_reason": {"$ref": "#/$defs/missingReason"}}},
|
||||
{"properties": {"value": {"not": {"type": "null"}}, "missing_reason": {"type": "null"}}}
|
||||
]
|
||||
},
|
||||
"classification": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["family", "view", "gear_slot", "record_types", "confidence", "abstention_reason"],
|
||||
"properties": {
|
||||
"family": {"$ref": "#/$defs/family"}, "view": {"type": "string"},
|
||||
"gear_slot": {"type": ["string", "null"]},
|
||||
"record_types": {"type": "array", "uniqueItems": true, "maxItems": 8, "items": {"$ref": "#/$defs/recordType"}},
|
||||
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
|
||||
"abstention_reason": {"type": ["string", "null"]}
|
||||
},
|
||||
"oneOf": [
|
||||
{"properties": {"family": {"const": "weapon"}, "view": {"enum": ["detail", "blueprint", "crafting", "stat_range", "talent_grid", "augmentation"]}, "gear_slot": {"const": null}, "record_types": {"minItems": 1, "items": {"enum": ["weapon", "weapon_talent", "weapon_augmentation_profile"]}}, "abstention_reason": {"const": null}}},
|
||||
{"properties": {"family": {"const": "gear"}, "view": {"enum": ["detail", "blueprint", "talent", "augmentation"]}, "gear_slot": {"enum": ["Mask", "Gloves", "Backpack", "Body Armor", "Holster", "Knee Pads"]}, "record_types": {"minItems": 1, "items": {"enum": ["gear", "brand_set", "gear_talent", "gear_augmentation_profile"]}}, "abstention_reason": {"const": null}}},
|
||||
{"properties": {"family": {"const": "skill_chip"}, "view": {"enum": ["detail", "set_bonus", "talent"]}, "gear_slot": {"const": null}, "record_types": {"minItems": 1, "items": {"enum": ["skill_chip_set", "skill_chip_set_bonus", "skill_chip_roll_pool", "skill_chip_talent"]}}, "abstention_reason": {"const": null}}},
|
||||
{"properties": {"family": {"const": "os_protocol"}, "view": {"enum": ["detail", "secondary_profile", "talent"]}, "gear_slot": {"const": null}, "record_types": {"minItems": 1, "items": {"enum": ["os_protocol", "os_protocol_secondary_profile", "os_protocol_talent"]}}, "abstention_reason": {"const": null}}},
|
||||
{"properties": {"family": {"const": "specialization"}, "view": {"enum": ["overview", "details", "ability", "focus_details", "focus_tree", "rank_details"]}, "gear_slot": {"const": null}, "record_types": {"minItems": 1, "items": {"enum": ["specialization", "specialization_focus", "specialization_ability", "specialization_tree_node", "specialization_tree_rank"]}}, "abstention_reason": {"const": null}}},
|
||||
{"properties": {"family": {"const": "unknown"}, "view": {"const": "unknown"}, "gear_slot": {"const": null}, "record_types": {"maxItems": 0}, "abstention_reason": {"enum": ["low_confidence", "ambiguous_family", "ambiguous_view", "unsupported_family", "unsupported_view", "insufficient_visual_evidence", "occluded", "corrupt_image", "resource_limit", "cancelled"]}}}
|
||||
]
|
||||
},
|
||||
"artifact": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["artifact_id", "sha256", "media_type", "byte_size", "sensitivity", "parent_artifact_id", "video_timestamp_ms"],
|
||||
"properties": {
|
||||
"artifact_id": {"$ref": "#/$defs/id"}, "sha256": {"$ref": "#/$defs/sha256"},
|
||||
"media_type": {"enum": ["image/png", "image/webp", "image/avif", "video/mp4", "video/webm", "video/x-matroska"]},
|
||||
"byte_size": {"type": "integer", "minimum": 1},
|
||||
"sensitivity": {"const": "private"},
|
||||
"parent_artifact_id": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/id"}]},
|
||||
"video_timestamp_ms": {"type": ["integer", "null"], "minimum": 0, "maximum": 86400000}
|
||||
},
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"media_type": {"enum": ["image/png", "image/webp", "image/avif"]},
|
||||
"byte_size": {"maximum": 67108864}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"media_type": {"enum": ["video/mp4", "video/webm", "video/x-matroska"]},
|
||||
"byte_size": {"maximum": 17179869184}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"capture": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["capture_id", "artifact_id", "state", "received_at", "failure_reason"],
|
||||
"properties": {
|
||||
"capture_id": {"$ref": "#/$defs/id"}, "artifact_id": {"$ref": "#/$defs/id"},
|
||||
"state": {"enum": ["received", "spooling", "stored", "deduplicated", "queued", "failed", "cancelled"]},
|
||||
"received_at": {"$ref": "#/$defs/timestamp"},
|
||||
"failure_reason": {"type": ["string", "null"], "maxLength": 2000}
|
||||
}
|
||||
},
|
||||
"screen": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["screen_id", "artifact_id", "classified_at", "classification"],
|
||||
"properties": {
|
||||
"screen_id": {"$ref": "#/$defs/id"}, "artifact_id": {"$ref": "#/$defs/id"},
|
||||
"classified_at": {"$ref": "#/$defs/timestamp"}, "classification": {"$ref": "#/$defs/classification"}
|
||||
}
|
||||
},
|
||||
"job": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["job_id", "kind", "state", "attempt", "max_attempts", "last_error_id"],
|
||||
"properties": {
|
||||
"job_id": {"$ref": "#/$defs/id"},
|
||||
"kind": {"enum": ["classify", "ocr", "vision_fallback", "frame_extract", "export"]},
|
||||
"state": {"enum": ["queued", "running", "retry_wait", "succeeded", "failed", "cancelled"]},
|
||||
"attempt": {"type": "integer", "minimum": 0, "maximum": 20},
|
||||
"max_attempts": {"type": "integer", "minimum": 1, "maximum": 20},
|
||||
"last_error_id": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/id"}]}
|
||||
}
|
||||
},
|
||||
"extraction": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["extraction_id", "screen_id", "state", "evidence_refs", "abstention_reason"],
|
||||
"properties": {
|
||||
"extraction_id": {"$ref": "#/$defs/id"}, "screen_id": {"$ref": "#/$defs/id"},
|
||||
"state": {"enum": ["pending", "local_processing", "fallback_pending", "fallback_processing", "candidate_ready", "abstained", "failed", "cancelled"]},
|
||||
"evidence_refs": {"type": "array", "maxItems": 1000, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"abstention_reason": {"type": ["string", "null"], "maxLength": 100}
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["group_id", "state", "screen_ids", "supersedes_group_ids"],
|
||||
"properties": {
|
||||
"group_id": {"$ref": "#/$defs/id"},
|
||||
"state": {"enum": ["ungrouped", "proposed", "grouped", "split", "superseded", "rejected", "cancelled"]},
|
||||
"screen_ids": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"supersedes_group_ids": {"type": "array", "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}}
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["review_id", "candidate_id", "state", "updated_at", "note"],
|
||||
"properties": {
|
||||
"review_id": {"$ref": "#/$defs/id"}, "candidate_id": {"$ref": "#/$defs/id"},
|
||||
"state": {"enum": ["pending", "in_review", "changes_requested", "approved", "rejected", "cancelled"]},
|
||||
"updated_at": {"$ref": "#/$defs/timestamp"}, "note": {"type": ["string", "null"], "maxLength": 4000}
|
||||
}
|
||||
},
|
||||
"export": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["export_id", "state", "artifact_id", "failure_reason"],
|
||||
"properties": {
|
||||
"export_id": {"$ref": "#/$defs/id"},
|
||||
"state": {"enum": ["not_requested", "queued", "building", "ready", "failed", "cancelled", "expired"]},
|
||||
"artifact_id": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/id"}]},
|
||||
"failure_reason": {"type": ["string", "null"], "maxLength": 2000}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["error_id", "state", "code", "message", "retry_after"],
|
||||
"properties": {
|
||||
"error_id": {"$ref": "#/$defs/id"},
|
||||
"state": {"enum": ["open", "retryable", "retrying", "recovered", "terminal", "dismissed"]},
|
||||
"code": {"enum": ["cancelled", "resource_limit", "timeout", "invalid_input", "engine_failure", "storage_failure", "network_failure", "schema_rejected", "unsupported", "ambiguous"]},
|
||||
"message": {"type": "string", "minLength": 1, "maxLength": 2000},
|
||||
"retry_after": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/timestamp"}]}
|
||||
}
|
||||
},
|
||||
"observedContext": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["level", "quality", "tier", "upgrade_state"],
|
||||
"properties": {
|
||||
"level": {"$ref": "#/$defs/fieldClaim"}, "quality": {"$ref": "#/$defs/fieldClaim"},
|
||||
"tier": {"$ref": "#/$defs/fieldClaim"}, "upgrade_state": {"$ref": "#/$defs/fieldClaim"}
|
||||
}
|
||||
},
|
||||
"observedInstance": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["instance_id", "family", "source_screen_ids", "observed_context", "fields"],
|
||||
"properties": {
|
||||
"instance_id": {"$ref": "#/$defs/id"}, "family": {"$ref": "#/$defs/family"},
|
||||
"source_screen_ids": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"observed_context": {"$ref": "#/$defs/observedContext"},
|
||||
"fields": {"type": "array", "maxItems": 1000, "items": {"$ref": "#/$defs/fieldClaim"}}
|
||||
}
|
||||
},
|
||||
"canonicalCandidate": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["candidate_id", "record_type", "source_instance_ids", "evidence_refs", "fields", "completeness", "relationship_status", "mechanic_status"],
|
||||
"properties": {
|
||||
"candidate_id": {"$ref": "#/$defs/id"}, "record_type": {"$ref": "#/$defs/recordType"},
|
||||
"source_instance_ids": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"evidence_refs": {"type": "array", "minItems": 1, "maxItems": 1000, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"fields": {"type": "array", "maxItems": 1000, "items": {"$ref": "#/$defs/fieldClaim"}},
|
||||
"completeness": {"enum": ["complete", "incomplete", "unsupported"]},
|
||||
"relationship_status": {"enum": ["evidenced", "unresolved", "unsupported", "not_applicable"]},
|
||||
"mechanic_status": {"enum": ["evidenced", "unresolved", "unsupported", "not_applicable"]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"schema_version": 2,
|
||||
"archive_id": "future-archive"
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"archive_id": "archive-001",
|
||||
"created_at": "2026-07-31T12:00:00Z",
|
||||
"generator": {"name": "game-data-capture", "version": "0.1.0", "policy_version": "1"},
|
||||
"artifacts": [
|
||||
{
|
||||
"artifact_id": "image-001",
|
||||
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"media_type": "image/png",
|
||||
"byte_size": 2048,
|
||||
"sensitivity": "private",
|
||||
"parent_artifact_id": null,
|
||||
"video_timestamp_ms": null
|
||||
}
|
||||
],
|
||||
"captures": [
|
||||
{"capture_id": "capture-001", "artifact_id": "image-001", "state": "queued", "received_at": "2026-07-31T11:59:55Z", "failure_reason": null}
|
||||
],
|
||||
"screens": [
|
||||
{
|
||||
"screen_id": "screen-001",
|
||||
"artifact_id": "image-001",
|
||||
"classified_at": "2026-07-31T11:59:57Z",
|
||||
"classification": {
|
||||
"family": "weapon",
|
||||
"view": "detail",
|
||||
"gear_slot": null,
|
||||
"record_types": ["weapon", "weapon_talent"],
|
||||
"confidence": 0.97,
|
||||
"abstention_reason": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"jobs": [],
|
||||
"extractions": [],
|
||||
"groups": [],
|
||||
"reviews": [
|
||||
{"review_id": "review-001", "candidate_id": "candidate-001", "state": "approved", "updated_at": "2026-07-31T12:00:00Z", "note": "Name verified against the image."}
|
||||
],
|
||||
"exports": [],
|
||||
"errors": [],
|
||||
"evidence_values": [
|
||||
{
|
||||
"evidence_id": "evidence-name",
|
||||
"field_path": "weapon.name",
|
||||
"raw_text": "LVOA-C",
|
||||
"normalized_value": "LVOA-C",
|
||||
"missing_reason": null,
|
||||
"confidence": 0.99,
|
||||
"source_engine": {"kind": "local_ocr", "engine_id": "fixture-ocr", "engine_version": "1"},
|
||||
"image_artifact_id": "image-001",
|
||||
"image_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"region": {"coordinate_space": "normalized", "x": 0.1, "y": 0.1, "width": 0.3, "height": 0.08},
|
||||
"correction_history": []
|
||||
},
|
||||
{
|
||||
"evidence_id": "evidence-level",
|
||||
"field_path": "observed.level",
|
||||
"raw_text": "20",
|
||||
"normalized_value": 20,
|
||||
"missing_reason": null,
|
||||
"confidence": 0.98,
|
||||
"source_engine": {"kind": "local_ocr", "engine_id": "fixture-ocr", "engine_version": "1"},
|
||||
"image_artifact_id": "image-001",
|
||||
"image_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"region": {"coordinate_space": "pixels", "x": 50, "y": 50, "width": 80, "height": 30},
|
||||
"correction_history": []
|
||||
},
|
||||
{
|
||||
"evidence_id": "evidence-quality",
|
||||
"field_path": "observed.quality",
|
||||
"raw_text": "High-end",
|
||||
"normalized_value": "High-end",
|
||||
"missing_reason": null,
|
||||
"confidence": 0.96,
|
||||
"source_engine": {"kind": "local_ocr", "engine_id": "fixture-ocr", "engine_version": "1"},
|
||||
"image_artifact_id": "image-001",
|
||||
"image_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"region": {"coordinate_space": "pixels", "x": 50, "y": 85, "width": 140, "height": 30},
|
||||
"correction_history": []
|
||||
},
|
||||
{
|
||||
"evidence_id": "evidence-tier",
|
||||
"field_path": "observed.tier",
|
||||
"raw_text": "T1",
|
||||
"normalized_value": 1,
|
||||
"missing_reason": null,
|
||||
"confidence": 0.97,
|
||||
"source_engine": {"kind": "local_ocr", "engine_id": "fixture-ocr", "engine_version": "1"},
|
||||
"image_artifact_id": "image-001",
|
||||
"image_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"region": {"coordinate_space": "pixels", "x": 200, "y": 85, "width": 60, "height": 30},
|
||||
"correction_history": []
|
||||
},
|
||||
{
|
||||
"evidence_id": "evidence-upgrade",
|
||||
"field_path": "observed.upgrade_state",
|
||||
"raw_text": null,
|
||||
"normalized_value": null,
|
||||
"missing_reason": "not_visible",
|
||||
"confidence": 0,
|
||||
"source_engine": {"kind": "manual", "engine_id": "review", "engine_version": "1"},
|
||||
"image_artifact_id": "image-001",
|
||||
"image_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"region": {"coordinate_space": "normalized", "x": 0, "y": 0, "width": 1, "height": 1},
|
||||
"correction_history": []
|
||||
},
|
||||
{
|
||||
"evidence_id": "evidence-damage",
|
||||
"field_path": "observed.damage",
|
||||
"raw_text": "12,400",
|
||||
"normalized_value": 12400,
|
||||
"missing_reason": null,
|
||||
"confidence": 1,
|
||||
"source_engine": {"kind": "manual", "engine_id": "review", "engine_version": "1"},
|
||||
"image_artifact_id": "image-001",
|
||||
"image_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"region": {"coordinate_space": "pixels", "x": 300, "y": 200, "width": 160, "height": 40},
|
||||
"correction_history": [
|
||||
{
|
||||
"correction_id": "correction-001",
|
||||
"corrected_at": "2026-07-31T12:00:00Z",
|
||||
"actor": "local_user",
|
||||
"reason": "Corrected a missing zero.",
|
||||
"before": {"raw_text": "1,240", "normalized_value": 1240, "missing_reason": null},
|
||||
"after": {"raw_text": "12,400", "normalized_value": 12400, "missing_reason": null}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"observed_instances": [
|
||||
{
|
||||
"instance_id": "instance-001",
|
||||
"family": "weapon",
|
||||
"source_screen_ids": ["screen-001"],
|
||||
"observed_context": {
|
||||
"level": {"path": "observed.level", "value": 20, "missing_reason": null, "evidence_refs": ["evidence-level"], "uncertainty_note": null},
|
||||
"quality": {"path": "observed.quality", "value": "High-end", "missing_reason": null, "evidence_refs": ["evidence-quality"], "uncertainty_note": null},
|
||||
"tier": {"path": "observed.tier", "value": 1, "missing_reason": null, "evidence_refs": ["evidence-tier"], "uncertainty_note": null},
|
||||
"upgrade_state": {"path": "observed.upgrade_state", "value": null, "missing_reason": "not_visible", "evidence_refs": ["evidence-upgrade"], "uncertainty_note": "The screen does not show an upgrade indicator."}
|
||||
},
|
||||
"fields": [
|
||||
{"path": "observed.damage", "value": 12400, "missing_reason": null, "evidence_refs": ["evidence-damage"], "uncertainty_note": "This is the configured level-20 instance value, not a canonical range endpoint."}
|
||||
]
|
||||
}
|
||||
],
|
||||
"canonical_candidates": [
|
||||
{
|
||||
"candidate_id": "candidate-001",
|
||||
"record_type": "weapon",
|
||||
"source_instance_ids": ["instance-001"],
|
||||
"evidence_refs": ["evidence-name"],
|
||||
"fields": [
|
||||
{"path": "weapon.name", "value": "LVOA-C", "missing_reason": null, "evidence_refs": ["evidence-name"], "uncertainty_note": null}
|
||||
],
|
||||
"completeness": "incomplete",
|
||||
"relationship_status": "unresolved",
|
||||
"mechanic_status": "not_applicable"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "gear",
|
||||
"view": "detail",
|
||||
"gear_slot": "Vest",
|
||||
"record_types": ["gear"],
|
||||
"confidence": 0.95,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "gear",
|
||||
"view": "talent",
|
||||
"gear_slot": "Body Armor",
|
||||
"record_types": ["gear_talent"],
|
||||
"confidence": 0.95,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "os_protocol",
|
||||
"view": "secondary_profile",
|
||||
"gear_slot": null,
|
||||
"record_types": ["os_protocol_secondary_profile"],
|
||||
"confidence": 1.3,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "os_protocol",
|
||||
"view": "secondary_profile",
|
||||
"gear_slot": null,
|
||||
"record_types": ["os_protocol_secondary_profile"],
|
||||
"confidence": 0.93,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "skill_chip",
|
||||
"view": "detail",
|
||||
"gear_slot": null,
|
||||
"record_types": ["weapon"],
|
||||
"confidence": 0.94,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "skill_chip",
|
||||
"view": "set_bonus",
|
||||
"gear_slot": null,
|
||||
"record_types": ["skill_chip_set_bonus"],
|
||||
"confidence": 0.94,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "specialization",
|
||||
"view": "focus_tree",
|
||||
"gear_slot": null,
|
||||
"record_types": ["specialization_tree_node"],
|
||||
"confidence": 0.91,
|
||||
"abstention_reason": "ambiguous_view"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "specialization",
|
||||
"view": "focus_tree",
|
||||
"gear_slot": null,
|
||||
"record_types": ["specialization_focus", "specialization_tree_node"],
|
||||
"confidence": 0.91,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "unknown",
|
||||
"view": "unknown",
|
||||
"gear_slot": null,
|
||||
"record_types": ["weapon"],
|
||||
"confidence": 0.22,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "unknown",
|
||||
"view": "unknown",
|
||||
"gear_slot": null,
|
||||
"record_types": [],
|
||||
"confidence": 0.22,
|
||||
"abstention_reason": "low_confidence"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "weapon",
|
||||
"view": "talent",
|
||||
"gear_slot": null,
|
||||
"record_types": ["weapon"],
|
||||
"confidence": 0.9,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"family": "weapon",
|
||||
"view": "detail",
|
||||
"gear_slot": null,
|
||||
"record_types": ["weapon", "weapon_talent"],
|
||||
"confidence": 0.97,
|
||||
"abstention_reason": null
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"schema_version": 2,
|
||||
"handoff_id": "future-handoff"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"handoff_id": "handoff-001",
|
||||
"created_at": "2026-07-31T12:05:00Z",
|
||||
"source_archive": {
|
||||
"archive_id": "archive-001",
|
||||
"manifest_sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||
"schema_version": 1
|
||||
},
|
||||
"trust_boundary": {
|
||||
"intended_destination": "authenticated_isac_intake",
|
||||
"mutation_authority": "none",
|
||||
"requires_authenticated_action": true,
|
||||
"preserves_moderation": true,
|
||||
"creates_audit_events": false
|
||||
},
|
||||
"source_artifacts": [
|
||||
{
|
||||
"artifact_id": "image-001",
|
||||
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"media_type": "image/png",
|
||||
"byte_size": 2048
|
||||
}
|
||||
],
|
||||
"evidence_values": [
|
||||
{
|
||||
"evidence_id": "evidence-name",
|
||||
"field_path": "weapon.name",
|
||||
"raw_text": "LVOA-C",
|
||||
"normalized_value": "LVOA-C",
|
||||
"missing_reason": null,
|
||||
"confidence": 0.99,
|
||||
"source_engine": {"kind": "local_ocr", "engine_id": "fixture-ocr", "engine_version": "1"},
|
||||
"image_artifact_id": "image-001",
|
||||
"image_sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"region": {"coordinate_space": "normalized", "x": 0.1, "y": 0.1, "width": 0.3, "height": 0.08},
|
||||
"correction_history": []
|
||||
}
|
||||
],
|
||||
"records": [
|
||||
{
|
||||
"handoff_record_id": "handoff-record-001",
|
||||
"record_type": "weapon",
|
||||
"intent": "create_draft",
|
||||
"target_id": null,
|
||||
"review_state": "approved",
|
||||
"source_candidate_ids": ["candidate-001"],
|
||||
"observed_instance_ids": ["instance-001"],
|
||||
"fields": [
|
||||
{"path": "weapon.name", "value": "LVOA-C", "missing_reason": null, "evidence_refs": ["evidence-name"], "uncertainty_note": null}
|
||||
],
|
||||
"relationships": {"status": "unresolved", "evidence_refs": [], "note": "ISAC must resolve and validate canonical relationships before submission."},
|
||||
"mechanics": {"status": "not_applicable", "evidence_refs": [], "note": null}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://shd.build/schemas/game-data-capture/isac-handoff-v1.json",
|
||||
"title": "Authenticated ISAC draft handoff v1",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version", "handoff_id", "created_at", "source_archive", "trust_boundary",
|
||||
"source_artifacts", "evidence_values", "records"
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": {"const": 1},
|
||||
"handoff_id": {"$ref": "#/$defs/id"},
|
||||
"created_at": {"$ref": "#/$defs/timestamp"},
|
||||
"source_archive": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["archive_id", "manifest_sha256", "schema_version"],
|
||||
"properties": {
|
||||
"archive_id": {"$ref": "#/$defs/id"}, "manifest_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"schema_version": {"const": 1}
|
||||
}
|
||||
},
|
||||
"trust_boundary": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["intended_destination", "mutation_authority", "requires_authenticated_action", "preserves_moderation", "creates_audit_events"],
|
||||
"properties": {
|
||||
"intended_destination": {"const": "authenticated_isac_intake"},
|
||||
"mutation_authority": {"const": "none"},
|
||||
"requires_authenticated_action": {"const": true},
|
||||
"preserves_moderation": {"const": true},
|
||||
"creates_audit_events": {"const": false}
|
||||
}
|
||||
},
|
||||
"source_artifacts": {"type": "array", "maxItems": 10000, "items": {"$ref": "#/$defs/sourceArtifact"}},
|
||||
"evidence_values": {"type": "array", "maxItems": 100000, "items": {"$ref": "#/$defs/evidenceValue"}},
|
||||
"records": {"type": "array", "maxItems": 20000, "items": {"$ref": "#/$defs/handoffRecord"}}
|
||||
},
|
||||
"$defs": {
|
||||
"id": {"type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"},
|
||||
"sha256": {"type": "string", "pattern": "^[a-f0-9]{64}$"},
|
||||
"timestamp": {"type": "string", "format": "date-time", "maxLength": 40},
|
||||
"recordType": {"enum": [
|
||||
"weapon", "weapon_talent", "weapon_augmentation_profile", "gear", "brand_set",
|
||||
"gear_talent", "gear_augmentation_profile", "skill_chip_set", "skill_chip_set_bonus",
|
||||
"skill_chip_roll_pool", "skill_chip_talent", "os_protocol", "os_protocol_secondary_profile",
|
||||
"os_protocol_talent", "specialization", "specialization_focus", "specialization_ability",
|
||||
"specialization_tree_node", "specialization_tree_rank"
|
||||
]},
|
||||
"missingReason": {"enum": [
|
||||
"not_visible", "occluded", "unreadable", "not_present_on_screen", "unsupported",
|
||||
"ambiguous", "extraction_failed", "not_applicable", "redacted"
|
||||
]},
|
||||
"jsonValue": {
|
||||
"oneOf": [
|
||||
{"type": "null"}, {"type": "boolean"}, {"type": "number"},
|
||||
{"type": "string", "maxLength": 8192},
|
||||
{"type": "array", "maxItems": 500, "items": {"$ref": "#/$defs/jsonValue"}},
|
||||
{"type": "object", "maxProperties": 500, "additionalProperties": {"$ref": "#/$defs/jsonValue"}}
|
||||
]
|
||||
},
|
||||
"sourceEngine": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["kind", "engine_id", "engine_version"],
|
||||
"properties": {
|
||||
"kind": {"enum": ["local_ocr", "openai_vision", "classifier", "manual", "video_decoder"]},
|
||||
"engine_id": {"type": "string", "minLength": 1, "maxLength": 100},
|
||||
"engine_version": {"type": "string", "minLength": 1, "maxLength": 100}
|
||||
}
|
||||
},
|
||||
"region": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["coordinate_space", "x", "y", "width", "height"],
|
||||
"properties": {
|
||||
"coordinate_space": {"const": "normalized"},
|
||||
"x": {"type": "number", "minimum": 0, "maximum": 1},
|
||||
"y": {"type": "number", "minimum": 0, "maximum": 1},
|
||||
"width": {"type": "number", "exclusiveMinimum": 0, "maximum": 1},
|
||||
"height": {"type": "number", "exclusiveMinimum": 0, "maximum": 1}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["coordinate_space", "x", "y", "width", "height"],
|
||||
"properties": {
|
||||
"coordinate_space": {"const": "pixels"},
|
||||
"x": {"type": "integer", "minimum": 0, "maximum": 100000},
|
||||
"y": {"type": "integer", "minimum": 0, "maximum": 100000},
|
||||
"width": {"type": "integer", "minimum": 1, "maximum": 100000},
|
||||
"height": {"type": "integer", "minimum": 1, "maximum": 100000}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"valueState": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["raw_text", "normalized_value", "missing_reason"],
|
||||
"properties": {
|
||||
"raw_text": {"type": ["string", "null"], "maxLength": 8192},
|
||||
"normalized_value": {"$ref": "#/$defs/jsonValue"},
|
||||
"missing_reason": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/missingReason"}]}
|
||||
},
|
||||
"oneOf": [
|
||||
{"properties": {"normalized_value": {"type": "null"}, "missing_reason": {"$ref": "#/$defs/missingReason"}}},
|
||||
{"properties": {"normalized_value": {"not": {"type": "null"}}, "missing_reason": {"type": "null"}}}
|
||||
]
|
||||
},
|
||||
"correction": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["correction_id", "corrected_at", "actor", "reason", "before", "after"],
|
||||
"properties": {
|
||||
"correction_id": {"$ref": "#/$defs/id"}, "corrected_at": {"$ref": "#/$defs/timestamp"},
|
||||
"actor": {"enum": ["local_user", "system_reprocess"]},
|
||||
"reason": {"type": "string", "minLength": 1, "maxLength": 1000},
|
||||
"before": {"$ref": "#/$defs/valueState"}, "after": {"$ref": "#/$defs/valueState"}
|
||||
}
|
||||
},
|
||||
"evidenceValue": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["evidence_id", "field_path", "raw_text", "normalized_value", "missing_reason", "confidence", "source_engine", "image_artifact_id", "image_sha256", "region", "correction_history"],
|
||||
"properties": {
|
||||
"evidence_id": {"$ref": "#/$defs/id"},
|
||||
"field_path": {"type": "string", "pattern": "^[A-Za-z0-9_.-]{1,256}$"},
|
||||
"raw_text": {"type": ["string", "null"], "maxLength": 8192},
|
||||
"normalized_value": {"$ref": "#/$defs/jsonValue"},
|
||||
"missing_reason": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/missingReason"}]},
|
||||
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
|
||||
"source_engine": {"$ref": "#/$defs/sourceEngine"},
|
||||
"image_artifact_id": {"$ref": "#/$defs/id"}, "image_sha256": {"$ref": "#/$defs/sha256"},
|
||||
"region": {"$ref": "#/$defs/region"},
|
||||
"correction_history": {"type": "array", "maxItems": 100, "items": {"$ref": "#/$defs/correction"}}
|
||||
},
|
||||
"oneOf": [
|
||||
{"properties": {"normalized_value": {"type": "null"}, "missing_reason": {"$ref": "#/$defs/missingReason"}}},
|
||||
{"properties": {"normalized_value": {"not": {"type": "null"}}, "missing_reason": {"type": "null"}}}
|
||||
]
|
||||
},
|
||||
"fieldClaim": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["path", "value", "missing_reason", "evidence_refs", "uncertainty_note"],
|
||||
"properties": {
|
||||
"path": {"type": "string", "pattern": "^[A-Za-z0-9_.-]{1,256}$"},
|
||||
"value": {"$ref": "#/$defs/jsonValue"},
|
||||
"missing_reason": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/missingReason"}]},
|
||||
"evidence_refs": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"uncertainty_note": {"type": ["string", "null"], "maxLength": 2000}
|
||||
},
|
||||
"oneOf": [
|
||||
{"properties": {"value": {"type": "null"}, "missing_reason": {"$ref": "#/$defs/missingReason"}}},
|
||||
{"properties": {"value": {"not": {"type": "null"}}, "missing_reason": {"type": "null"}}}
|
||||
]
|
||||
},
|
||||
"sourceArtifact": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["artifact_id", "sha256", "media_type", "byte_size"],
|
||||
"properties": {
|
||||
"artifact_id": {"$ref": "#/$defs/id"}, "sha256": {"$ref": "#/$defs/sha256"},
|
||||
"media_type": {"enum": ["image/png", "image/webp", "image/avif"]},
|
||||
"byte_size": {"type": "integer", "minimum": 1, "maximum": 67108864}
|
||||
}
|
||||
},
|
||||
"evidenceSection": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["status", "evidence_refs", "note"],
|
||||
"properties": {
|
||||
"status": {"enum": ["evidenced", "unresolved", "unsupported", "not_applicable"]},
|
||||
"evidence_refs": {"type": "array", "maxItems": 1000, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"note": {"type": ["string", "null"], "maxLength": 4000}
|
||||
}
|
||||
},
|
||||
"handoffRecord": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": [
|
||||
"handoff_record_id", "record_type", "intent", "target_id", "review_state",
|
||||
"source_candidate_ids", "observed_instance_ids", "fields", "relationships", "mechanics"
|
||||
],
|
||||
"properties": {
|
||||
"handoff_record_id": {"$ref": "#/$defs/id"}, "record_type": {"$ref": "#/$defs/recordType"},
|
||||
"intent": {"enum": ["create_draft", "update_draft", "abstain"]},
|
||||
"target_id": {"oneOf": [{"type": "null"}, {"$ref": "#/$defs/id"}]},
|
||||
"review_state": {"enum": ["approved", "abstained"]},
|
||||
"source_candidate_ids": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"observed_instance_ids": {"type": "array", "minItems": 1, "maxItems": 100, "uniqueItems": true, "items": {"$ref": "#/$defs/id"}},
|
||||
"fields": {"type": "array", "maxItems": 1000, "items": {"$ref": "#/$defs/fieldClaim"}},
|
||||
"relationships": {"$ref": "#/$defs/evidenceSection"},
|
||||
"mechanics": {"$ref": "#/$defs/evidenceSection"}
|
||||
},
|
||||
"oneOf": [
|
||||
{"properties": {"intent": {"const": "create_draft"}, "target_id": {"const": null}, "review_state": {"const": "approved"}}},
|
||||
{"properties": {"intent": {"const": "update_draft"}, "target_id": {"$ref": "#/$defs/id"}, "review_state": {"const": "approved"}}},
|
||||
{"properties": {"intent": {"const": "abstain"}, "target_id": {"const": null}, "review_state": {"const": "abstained"}, "fields": {"maxItems": 0}}}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://shd.build/schemas/game-data-capture/screenshot-classification-v1.json",
|
||||
"title": "Screenshot classification v1",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["family", "view", "gear_slot", "record_types", "confidence", "abstention_reason"],
|
||||
"properties": {
|
||||
"family": {"enum": ["weapon", "gear", "skill_chip", "os_protocol", "specialization", "unknown"]},
|
||||
"view": {"type": "string"},
|
||||
"gear_slot": {"type": ["string", "null"]},
|
||||
"record_types": {"type": "array", "uniqueItems": true, "maxItems": 8, "items": {"type": "string"}},
|
||||
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
|
||||
"abstention_reason": {"type": ["string", "null"]}
|
||||
},
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"family": {"const": "weapon"},
|
||||
"view": {"enum": ["detail", "blueprint", "crafting", "stat_range", "talent_grid", "augmentation"]},
|
||||
"gear_slot": {"const": null},
|
||||
"record_types": {"minItems": 1, "items": {"enum": ["weapon", "weapon_talent", "weapon_augmentation_profile"]}},
|
||||
"abstention_reason": {"const": null}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"family": {"const": "gear"},
|
||||
"view": {"enum": ["detail", "blueprint", "talent", "augmentation"]},
|
||||
"gear_slot": {"enum": ["Mask", "Gloves", "Backpack", "Body Armor", "Holster", "Knee Pads"]},
|
||||
"record_types": {"minItems": 1, "items": {"enum": ["gear", "brand_set", "gear_talent", "gear_augmentation_profile"]}},
|
||||
"abstention_reason": {"const": null}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"family": {"const": "skill_chip"},
|
||||
"view": {"enum": ["detail", "set_bonus", "talent"]},
|
||||
"gear_slot": {"const": null},
|
||||
"record_types": {"minItems": 1, "items": {"enum": ["skill_chip_set", "skill_chip_set_bonus", "skill_chip_roll_pool", "skill_chip_talent"]}},
|
||||
"abstention_reason": {"const": null}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"family": {"const": "os_protocol"},
|
||||
"view": {"enum": ["detail", "secondary_profile", "talent"]},
|
||||
"gear_slot": {"const": null},
|
||||
"record_types": {"minItems": 1, "items": {"enum": ["os_protocol", "os_protocol_secondary_profile", "os_protocol_talent"]}},
|
||||
"abstention_reason": {"const": null}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"family": {"const": "specialization"},
|
||||
"view": {"enum": ["overview", "details", "ability", "focus_details", "focus_tree", "rank_details"]},
|
||||
"gear_slot": {"const": null},
|
||||
"record_types": {"minItems": 1, "items": {"enum": ["specialization", "specialization_focus", "specialization_ability", "specialization_tree_node", "specialization_tree_rank"]}},
|
||||
"abstention_reason": {"const": null}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"family": {"const": "unknown"},
|
||||
"view": {"const": "unknown"},
|
||||
"gear_slot": {"const": null},
|
||||
"record_types": {"maxItems": 0},
|
||||
"abstention_reason": {"enum": ["low_confidence", "ambiguous_family", "ambiguous_view", "unsupported_family", "unsupported_view", "insufficient_visual_evidence", "occluded", "corrupt_image", "resource_limit", "cancelled"]}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user