Data dictionary for the CHIRPdb database prepared for the Alan Turing Institute Data Study Group. See the dataset overview for context, provenance and limitations. Content conventions follow DAMA-DMBOK.
What the database contains
This dictionary documents the full CHIRPdb schema, but the database as delivered populates only two of its layers. Expect data in:
- Reports & text -
documents,authors,sentences, and the report-derived incident facts indocument_particularsanddocument_vessels. Two corpora sit here, separated bydocuments.jurisdiction: 796 UK MAIB reports ('UK') and 456 US NTSB reports ('US'), 1,252 documents in total. - Incident metadata from the MAIB spreadsheets -
occurrences,vessels,affected_persons,affected_persons_ppe, the report↔occurrence link carried ondocuments.occurrence_id, plus the vocabularies feeding them (taxonomy_terms,ppe_items). MAIB-only: NTSB publishes no equivalent dataset, so these tables describe UK incidents alone and no NTSB document carries anoccurrence_id. - Seeded reference vocabularies -
shield_codes/shield_code_categories(the full SHIELD taxonomy) andnarrative_entity_types. Loaded as controlled vocabulary; nothing references them yet.
The analysis, findings and entity layers are empty - no chunking, SHIELD tagging, safety-issue/recommendation extraction or entity resolution has been run:
chunks,chunk_sentences,analysis- empty (no chunking pass).chunk_shield_codes- empty: the SHIELD taxonomy is loaded but no code is applied to any passage.safety_issues,safety_issue_legislation,recommendations,recommendation_organisations- empty (no findings extraction).narrative_entities,narrative_entity_mentions- empty (no NER/coreference pass).organisations,legislation, and the identifier tables (author_identifiers,organisation_identifiers) - empty (nothing populates them at this stage).
How to read this document
Every column is classified in the Source column as one of:
| Label | Meaning |
|---|---|
| Source | Source-document field - value taken from the source report, MAIB or NTSB (PDF content or file metadata) |
| MAIB | MAIB Data Portal field - value taken from the MAIB spreadsheet extract. Used only on the spreadsheet-fed tables, which hold UK incidents alone |
| Pipeline | Pipeline-derived (deterministic) - computed by the ingestion pipeline with no model involvement |
| AI-U | AI-generated (unverified) - produced by an LLM or NLP model, not confirmed by a human |
| AI-V | AI-generated (human-verified) - AI-produced and confirmed by an analyst |
| System | System metadata - surrogate keys, timestamps, status flags, generated search columns, seeded reference data |
A slashed label (Pipeline / AI-U) marks a column whose extractor is deterministic with a model fallback.
Four conventions apply throughout:
- Row-level verification. Tables carrying an
is_verifiedflag (chunk_shield_codes,safety_issues,recommendations) hold AI-generated content whose verification status varies per row. Their content columns are marked AI-U (or Pipeline / AI-U where a deterministic extractor populates them today); treat rows whereis_verified = trueas AI-V. Sentences are the analogous case at document level:documents.status = 'verified'marks a document whose extracted text an analyst has confirmed. - Sentence text. Text is extracted by a vision LLM reading a rendered image of each page, with deterministic passes (structural-metadata normalisation, line rejoin, content-loss repair) applied on top of the model output. Sentence text and structure columns are therefore marked AI-U, qualified by the parent document's
status. - Two record sets, linked - not merged. Incident data comes from two sources kept in separate tables rather than reconciled into one row:
- the MAIB Data Portal spreadsheet →
occurrencesand its childrenvessels/affected_persons, plus the vocabulariestaxonomy_terms/ppe_items. Spreadsheet-only facts, UK-only;source_id/source_modified_atcarry MAIB's per-record identifier and revision date, driving upsert on each refresh so only MAIB-revised rows are touched. Columns on these tables carry the MAIB label. - the report PDF, MAIB or NTSB →
document_particulars(incident facts stated in the report) anddocument_vessels(vessels named in the report), each hanging offdocuments. Columns fed this way carry the Source label, which says nothing about which body published the report - readdocuments.jurisdictionfor that.
A MAIB report links to its occurrence through documents.occurrence_id, with documents.occurrence_matched_on recording how the link was made (publication_number or manual); several reports can point at the same occurrence (e.g. an interim report followed by the final one). NTSB documents have no occurrence to link to, so only the report-PDF set applies to them.
- Jurisdiction split.
documents.jurisdictionis the column that separates the corpora -'UK'for MAIB,'US'for NTSB - and everything owned by a document (sentences,document_particulars,document_vessels, and the analysis layer once populated) inherits that split through itsdocument_id. Field coverage differs between the two: see the per-column notes ondocuments,document_particularsanddocument_vessels, and the fill-rate figures in the README.
All tables carry created_at and updated_at (timestamptz, defaulting to now(), with updated_at maintained by a BEFORE UPDATE trigger). These are listed once per table without repeating the explanation. Exceptions, noted on their entries: the vocabulary and junction tables taxonomy_terms, ppe_items, affected_persons_ppe carry no audit timestamps.
1. Reports and incident record
documents
One row per ingested report PDF - MAIB or NTSB. The root of the ownership chain: deleting a document cascades to everything extracted from it. 1,252 rows: 796 with jurisdiction = 'UK' (MAIB), 456 with 'US' (NTSB).
Keys: PK id. UNIQUE hash. FK author_id → authors(id) ON DELETE SET NULL. FK occurrence_id → occurrences(id) ON DELETE SET NULL. CHECK documents_lease_requires_start (claim_expires_at set implies claim_started_at set); CHECK documents_occurrence_link_has_provenance (occurrence_id set implies occurrence_matched_on set); CHECK occurrence_matched_on is null or in ('publication_number', 'manual'); CHECK documents_jurisdiction_check (jurisdiction is null or in ('UK', 'US')).
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| author_id | uuid | yes | Investigating body that published the report (MAIB or NTSB) | FK to authors; survives author deletion (SET NULL) | Pipeline |
| title | text | no | Report title | - | Source |
| url | text | yes | URL the report was retrieved from | - | Pipeline |
| filename | text | yes | Filename of the source PDF | - | Pipeline |
| hash | text | no | Hash of the source file; dedupes re-ingestion | unique | Pipeline |
| publication_number | text | yes | Publisher's report reference: MAIB Publication_No for UK rows, NTSB report number for US rows. For MAIB it is also the key a report is matched to a spreadsheet occurrence on | NTSB values are prefixed MAB- (265), MIR- (167) or MAR- (21); null on 3 NTSB rows | Source |
| document_type | text | yes | GOV.UK publication class (Publication_Type), e.g. investigation-report, safety-bulletin | MAIB rows only - null for every NTSB document | Source |
| occurrence_id | uuid | yes | The spreadsheet occurrence this report describes; resolved from publication_number. Several reports (e.g. interim + final) may point at one occurrence | FK to occurrences, SET NULL; MAIB rows only (58 populated), always null for NTSB | Pipeline |
| occurrence_matched_on | text | yes | How the occurrence link was made | publication_number (auto) or manual; required when occurrence_id is set | Pipeline |
| publication_date | date | yes | Date the report was published | - | Source |
| status | document_status | no | Extraction-pipeline state | enum: queued, extracting, extracted, verified, extraction_failed; default queued | System |
| extraction_fallback | boolean | no | True if extraction fell back to a degraded result after retries were exhausted | default false | System |
| jurisdiction | text | yes | Reporting jurisdiction; the column that separates the two corpora | default 'UK'; 'UK' = MAIB (796), 'US' = NTSB (456) | Pipeline |
| page_count | integer | yes | Page count of the source PDF | - | Pipeline |
| pdf_subject | text | yes | Subject field from PDF file metadata | - | Source |
| pdf_author | text | yes | Author field from PDF file metadata | - | Source |
| claim_token | uuid | yes | Lease token held by the worker currently extracting this document; guards against double-processing | - | System |
| claim_started_at | timestamptz | yes | When the current extraction lease was taken | - | System |
| claim_expires_at | timestamptz | yes | When the lease expires and the document may be re-queued | requires claim_started_at (check-constrained) | System |
| title_tsv | tsvector | - | Full-text search index over title | generated column (always derived) | System |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
Document status lifecycle: queued → extracting → extracted → verified, with extracting → extraction_failed on an irrecoverable crash. extracted means the automated pipeline finished; verified means an analyst confirmed the results. The claim_* columns are the extraction lease used to recover documents stranded by a crashed worker. As delivered, all 1,252 documents are at extracted, and 201 carry extraction_fallback = true (182 MAIB, 19 NTSB).
document_particulars
Incident facts as stated in the report PDF - the report-path counterpart to the spreadsheet's occurrences. One row per document (1:1), so 1,252 rows across both corpora. Columns are populated only where the report states the fact, and NTSB reports state fewer of them: of 456 NTSB rows, accident_date is set on 198, accident_location 208, accident_type 130, severity 71, loss_of_life 33 (MAIB, of 796: 796 / 731 / 279 / 305 / 183).
Keys: PK document_id. FK document_id → documents(id) ON DELETE CASCADE. CHECK loss_of_life is null or ≥ 0.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| document_id | uuid | no | The report these particulars are drawn from | PK, FK, cascade delete | Pipeline |
| accident_date | date | yes | Date of the incident as stated in the report | - | Source |
| accident_location | text | yes | Named place of the incident | free text from report | Source |
| severity | text | yes | Severity as stated in the report | free text from report | Source |
| accident_type | text | yes | Type of accident | free text; ⚠ unreliable - often holds the voyage or vessel-operation type instead (see note) | Source |
| loss_of_life | integer | yes | Number of deaths | null or ≥ 0 (check-constrained) | Source |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
accident_type does not reliably hold the accident type. The extraction pass frequently picks up the report's statement of the voyage or vessel-operation type (what the vessel was doing) rather than what happened to it, so the column mixes the two. Do not treat it as an accident classification without reading the values first; for MAIB documents, the spreadsheet's occurrences.main_event_term_id (the main_event taxonomy) is the classification to use instead.
document_vessels
Vessels named in the report PDF - the report-path counterpart to the spreadsheet's vessels. A document names zero or more vessels (1,252 rows as delivered, one per document). Coverage differs by corpus: vessel_name is set on 400 of 456 NTSB rows and 299 of 796 MAIB rows, vessel_type on 395 / 796, while port_of_origin and destination are populated for MAIB only (286 and 262) and empty for every NTSB row.
Keys: PK id. FK document_id → documents(id) ON DELETE CASCADE.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| document_id | uuid | no | Owning report | FK, cascade delete | Pipeline |
| vessel_name | text | yes | Vessel name as stated in the report | - | Source |
| vessel_type | text | yes | Vessel type as stated in the report | free text from report | Source |
| port_of_origin | text | yes | Port of origin | - | Source |
| destination | text | yes | Destination | - | Source |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
authors
Investigating bodies that publish reports (MAIB, NTSB). Shared reference data, not owned by any document. 22 rows as delivered, and they are not yet canonicalised: the same body appears under several name variants taken from PDF metadata (e.g. MAIB, Marine Accident Investigation Branch, www.maib.gov.uk; NTSB, National Transportation Safety Board, and the typo NSTB), alongside rows that are individual people named as the PDF's author. Group by the body yourself - or filter on documents.jurisdiction - rather than trusting authors.name as a key.
Keys: PK id.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| name | text | no | Name of the publishing body | - | Source |
| text | yes | Contact email for the publishing body | scraped, then manually curated/checked (final version); not populated here | Pipeline | |
| phone_number | text | yes | Contact phone | scraped, then manually curated/checked (final version); not populated here | Pipeline |
| address | text | yes | Postal address | scraped, then manually curated/checked (final version); not populated here | Pipeline |
| website_url | text | yes | Website | scraped, then manually curated/checked (final version); not populated here | Pipeline |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
author_identifiers
Curated identifiers that canonicalise an author, one row per identifier - so name variants (e.g. "MAIB" vs "Maritime Accident Investigation Branch") resolve to a single author rather than many near-duplicates.
Keys: PK id. FK author_id → authors(id) ON DELETE CASCADE.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| author_id | uuid | no | Owning author | FK, cascade delete | Pipeline |
| identifier | text | no | Curated identifier used to resolve name variants to one canonical author (e.g. "MAIB" and "Maritime Accident Investigation Branch" → the same body) | curated | System |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
occurrences
One incident as recorded in the MAIB Data Portal spreadsheet - what happened, when, where, how severe. Purely spreadsheet-sourced; it holds no report-PDF fields, and it is UK-only: NTSB has no counterpart feed, so this table and its children describe MAIB incidents alone. The report(s) describing an occurrence point to it via documents.occurrence_id, and the report's own view of the incident lives in document_particulars.
Keys: PK id. UNIQUE source_id. FK main_event_term_id → taxonomy_terms(id) ON DELETE SET NULL.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| source_id | text | no | MAIB's stable per-incident identifier (Occurrence_Id); upsert key for spreadsheet refresh | not null, unique | MAIB |
| source_modified_at | date | yes | MAIB's per-record revision date (Occurrence_Record_Modified_On); drives selective refresh | - | MAIB |
| publication_number | text | yes | MAIB report reference (Publication_No); the value a report's documents.publication_number is matched against to set documents.occurrence_id | - | MAIB |
| accident_date | date | yes | Date of the incident (Local_Date_Main_Event, month precision) | - | MAIB |
| date_unconfirmed | boolean | yes | Whether MAIB's date is unconfirmed (Date_Main_Event_Unconfirmed) | - | MAIB |
| severity | text | yes | Incident severity (Occurrence_Severity) | clean 4-value vocab | MAIB |
| main_event_term_id | uuid | yes | Principal event, as a taxonomy term (Main_Event_L1/L2) | FK to taxonomy_terms (main_event) | MAIB |
| short_description | text | yes | Brief description of the incident | - | MAIB |
| description | text | yes | Fuller description of the incident | - | MAIB |
| latitude | text | yes | Latitude, captured verbatim (deliberately text, not a geo type) | not validated as coordinates | MAIB |
| longitude | text | yes | Longitude, captured verbatim (see above) | not validated as coordinates | MAIB |
| year_reported | integer | yes | Year the incident was reported | - | MAIB |
| location_zone | text | yes | Sea-area zone (Occurrence_Location) | Coastal (≤12nm), Open sea, Inland | MAIB |
| accident_port | text | yes | Nearest port to the incident (Port_Of_Accident_L2) | - | MAIB |
| state_reporting | text | yes | Reporting jurisdiction (State_Reporting) | UK / Non-UK | MAIB |
| natural_light | text | yes | Natural light at the incident (Natural_Light) | - | MAIB |
| sea_state | text | yes | Sea state (Sea_State) | - | MAIB |
| visibility | text | yes | Visibility (Visibility) | - | MAIB |
| weather | text | yes | Weather (Weather) | - | MAIB |
| wind_force | text | yes | Wind force (Wind_Force) | - | MAIB |
| sar_intervention | text | yes | Whether search-and-rescue was involved (SAR_Intervention) | - | MAIB |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
main_event_term_id references the shared taxonomy_terms tree (see §4). Report-PDF incident facts (accident type, named location, loss of life) are not held here - they live in document_particulars, reached via documents.occurrence_id. A report is linked to its occurrence by documents.occurrence_id (the FK sits on documents, so several reports can share one occurrence).
vessels
Vessels involved in a spreadsheet occurrence - the particulars from the MAIB Data Portal, and so UK-only. An occurrence involves one or more vessels. Vessels as named in the report PDF are separate: see document_vessels.
Keys: PK id. UNIQUE source_id. FK occurrence_id → occurrences(id) ON DELETE CASCADE. FKs vessel_category_term_id, ship_type_term_id, place_on_board_term_id → taxonomy_terms(id) ON DELETE SET NULL.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| occurrence_id | uuid | yes | Owning occurrence | FK, cascade delete | Pipeline |
| source_id | text | no | MAIB's per-vessel identifier (Vessel_Profile_Id); upsert key | not null, unique | MAIB |
| source_modified_at | date | yes | MAIB's per-record revision date (Vessel_Record_Modified_On) | - | MAIB |
| flag_state | text | yes | Flag state (Flag_State) | - | MAIB |
| vessel_category_term_id | uuid | yes | Size band as a taxonomy term (Vessel_Category_L1/L2) | FK to taxonomy_terms (vessel_category) | MAIB |
| ship_type_term_id | uuid | yes | What the vessel is, as a taxonomy term (Ship_Craft_Type_L1-L4) | FK to taxonomy_terms (ship_type) | MAIB |
| is_commercial_vessel | boolean | yes | Commercial vs leisure (Is_Commercial_Vessel) | - | MAIB |
| hull_material | text | yes | Hull material (Hull_Material) | - | MAIB |
| gross_tonnage | numeric | yes | Gross tonnage (GT_Gross_Tonnage) | - | MAIB |
| length_metres | numeric | yes | Overall length in metres (LOA_Length_Overall_in_Metres, fallback Registered_Length_In_Metres) | - | MAIB |
| year_built | integer | yes | Year built | - | MAIB |
| port_of_origin | text | yes | Departure port (Port_Of_Departure_L2) | - | MAIB |
| voyage_segment | text | yes | Phase of voyage (Voyage_Segment) | e.g. Mid-water, Arrival, Anchored | MAIB |
| pilot_on_board | text | yes | Pilotage state (Pilot_On_Board) | - | MAIB |
| crew_count | integer | yes | Crew on the voyage (Crew_Voyage) | - | MAIB |
| place_on_board_term_id | uuid | yes | Where on the vessel the event occurred, as a taxonomy term (Place_On_Board_L1-L3) | FK to taxonomy_terms (vessel_place_on_board) | MAIB |
| did_vessel_sink | boolean | yes | Whether the vessel sank (Did_The_Vessel_Sink) | - | MAIB |
| vessel_abandoned | boolean | yes | Whether the vessel was abandoned (Vessel_Abandoned) | - | MAIB |
| damage_severity | text | yes | Damage-severity grade (Loss_Of_Vessel_Damage); cased/normalised on ingest | No damage … Loss of ship | MAIB |
| damage_description | text | yes | Free-text damage detail (Damage_Description); distinct from the grade | - | MAIB |
| pollution_result | text | yes | Pollution outcome (Pollution_Result) | - | MAIB |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
Death and injury counts are not stored on vessels; count them from affected_persons by person_type and physical-condition outcome so there is one source of truth. Vessel classification lives entirely in taxonomy_terms references (vessel_category_term_id, ship_type_term_id); the report's own vessel names/types sit apart in document_vessels.
affected_persons
People affected aboard a vessel of a spreadsheet occurrence, so UK-only like its parents. A vessel carries zero or more affected persons. No names are stored - demographic and injury attributes only.
Keys: PK id. UNIQUE source_id. FK vessel_id → vessels(id) ON DELETE CASCADE. FKs physical_condition_term_id, injury_type_term_id, deviation_term_id, place_on_board_term_id → taxonomy_terms(id).
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| vessel_id | uuid | yes | Vessel the person was aboard | FK, cascade delete | Pipeline |
| source_id | text | yes | MAIB's per-person identifier (Affected_Person_Id); upsert key | unique | MAIB |
| source_modified_at | date | yes | MAIB's per-record revision date (Affected_Person_Record_Modified_On) | - | MAIB |
| sequence_no | integer | yes | Person's order within the incident (Sequence_No) | - | MAIB |
| age | integer | yes | Age | - | MAIB |
| gender | text | yes | Gender as stated | free text | MAIB |
| person_type | text | yes | Role category (Affected_Person_Type, e.g. crew, passenger) | free text | MAIB |
| rank | text | yes | Rank or position aboard | free text | MAIB |
| on_duty | boolean | yes | Whether on duty at the time | - | MAIB |
| nationality | text | yes | Nationality | free text | MAIB |
| physical_condition_term_id | uuid | yes | Outcome / severity / incapacitation as a taxonomy term (Physical_Condition_L1-L3) | FK to taxonomy_terms (physical_condition) | MAIB |
| injury_type_term_id | uuid | yes | Injury and subtype as a taxonomy term (Injury_Type_L1/L2) | FK to taxonomy_terms (injury_type) | MAIB |
| parts_of_body_injured | text | yes | Body parts injured (Parts_of_Body_Injured) | free text | MAIB |
| deviation_term_id | uuid | yes | Accident mechanism as a taxonomy term (Affected_Person_Deviation_L1/L2, e.g. slip/fall, body movement) | FK to taxonomy_terms (deviation) | MAIB |
| place_on_board_term_id | uuid | yes | Where the person was, as a taxonomy term (Affected_Person_Place_On_Board_L1-L5) | FK to taxonomy_terms (person_place_on_board) | MAIB |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
Injury type is a taxonomy_terms reference (injury_type_term_id). PPE worn and lacking is recorded per person in affected_persons_ppe (below), one row per item.
affected_persons_ppe
Junction: which PPE items a person wore or lacked. One row per person per item, split out of the spreadsheet's comma-joined PPE_Used / PPE_Deficient values so items can be counted and filtered. Carries no audit timestamps.
Keys: Composite PK (affected_person_id, ppe_item_id, status). FKs affected_person_id → affected_persons(id), ppe_item_id → ppe_items(id).
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| affected_person_id | uuid | no | The person | PK part, FK | Pipeline |
| ppe_item_id | uuid | no | The PPE item | PK part, FK | Pipeline |
| status | text | no | Whether the item was worn or missing | used (from PPE_Used) / deficient (from PPE_Deficient) | MAIB |
| deficiency_reason | text | yes | Why the item was deficient, where recorded | - | MAIB |
2. Parsed text
sentences
Every sentence of every report, in original reading order - 341,057 rows, 293,454 from MAIB documents and 47,603 from NTSB ones. The atomic unit of text; everything in the analysis layer traces back here. Sentences carry no jurisdiction of their own: join through document_id to split the corpora. Text is produced by a vision LLM reading a rendered image of each page, with deterministic passes applied on top - the stored text reflects that output, with the parent document's status indicating how much to trust it.
There is no sections table: a row with text_type = 'heading' is a section boundary, and a section's contents are the sentences whose sort_order falls between that heading and the next.
Keys: PK id. FK document_id → documents(id) ON DELETE CASCADE. CHECK heading_level BETWEEN 1 AND 6. CHECK page_number is null or ≥ 1.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| document_id | uuid | yes | Owning report | FK, cascade delete | Pipeline |
| text | text | no | Sentence text | - | AI-U (vision-LLM extracted from the page image, deterministic passes on top; see documents.status) |
| text_type | sentence_text_type | no | Kind of text | enum: heading, paragraph, list_item, footnote, caption, table, frontmatter | AI-U |
| sort_order | integer | yes | Position in original reading order (0-based) | - | Pipeline |
| relevance_score | integer | yes | AI-assigned score of a sentence's analytical relevance (e.g. ~0 for frontmatter, ~1 for a safety-issue / SHIELD-relevant sentence) | ⚠ not reliably populated in this database - do not depend on it | AI-U |
| heading_level | smallint | yes | Heading depth; set only on headings | 1–6, check-constrained | AI-U |
| page_number | integer | yes | Source PDF page the sentence was extracted from | null or ≥ 1 (check-constrained) | Pipeline |
| block_id | text | yes | Identifier of the layout block the sentence came from | - | Pipeline |
| text_tsv | tsvector | - | Full-text search index over text | generated column | System |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
chunks
A grouped passage of consecutive sentences - the unit the analysis pipeline works on. A chunk's membership still lives in chunk_sentences, so chunking strategy can change without touching sentence records, but the chunk also carries its own document_id: the transitive path chunk_sentences → sentences → documents disappears when a document is re-extracted (its sentences are rewritten and the junction rows cascade away), which used to strand chunks unreachable from any document, and a chunk needs to know its document before any sentences are attached to it.
Keys: PK id. FK document_id → documents(id) ON DELETE CASCADE. A trigger (trg_validate_chunk_document) rejects a document_id that contradicts the document derived from the chunk's sentences; it validates rather than derives, so a chunk with no sentences yet may name its document freely.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| document_id | uuid | yes | Report the passage belongs to, recorded directly rather than derived through chunk_sentences | FK, cascade delete; null where a chunk's document cannot be established (see note below) | Pipeline |
| extracted_text | text | yes | Text of the passage | - | Pipeline (derived from member sentences) |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
document_id is nullable for two reasons, both meaning "the data does not say": a chunk left over from a re-ingestion has no surviving sentences to derive a document from, and a chunk whose sentences span more than one document is not assigned one rather than being given an arbitrary guess. Deleting a document now deletes its chunks, matching sentences, safety_issues and recommendations.
chunk_sentences
Junction: which sentences belong to which chunk, and in what order.
Keys: Composite PK (chunk_id, sentence_id). FKs chunk_id → chunks(id), sentence_id → sentences(id), both ON DELETE CASCADE.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| chunk_id | uuid | no | Chunk | PK part, FK, cascade delete | Pipeline |
| sentence_id | uuid | no | Member sentence | PK part, FK, cascade delete | Pipeline |
| sort_order | integer | yes | Sentence position within the chunk | auto-assigned by trigger when null | Pipeline |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
narrative_entities
Canonical named things (people, vessels, organisations, locations, equipment) extracted from a document's text - one row per distinct thing per document, with a normalised canonical name. Coreference resolution is persisted here: many surface forms, one entity.
Keys: PK id. FK document_id → documents(id) ON DELETE CASCADE. FK type → narrative_entity_types(name) ON DELETE RESTRICT (natural-key FK). A database trigger enforces that an entity's mentions can only anchor to sentences of the entity's own document.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| document_id | uuid | no | Report the entity is scoped to | FK, cascade delete | Pipeline |
| type | text | no | Entity type | FK to narrative_entity_types(name): person, vessel, organisation, location, equipment | AI-U |
| canonical_name | text | no | Normalised name for the entity | - | AI-U |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
narrative_entity_mentions
Each occurrence of an entity in the text: the exact words used and their character position within the sentence.
Keys: PK id. FKs narrative_entity_id → narrative_entities(id), sentence_id → sentences(id), both ON DELETE CASCADE. CHECK: char_span non-empty with lower bound ≥ 0.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| narrative_entity_id | uuid | no | Entity being mentioned | FK, cascade delete | AI-U |
| sentence_id | uuid | no | Sentence containing the mention | FK, cascade delete | AI-U |
| surface_form | text | no | Exact words used (e.g. "the Master", "Captain Smith") | - | AI-U |
| char_span | int4range | no | Half-open character range into the sentence text | non-empty, lower ≥ 0 (check-constrained) | AI-U |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
3. Analysis and findings
analysis
Free-form per-chunk analysis output. Different analytical passes can sit side by side on the same passage. No verification flag exists on this table - treat all content as unverified.
Keys: PK id. FK chunk_id → chunks(id) ON DELETE CASCADE.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| chunk_id | uuid | yes | Passage analysed | FK, cascade delete | Pipeline |
| analysis_type | text | yes | Optional label an analyst supplies when uploading an analysis of a passage | free text; no controlled vocabulary | System (analyst-provided) |
| content | text | yes | The analysis output itself | - | AI-U |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
chunk_shield_codes
Application of a SHIELD causal-factor code to a chunk - the link that makes incidents comparable and countable. Verification lives on the association itself, because an analyst verifies "this code applies to this passage".
Keys: Composite PK (chunk_id, shield_code_id). FKs chunk_id → chunks(id), shield_code_id → shield_codes(id), both ON DELETE CASCADE.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| chunk_id | uuid | no | Tagged passage | PK part, FK, cascade delete | AI-U (the tagging is the AI judgement; AI-V where is_verified) |
| shield_code_id | uuid | no | Applied SHIELD code | PK part, FK, cascade delete | AI-U (as above) |
| is_verified | boolean | yes | Analyst has confirmed this code applies to this passage | default false | System (records human verification action) |
| verified_at | timestamptz | yes | When verified | trigger-stamped when is_verified flips true, cleared when false | System |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
safety_issues
A named safety concern the report raises, owned by a document and optionally traced to the chunk it was drawn from. chunk_id is provenance, not ownership: chunks are pipeline artefacts and may be regenerated, so the link is SET NULL rather than cascade - a verified finding survives re-chunking.
Keys: PK id. FK document_id → documents(id) ON DELETE CASCADE. FK chunk_id → chunks(id) ON DELETE SET NULL. CHECK safety_issues_record_type_valid (record_type in ('safety_issue', 'safety_lesson')). Partial index on record_type where record_type <> 'safety_issue' - nearly every row is a safety_issue, so lessons are the selective side worth indexing. A trigger validates (and derives, where unambiguous) document_id against the chunk's actual document, falling back to chunks.document_id when the chunk has no sentences yet.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| document_id | uuid | yes | Owning report | FK, cascade delete; trigger-validated against chunk | Pipeline |
| chunk_id | uuid | yes | Passage the issue was drawn from | FK, SET NULL on chunk deletion | Pipeline (provenance link) |
| name | text | yes | The safety issue | - | AI-U (AI-V where is_verified) |
| record_type | text | no | Whether the row is a finding about this accident or a general safety lesson to the industry | safety_issue or safety_lesson, CHECK-constrained; default safety_issue | Pipeline / AI-U (AI-V where is_verified) |
| is_contributory | boolean | yes | Did this issue contribute directly to the accident? | null means the report did not classify it (see note) | Pipeline / AI-U (AI-V where is_verified) |
| is_addressed | boolean | yes | Was the issue addressed, or did it result in recommendations? | null means the report did not classify it (see note) | Pipeline / AI-U (AI-V where is_verified) |
| is_verified | boolean | yes | Analyst has confirmed the finding | default false | System (records human verification action) |
| verified_at | timestamptz | yes | When verified | trigger-stamped | System |
| name_tsv | tsvector | - | Full-text search index over name | generated column | System |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
is_contributory and is_addressed split MAIB's four-way classification of safety issues (directly contributing, addressed or resulted in recommendations / other directly contributing / not directly contributing, addressed or resulted in recommendations / other not directly contributing) into the two independent facts it actually encodes. Both are nullable because only modern-era reports classify at all: mid-era reports print bare FINDINGS / OTHER FINDINGS, older ones list findings under a CONCLUSIONS part, and bulletins do not classify. Null means the report did not say - never "unknown, pending backfill".
record_type distinguishes the two kinds of free-text observation the table holds. A safety_lesson is general advice to the industry, printed under a SAFETY LESSONS heading in bulletins and in the safety-flyer annexes of full reports; for several bulletins it is the only safety content in the document. Lessons share this table because they have the same shape as issues - free text, no addressee, no identifier - and simply leave the two classification booleans null.
recommendations
An action the report calls for, in the report's own words. Same shape and delete semantics as safety_issues.
Keys: PK id. FK document_id → documents(id) ON DELETE CASCADE. FK chunk_id → chunks(id) ON DELETE SET NULL. Partial index on reference_number where not null. Same document_id validation trigger as safety_issues.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| document_id | uuid | yes | Owning report | FK, cascade delete; trigger-validated against chunk | Pipeline |
| chunk_id | uuid | yes | Passage the recommendation was drawn from | FK, SET NULL on chunk deletion | Pipeline (provenance link) |
| action | text | no | The recommended action | - | AI-U (AI-V where is_verified) |
| reference_number | text | yes | The publisher's own reference for the recommendation, as printed (e.g. 2026/149, S2024/137M) | indexed, deliberately not unique; null for the large share of the corpus that predates the scheme | Pipeline / AI-U (AI-V where is_verified) |
| addressee | text | yes | Who the recommendation is aimed at, as the report's lead-in line words it (e.g. "Poseidon Trawlers Limited is recommended to:") | free text; one lead-in governs several recommendations, so the same value repeats across rows | Pipeline / AI-U (AI-V where is_verified) |
| is_verified | boolean | yes | Analyst has confirmed the finding | default false | System (records human verification action) |
| verified_at | timestamptz | yes | When verified | trigger-stamped | System |
| action_tsv | tsvector | - | Full-text search index over action | generated column | System |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
reference_number is the publisher's sequential identifier across its whole annual output, so one report's recommendations run consecutively and a recommendation made in one report can be cited by name in a later one. It is not unique in this table by design: re-ingesting a document rewrites its records, and roughly 60% of the corpus predates the numbering scheme. addressee keeps the report's own wording rather than pointing at organisations, because the party addressed is often a class of people ("All UK Operators of small commercial high speed craft…") rather than a nameable company; the structured link, when made, is layered on top in recommendation_organisations and never replaces this text.
safety_issue_legislation
Junction linking a safety issue to legislation that bears on it, with the passage of text that made the connection - so the citation itself is traceable.
Keys: Composite PK (safety_issue_id, legislation_id). FKs to safety_issues(id) and legislation(id), both ON DELETE CASCADE.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| safety_issue_id | uuid | no | Safety issue | PK part, FK, cascade delete | AI-U (the link is the AI judgement) |
| legislation_id | uuid | no | Legislation cited | PK part, FK, cascade delete | AI-U |
| extracted_text | text | yes | The passage that made the connection | - | AI-U |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
recommendation_organisations
Junction linking a recommendation to the organisations it is directed at. Implementation is tracked per organisation, because each may act on the same recommendation at a different time.
Keys: Composite PK (recommendation_id, organisation_id). FKs to recommendations(id) and organisations(id), both ON DELETE CASCADE.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| recommendation_id | uuid | no | Recommendation | PK part, FK, cascade delete | AI-U (the directed-at link) |
| organisation_id | uuid | no | Addressee organisation | PK part, FK, cascade delete | AI-U |
| is_implemented | boolean | yes | Organisation has implemented the recommendation | default false | System (records human tracking action) |
| implemented_at | timestamptz | yes | When marked implemented | trigger-stamped when is_implemented flips true, cleared when false | System |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
4. Lookup and reference tables
shield_code_categories
Categories grouping SHIELD codes. Seeded reference data (20 categories).
Keys: PK id. UNIQUE name.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| name | text | no | Category name | unique | System (seeded CHIRP taxonomy) |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
shield_codes
The SHIELD causal-factor taxonomy itself - CHIRP's controlled vocabulary of human factors in maritime incidents. Seeded reference data (96 codes in 20 categories under three top-level groups); see Appendix A.
Keys: PK id. UNIQUE code. FK category_id → shield_code_categories(id) ON DELETE SET NULL (an uncategorised code remains valid).
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| category_id | uuid | yes | Grouping category | FK, SET NULL | System (seeded CHIRP taxonomy) |
| code | text | no | Short taxonomy identifier (e.g. PPC2) | unique | System (seeded CHIRP taxonomy) |
| title | text | no | Code title (e.g. "Fatigue") | - | System (seeded CHIRP taxonomy) |
| definition | text | yes | Full definition of the causal factor | - | System (seeded CHIRP taxonomy) |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
narrative_entity_types
Controlled vocabulary of entity types. Seeded reference data (5 types); referenced by natural key from narrative_entities.type.
Keys: PK id. UNIQUE name.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| name | text | no | Type name | unique; seeded values: person, vessel, organisation, location, equipment | System (seeded vocabulary) |
| description | text | yes | What the type covers | - | System (seeded vocabulary) |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
legislation
Legislation register shared across safety issues - one law can back findings in many reports. When this feature ships, an agentic AI attaches relevant legislation to a safety issue, sourced from the report itself or pulled from external legal sources; every attachment needs analyst verification. Not yet implemented - empty in this database.
Keys: PK id.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| name | text | no | Name of the legislation | - | AI-U (AI-attached, requires verification) |
| reference | text | yes | Formal reference | - | AI-U (AI-attached, requires verification) |
| jurisdiction | text | yes | Jurisdiction of the legislation | - | AI-U (AI-attached, requires verification) |
| url | text | yes | Link to the legislation | - | AI-U (AI-attached, requires verification) |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
organisations
Parties that recommendations are directed at. Identified by the AI as it extracts recommendations - it works out which party each recommendation points to. Contact details are essential for a company: they let CHIRP track whether a recommendation was implemented, and chase or escalate to the organisation if not. The AI fills contact fields from the report text where it can, otherwise from a web search, otherwise they are added manually; all are shown to the CHIRP user to check and audit.
A row is not always a company. Reports frequently address a class of people - "All UK Operators of small commercial high speed craft…" - and the same class recurs across reports, so it earns a row of its own; kind says which sort of row it is. A class has no contact, which is why contact_name is nullable.
Keys: PK id.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| name | text | no | Organisation or class name | - | AI-U (extracted from the recommendation) |
| kind | organisation_kind | no | Whether the row is a named company or a class of people | enum: company, class; default company | AI-U (extracted from the recommendation) |
| contact_name | text | yes | Named contact at the organisation | null for a class row, which has no contact | AI-U (from text, else web search, else manual; CHIRP-verified) |
| text | yes | Contact email | - | AI-U (from text, else web search, else manual; CHIRP-verified) | |
| phone_number | text | yes | Contact phone | - | AI-U (from text, else web search, else manual; CHIRP-verified) |
| address | text | yes | Postal address | - | AI-U (from text, else web search, else manual; CHIRP-verified) |
| website_url | text | yes | Website | - | AI-U (from text, else web search, else manual; CHIRP-verified) |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
organisation_identifiers
Curated identifiers that canonicalise an organisation, one row per identifier - so spelling variants resolve to a single organisation rather than many near-duplicates. Mirrors author_identifiers.
Keys: PK id. FK organisation_id → organisations(id) ON DELETE CASCADE.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| organisation_id | uuid | no | Owning organisation | FK, cascade delete | Pipeline |
| identifier | text | no | Curated identifier used to resolve name variants to one canonical organisation | curated | System |
| created_at / updated_at | timestamptz | yes | Audit timestamps | - | System |
taxonomy_terms
Shared lookup for every tree-shaped MAIB classification - spreadsheet-sourced, so referenced only from the UK-side tables. One row per term; parent_id links a term to its parent; taxonomy names which tree the term belongs to. Built from the spreadsheet's parallel level-columns (_L1, _L2, …), collapsed into one tree so a query can group by a type without knowing which level each row happens to fill. Carries no audit timestamps.
Keys: PK id. UNIQUE (id, taxonomy) and (taxonomy, parent_id, label). Composite self-FK (parent_id, taxonomy) → (id, taxonomy) ON UPDATE CASCADE ON DELETE CASCADE - a term's parent must live in the same taxonomy.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| taxonomy | taxonomy_name | no | Which tree the term belongs to | enum: main_event, ship_type, vessel_category, vessel_place_on_board, person_place_on_board, physical_condition, injury_type, deviation | MAIB |
| parent_id | uuid | yes | Parent term; null at the root of a tree | self-FK, same taxonomy | MAIB |
| label | text | no | The term text (e.g. "General Cargo") | - | MAIB |
Referenced from: occurrences.main_event_term_id; vessels.vessel_category_term_id, ship_type_term_id, place_on_board_term_id; affected_persons.physical_condition_term_id, injury_type_term_id, deviation_term_id, place_on_board_term_id. Place-on-board is split into two trees - vessel_place_on_board (referenced by vessels) and person_place_on_board (referenced by affected_persons).
ppe_items
Controlled vocabulary of PPE items, split out of the spreadsheet's comma-joined PPE_Used / PPE_Deficient cells. Referenced from affected_persons_ppe. Carries no audit timestamps.
Keys: PK id. UNIQUE label.
| Column | Type | Nullable | Description | Valid values / constraints | Source |
|---|---|---|---|---|---|
| id | uuid | no | Surrogate key | default gen_random_uuid() | System |
| label | text | no | PPE item name (e.g. "Life jacket") | unique | MAIB |
Database-enforced behaviour
Constraints participants should know about when writing to (or reasoning about) the data:
updated_atis trigger-maintained on every table except the vocabulary/junction tablestaxonomy_terms,ppe_items,affected_persons_ppe, which carry no timestamps.verified_at/implemented_atare trigger-stamped from their boolean flags and cannot drift: application code writes only the boolean.chunk_sentences.sort_orderis auto-assigned by trigger when inserted null.- Triggers validate that
safety_issues.document_idandrecommendations.document_idagree with the document derived from theirchunk_id- falling back tochunks.document_idwhen the chunk has no sentences attached yet - and that a narrative entity's mentions anchor only to sentences of the entity's own document. chunks.document_idis likewise trigger-validated (trg_validate_chunk_document): it may not contradict the document derived from the chunk's sentences, but a chunk with no sentences yet may name its document freely. Deleting a document cascades to its chunks.documents.jurisdictionis CHECK-restricted to'UK'or'US'(or null);safety_issues.record_typeto'safety_issue'or'safety_lesson', NOT NULL, defaulting tosafety_issue;organisations.kindis a NOT NULL enum defaulting tocompany.recommendations.reference_numberis indexed but deliberately not unique - re-ingesting a document rewrites its records, so uniqueness would fight regeneration rather than protect anything.tsvectorcolumns (title_tsv,text_tsv,name_tsv,action_tsv) are generated columns and cannot be written directly.source_idis UNIQUE onoccurrences,vesselsandaffected_persons(and NOT NULL onoccurrences/vessels) - the key MAIB spreadsheet ingestion upserts on (ON CONFLICT (source_id) DO UPDATE), touching only rows whosesource_modified_atshows MAIB revised them.documents.hashis UNIQUE (dedupes re-ingestion). The extraction lease is guarded by a CHECK:claim_expires_atmay be set only whenclaim_started_atis.taxonomy_termsenforces that a term's parent is in the sametaxonomy(composite FK on(parent_id, taxonomy)).documents.occurrence_matched_onis CHECK-restricted topublication_numberormanual, and is required wheneverdocuments.occurrence_idis set;document_particulars.loss_of_lifemust be null or ≥ 0;sentences.page_numbermust be null or ≥ 1.
Appendix A - SHIELD taxonomy
SHIELD is CHIRP's controlled taxonomy of human factors in maritime incidents: 96 codes in 20 categories under three top-level groups. Each code has a short identifier (e.g. PPC2), a title (e.g. "Fatigue") and a full definition. The taxonomy is seeded reference data - the complete list is reproduced below and lives in the shield_codes and shield_code_categories tables.
SHIELD is presented as an iceberg: the visible acts at the tip, the preconditions that set them up below the waterline, and the operational leadership decisions deeper still. For the model and its rationale, see the published paper: A New Taxonomy for the Analysis of Human Factors in Maritime Incidents (Safety, 2023).
| Group | Scope | Size |
|---|---|---|
| A · ACTS | Active failures by operators - Perception; Planning and Decision Making; Intentional Deviation; Response Execution; Communicating | 5 categories, 19 codes |
| P · PRECONDITIONS | Conditions that set the stage - Physical Environment; Equipment and Workplace; Interpersonal Communication; Team/Group; Misperception; Awareness; Memory; Mental Workload; Personal Factors; Physiological Condition; Drugs and Nutrition; Competence, Skills and Capability | 12 categories, 62 codes |
| L · OPERATIONAL LEADERSHIP | Leadership decisions affecting safety - Personnel Leadership; Operations Planning; Task Leadership | 3 categories, 15 codes |
The full taxonomy
All 96 codes, grouped by their three top-level groups and 20 categories.
A · ACTS
Communicating
| Code | Title | Definition |
|---|---|---|
| AC1 | Incorrect/unclear transmission of information | The operator transmits to other actors information which is incorrect or unclear, e.g. use of wrong callsign. |
| AC2 | No transmission of information | The operator does not transmit information which is necessary for other actors to operate safely / effectively. |
Intentional Deviation
| Code | Title | Definition |
|---|---|---|
| AI1 | Workaround in normal conditions | The operator decides to intentionally deviate from an agreed procedure or practice in a normal operating condition. |
| AI2 | Routine workaround | The operator habitually and intentionally deviates from an agreed procedure or practice on a regular basis. |
| AI3 | Workaround in exceptional conditions | The operator decides to intentionally deviate from an agreed procedure or practice in an exceptional operating condition. |
| AI4 | Sabotage | The operator decides to intentionally deviate from an agreed procedure or practice in order to create damage to the system or organisation. |
Perception
| Code | Title | Definition |
|---|---|---|
| AP1 | No/wrong/late visual detection | The operator does not detect (or detects too late or inaccurately) a visual signal necessary to formulate a proper action plan or make a correct decision. |
| AP2 | No/wrong/late auditory detection | The operator does not detect (or detects too late or inaccurately) an auditory signal necessary to formulate a proper action plan or make a correct decision. |
| AP3 | No/wrong/late kinaesthetic detection | The operator does not detect (or detects too late or inaccurately) a kinaesthetic signal necessary to formulate a proper action plan or make a correct decision. |
| AP4 | No/wrong/late with other senses (e.g. smell, temperature) | The operator does not perceive (or perceives too late or inaccurately) information received with senses different from vision, hearing and touch, which is necessary to formulate a proper action plan or make a correct decision. |
Planning and Decision Making
| Code | Title | Definition |
|---|---|---|
| AD1 | Incorrect decision or plan | The operator fails to elaborate an action plan or make a decision which is insufficient to manage the situation. |
| AD2 | Late decision or plan | The operator fails to elaborate a timely action plan or decision to manage the situation. |
| AD3 | No decision or plan | The operator fails to elaborate any action plan or decision to manage the situation. |
Response Execution
| Code | Title | Definition |
|---|---|---|
| AR1 | Timing error | The operator has planned to take an action which is appropriate for the situation, but executes it either too early or too late. |
| AR2 | Sequence error | The operator carries out a series of actions in the wrong sequence. |
| AR3 | Right action on the wrong object | The operator has planned to take an action which is appropriate for the perceived situation but - when executing it - selects an object (e.g. lever, knob, button, HMI element) different from the intended one. |
| AR4 | Wrong action on the right object | The operator selects the correct object (e.g. lever, knob, button, HMI element), but performs an action that is not the correct one. |
| AR5 | Lack of physical coordination | The operator takes an action which is appropriate for the perceived situation, but executes it in a wrong manner, due to lack of physical coordination. |
| AR6 | No action executed | The operator has planned to take an action which is appropriate for the perceived situation, but does not execute it. |
L · OPERATIONAL LEADERSHIP
Operations Planning
| Code | Title | Definition |
|---|---|---|
| LO1 | Inadequate risk assessment | Operations leader does not adequately evaluate the risks associated with a specific operation or scenario. |
| LO2 | Inadequate crew or team makeup or composition | Operations leader allows inadequate makeup or composition of crew or team for a given activity/operation. |
| LO3 | Inappropriate pressure to perform a task | Inappropriate pressure by operational leader causes an operator to feel pressured to perform a task or activity. |
| LO4 | Directed task with inadequate qualification or currency | Operations leader allows an operator to perform a task, while the qualification or currency of the operator are not in line with the training requirements for the associated activity. |
| LO5 | Directed task with limited experience | Operations leader allows operators to perform a task, while their experience for a specific operation, event or scenario is too limited. |
| LO6 | Directed task with inadequate equipment | Operations leader directs operators to undertake an activity that is beyond the capabilities of their equipment. |
Personnel Leadership
| Code | Title | Definition |
|---|---|---|
| LP1 | No personnel measures against regular risky behaviour | An operations leader does not identify an operator who regularly exhibits risky behaviours or does not institute the necessary remedial action. |
| LP2 | Inappropriate behaviour affects learning | Inappropriate behaviour of operations leader affects learning by operators, which manifests itself in actions that are either inappropriate to their skill level or violate standard procedures. |
| LP3 | Personality conflict | A personality conflict exists between an operations leader and an operator. |
| LP4 | Lack of feedback on safety reporting | Operations leader does not provide feedback to operator following his/her provision of information on a potential safety issue. |
Task Leadership
| Code | Title | Definition |
|---|---|---|
| LT1 | Inadequate leadership or supervision | Availability, competency, quality or timeliness of leadership or supervision does not meet task demands. |
| LT2 | No correction of unsafe practices | An operations leader does not correct known unsafe practices, conditions, guidance or procedure, which allows hazardous practices within the scope of his / her authority. |
| LT3 | No enforcement of existing rules | Operations leader does not enforce organisational and operating rules. |
| LT4 | Allowing unwritten policies to become standard | Operations leader allows policies that have not been formally recognized by the organisation to be perceived as standards. |
| LT5 | Directed deviation | Operations leader directs a subordinate to deviate from existing regulations, procedures or technical guidance. |
P · PRECONDITIONS
Awareness
| Code | Title | Definition |
|---|---|---|
| PAW1 | Channelized attention | Operator focuses all attention on a limited number of cues and excludes other cues of an equal or higher priority. This includes tunnel vision. |
| PAW2 | Confusion | Operator does not maintain a cohesive awareness of events and required actions, and this leads to confusion. |
| PAW3 | Distraction | Interruption and/or inappropriate redirection of operator's attention. |
| PAW4 | Inattention | Operator is not alert / ready to process immediately available information. |
| PAW5 | Geographically lost | The operator perceives to be at a different location compared to the one where s/he actually is. |
| PAW6 | Unsuitable mental model | Operator uses an unsuitable mental model to integrate information and arrives at a wrong understanding of the situation (e.g. wrong understanding of automation behaviour). |
| PAW7 | Pre-conceived notion or expectancy | Prevalence of expectations on a certain course of action regardless of other cues degrades operator performance. |
Competence, Skills and Capability
| Code | Title | Definition |
|---|---|---|
| PCS1 | Inadequate experience | Operator does not have sufficient experience with a task at hand. |
| PCS2 | Lack of proficiency | Operator capability to accomplish a task does not meet the performance levels expected from her/his skill level. |
| PCS3 | Inadequate training or currency | Operator does not meet general training or recurring training requirements for the task assigned to her/him. |
| PCS4 | Body size, strength or coordination limitations | Body size, strength, dexterity, coordination mobility or other biomechanical limitations of the operator degrade the task performance of the operator. |
Drugs and Nutrition
| Code | Title | Definition |
|---|---|---|
| PDN1 | Recreational drugs and alcohol | Recreational use of drugs or alcohol impairs or interferes with operator performance. |
| PDN2 | Prescribed drugs or OTC medications | Use of prescribed drugs or over-the-counter medications or supplements interferes with operator task performance. |
| PDN3 | Inadequate nutrition, hydration or dietary practice | Inadequate nutritional state, hydration or dietary practice degrade operator performance. |
Equipment and Workplace
| Code | Title | Definition |
|---|---|---|
| PEW1 | Ergonomics and human machine interface issues | The ergonomics of tools and human machines interface, including controls, switches, displays, warning systems and symbology degrade the operator's performance. |
| PEW2 | Technology creates an unsafe situation | The design, malfunction, failure, symbology, logic or other aspects of technical/automated systems degrade the operator's performance. |
| PEW3 | Workspace or working position incompatible with operation | The interior or exterior workspace layout or the working position are incompatible with the task requirements of the operator. |
| PEW4 | Personal protective equipment interference | Personal protection equipment (helmets, suits, gloves, etc.) interferes with normal duties of the operator. |
| PEW5 | Communication equipment inadequate | Communication equipment is inadequate or unavailable to support task demands. Communications can be voice, data or multi-sensory. |
| PEW6 | Fuels or materials | Working with fuels, chemicals or materials degrades the operator's performance. |
Interpersonal Communication
| Code | Title | Definition |
|---|---|---|
| PCO1 | Briefing or handover inadequate | Individual or team has not well completed the briefing or handover of an activity. |
| PCO2 | Inadequate communication due to team members' rank or position | Differences in rank or position within team limit or jeopardize team communication. |
| PCO3 | Language difficulties | Communication between operators with different native languages degrades operator's performance. |
| PCO4 | Non-standard or complex communication | Operators use terminology / phrases or hand signals differing from standards and training, or they use complex messages that may lead to misunderstanding. |
Memory
| Code | Title | Definition |
|---|---|---|
| PME1 | Forget actions/intentions | The operator has a temporary memory lapse and forgets planned actions or intentions. |
| PME2 | No/inaccurate recall of information | The operator does not retrieve or recall information accurately from memory. |
| PME3 | Negative habit | The operator uses a highly learned behaviour from past experiences which is inadequate to handle the present situation. |
Mental Workload
| Code | Title | Definition |
|---|---|---|
| PMW1 | High workload | High workload degrades the operator's performance. |
| PMW2 | Low workload | Low workload imposes idleness and waiting, and it degrades operator's performance. |
| PMW3 | Information processing overload | Available mental resources are insufficient to process the amount of complex information. |
| PMW4 | Startle effect | Available mental resources are insufficient to process sudden, high-intensity, unexpected information, leading to the startle effect. |
Misperception
| Code | Title | Definition |
|---|---|---|
| PER1 | Motion illusion | Erroneous physical sensation of orientation, motion or acceleration by the operator. |
| PER2 | Visual illusion | Erroneous perception of orientation, motion or acceleration following visual stimuli. |
| PER3 | Misperception of changing environment | Misperceived or misjudged altitude, separation, speed, closure rate, road/sea conditions, aircraft/vehicle location within the performance envelope. |
| PER4 | Misinterpreted or misread instrument | Misread, misinterpreted or not recognized significance of correct instrument reading. |
Personal Factors
| Code | Title | Definition |
|---|---|---|
| PPF1 | Emotional state | Strong positive or negative emotion degrade operator's performance. |
| PPF2 | Personality style | Operator's personality traits (e.g. authoritarian, over-conservative, impulsive, invulnerable, submissive) contribute to degraded performance and/or negatively affect interaction with other team members. |
| PPF3 | Confidence level | Inadequate estimation by the operator of personal capability, of the capability of others or the capability of equipment degrades performance. |
| PPF4 | Performance/peer pressure | Threat to self-image and feeling of pressure to perform an activity despite concerns about the risk associated degrades performance. |
| PPF5 | Motivation | Excessive or inadequate motivation to accomplish a task or prevalence of personal goals over organisation's goals degrades operator performance. |
| PPF6 | Pre-existing psychological condition | Pre-existing acknowledged personality, psychological or psychosocial disorder/problem degrades operator performance. |
| PPF7 | Risk underestimation | False sense of safety or complacency brings the operator to ignore hazards or to underestimate the risks associated to them, thus degrading performance. |
Physical Environment
| Code | Title | Definition |
|---|---|---|
| PPE1 | Vision affected by environment | Environmental conditions affect the operator's vision. |
| PPE2 | Operator movement affected by environment | Environmental conditions affect the operator's movement. |
| PPE3 | Hearing affected by environment | Environmental conditions affect the operator's ability to hear. |
| PPE4 | Mental processing affected by environment | Environmental conditions affect the operator's ability to mentally process or think about information. |
| PPE5 | Heat or cold stress | Exposure to heat or cold degrades the operator's performance capabilities. |
| PPE6 | Operation more difficult due to weather and environment | Weather conditions and/or environment make controlling the operation more difficult. |
| PPE7 | Acceleration | Forces acting on a body by acceleration or gravity degrade the operator's performance capabilities. |
| PPE8 | Vibration stress | Excessive exposure to vibration degrades operator physical or cognitive performance. |
| PPE9 | Long term isolation | An individual is subject to long term isolation and this degrades operator performance. |
Physiological Condition
| Code | Title | Definition |
|---|---|---|
| PPC1 | Injury or illness existed during operation | Pre-existing physical illness, injury, deficit or diminished physical capability due to the injury, illness or deficit, degrades operator performance. This includes situations where the operator intentionally performs duties with a known (disqualifying) medical condition. |
| PPC2 | Fatigue | Diminished mental capability due to fatigue, restricted or shortened sleep, mental activity during prolonged wakefulness or disturbance of circadian rhythm degrades operator performance. |
| PPC3 | Mentally exhausted (burnout) | Exhaustion associated with the wearing effects of high operational and/or lifestyle tempo, in which operational requirements impinge on the ability to satisfy personal requirements degrades operator performance. |
| PPC4 | Hypoxia | Insufficient oxygen supply to the body impairs operator performance. |
| PPC5 | Decompression sickness | Development of nitrogen bubbles in the blood and tissues as a result of too quick reduction of atmospheric pressure causes operator chest pains, bends, difficult breathing, skin irritation, cramps. |
Team/Group
| Code | Title | Definition |
|---|---|---|
| PTG1 | Team working towards different goals | Team members are working towards different goals, leading to loss of shared situational awareness and not anticipating potential problems. |
| PTG2 | No cross-check and speaking-up by team member | Decisions or actions by team members are not crosschecked. There is no multi-person approach to execution of critical tasks / procedures and no communication of concerns, not necessarily due to rank or position. |
| PTG3 | No monitoring and speaking-up of team status and functioning | Team members do not monitor the status and functioning of each other for signs of stress, fatigue, complacency, and task saturation, or do not speak up if status and functioning are monitored as being incorrect. |
| PTG4 | No adaptation of team performance in demanding situation | Team does not adapt to demanding circumstances. There is no change in team roles and task allocation, there is no team priorisation of plans and tasks, no workload management, and no management of interruptions and distractions. |
| PTG5 | Long term team confinement | Long term close proximity or confinement degrades team functioning and operator performance. |
| PTG6 | Group think | Excessive tendency towards group, team or organisation consensus and conformity over independent critical analysis and decision making degrades operator performance. |