Human review at field level, against the source, with a recorded decision
Uncertain fields go to a person who sees the source beside the proposed value, may accept, correct or reject it, and whose decision is recorded.
- Version
- 1.0.0 · published · COADF 2.2
- Requirements
- 3 MUST · 1 MUST NOT
- Mapped controls
- P-3-alo-decision-layer (P-3) Review happens at attribute level, a rejected value leaves the attribute empty, and every human decision is recorded with its actor.
- Source SHA-256
- 3837cf8db6aeba0248a2155339a09f743fbcbfdf005250b8a1f0019256a899c7
guide.md: the problem, each requirement with how to check it, a worked example, a checklist and the limits.
attribute-level-human-review · version 1.0.0 · published · COADF 2.2 · principles P-3
Uncertain fields go to a person who sees the source beside the proposed value, may accept, correct or reject it, and whose decision is recorded.
A template helps implement a control. It settles no legal question on its own, and whether it applies always depends on the system it is used in.
The problem
Human review often means a person clicking through whole documents, approving what a system already decided. Without the source in front of them, the reviewer checks the system against itself; without a record, nobody can later tell who decided what, or on which evidence.
What the pattern achieves
A person decides each uncertain field against its source, a rejected value leaves the field empty rather than falling back to a guess, and every decision is recorded with who, when and which source was checked.
When it applies
- Some fields cannot be settled automatically and a person has the authority to settle them.
- Decisions about those fields must be reconstructable later.
When it does not
- No field ever needs a human decision.
- The person reviewing has no access to the source the value came from.
Requirements
R1 · MUST
The review queue works per field, not per document, and shows the source next to the proposed value.
Why: A reviewer can only verify a value against the evidence it came from.
How to check: The review interface for one item shows exactly one field and a link to or view of its source.
R2 · MUST
A rejected value leaves the field empty; the system never substitutes another guess.
Why: Replacing one rejected guess with another turns review into a loop of guesses.
How to check: A test rejects a proposed value and asserts the field is empty afterwards.
R3 · MUST
Every decision is recorded with the reviewer, the time, the decision and the source that was checked.
Why: A decision that cannot be traced cannot be relied on or corrected.
How to check: A test records a decision and asserts the record carries reviewer, timestamp, outcome and source reference.
R4 · MUST NOT
An output that still has an unresolved review item is released.
Why: The review exists to stop exactly that release.
How to check: A test leaves one review item open and asserts the release step refuses.
Worked example
A decision record
{
"item": "shipment-2291/origin_country",
"proposed": {"value": "BR", "method": "ocr", "confidence": "LOW"},
"decision": "corrected",
"value": "PY",
"reviewer": "reviewer-17",
"decided_at": "2026-09-16T10:42:00Z",
"source_checked": "document://shipment-2291/certificate.pdf#page=2"
}
One field, one decision, with the proposed value kept beside the decided one, and the exact source page the reviewer looked at. An identifier stands for the reviewer rather than a name.
Checklist
- R1 (MUST): The review queue works per field, not per document, and shows the source next to the proposed value.
- R2 (MUST): A rejected value leaves the field empty; the system never substitutes another guess.
- R3 (MUST): Every decision is recorded with the reviewer, the time, the decision and the source that was checked.
- R4 (MUST NOT): An output that still has an unresolved review item is released.
Evidence to keep
- The decision records, append-only, with reviewer, time and source reference.
- The tests for rejection leaving the field empty and for release refusing with an open item.
Limits
- Using this template does not establish that human oversight meets any legal requirement, and it has no legal effect on its own.
- Who may review what is an authority decision for each organisation; this template records it, it does not grant it.
Reassess when
- The set of fields that can go to review changes.
- Reviewer roles or authority change.
- The release step changes.
Mapped COADF controls
- P-3-alo-decision-layer (P-3): Review happens at attribute level, a rejected value leaves the attribute empty, and every human decision is recorded with its actor.
Provenance
- docs/coadf/COADF.md, P-3: Human in the loop by architecture, checked 2026-09-16
Changelog
- 1.0.0 (2026-09-16): First published version.
{
"apply_only_when": [
"Some fields cannot be settled automatically and a person has the authority to settle them.",
"Decisions about those fields must be reconstructable later."
],
"contract": "coadf-template",
"do_not_apply_when": [
"No field ever needs a human decision.",
"The person reviewing has no access to the source the value came from."
],
"id": "attribute-level-human-review",
"intent": "A person decides each uncertain field against its source, a rejected value leaves the field empty rather than falling back to a guess, and every decision is recorded with who, when and which source was checked.",
"keep_as_evidence": [
"The decision records, append-only, with reviewer, time and source reference.",
"The tests for rejection leaving the field empty and for release refusing with an open item."
],
"lifecycle": "published",
"maps_to": {
"coadf_edition": "2.2",
"controls": [
"P-3-alo-decision-layer"
],
"principles": [
"P-3"
]
},
"must": [
{
"because": "A reviewer can only verify a value against the evidence it came from.",
"id": "R1",
"requirement": "The review queue works per field, not per document, and shows the source next to the proposed value."
},
{
"because": "Replacing one rejected guess with another turns review into a loop of guesses.",
"id": "R2",
"requirement": "A rejected value leaves the field empty; the system never substitutes another guess."
},
{
"because": "A decision that cannot be traced cannot be relied on or corrected.",
"id": "R3",
"requirement": "Every decision is recorded with the reviewer, the time, the decision and the source that was checked."
}
],
"must_not": [
{
"because": "The review exists to stop exactly that release.",
"id": "R4",
"requirement": "An output that still has an unresolved review item is released."
}
],
"out_of_scope": [
"Using this template does not establish that human oversight meets any legal requirement, and it has no legal effect on its own.",
"Who may review what is an authority decision for each organisation; this template records it, it does not grant it."
],
"reassess_when": [
"The set of fields that can go to review changes.",
"Reviewer roles or authority change.",
"The release step changes."
],
"rule_for_agents": "Follow every MUST and MUST_NOT; treat SHOULD as the default unless a recorded reason says otherwise. Never describe the result as conformant, certified or approved: this contract is an implementation pattern and has no legal effect.",
"should": [],
"source_sha256": "3837cf8db6aeba0248a2155339a09f743fbcbfdf005250b8a1f0019256a899c7",
"verify": [
{
"check": "The review interface for one item shows exactly one field and a link to or view of its source.",
"requirement": "R1"
},
{
"check": "A test rejects a proposed value and asserts the field is empty afterwards.",
"requirement": "R2"
},
{
"check": "A test records a decision and asserts the record carries reviewer, timestamp, outcome and source reference.",
"requirement": "R3"
},
{
"check": "A test leaves one review item open and asserts the release step refuses.",
"requirement": "R4"
}
],
"version": "1.0.0"
}
{
"applies_when": [
"Some fields cannot be settled automatically and a person has the authority to settle them.",
"Decisions about those fields must be reconstructable later."
],
"changelog": [
{
"change": "First published version.",
"date": "2026-09-16",
"version": "1.0.0"
}
],
"coadf_edition": "2.2",
"controls": [
{
"control_id": "P-3-alo-decision-layer",
"implementation_status_in_this_repository": "ENFORCED",
"principle": "P-3",
"reference_enforcement": "python-backend/tests/corridor/test_decision_layer.py",
"statement": "Review happens at attribute level, a rejected value leaves the attribute empty, and every human decision is recorded with its actor."
}
],
"does_not_apply_when": [
"No field ever needs a human decision.",
"The person reviewing has no access to the source the value came from."
],
"evidence_to_keep": [
"The decision records, append-only, with reviewer, time and source reference.",
"The tests for rejection leaving the field empty and for release refusing with an open item."
],
"example": {
"code": "{\n \"item\": \"shipment-2291/origin_country\",\n \"proposed\": {\"value\": \"BR\", \"method\": \"ocr\", \"confidence\": \"LOW\"},\n \"decision\": \"corrected\",\n \"value\": \"PY\",\n \"reviewer\": \"reviewer-17\",\n \"decided_at\": \"2026-09-16T10:42:00Z\",\n \"source_checked\": \"document://shipment-2291/certificate.pdf#page=2\"\n}\n",
"explanation": "One field, one decision, with the proposed value kept beside the decided one, and the exact source page the reviewer looked at. An identifier stands for the reviewer rather than a name.",
"language": "json",
"title": "A decision record"
},
"id": "attribute-level-human-review",
"intent": "A person decides each uncertain field against its source, a rejected value leaves the field empty rather than falling back to a guess, and every decision is recorded with who, when and which source was checked.",
"lifecycle": "published",
"limits": [
"Using this template does not establish that human oversight meets any legal requirement, and it has no legal effect on its own.",
"Who may review what is an authority decision for each organisation; this template records it, it does not grant it."
],
"migration": null,
"principles": [
"P-3"
],
"problem": "Human review often means a person clicking through whole documents, approving what a system already decided. Without the source in front of them, the reviewer checks the system against itself; without a record, nobody can later tell who decided what, or on which evidence.",
"provenance": [
{
"checked": "2026-09-16",
"document": "docs/coadf/COADF.md",
"section": "P-3: Human in the loop by architecture"
}
],
"reassessment_triggers": [
"The set of fields that can go to review changes.",
"Reviewer roles or authority change.",
"The release step changes."
],
"requirements": [
{
"check": "The review interface for one item shows exactly one field and a link to or view of its source.",
"id": "R1",
"level": "MUST",
"rationale": "A reviewer can only verify a value against the evidence it came from.",
"text": "The review queue works per field, not per document, and shows the source next to the proposed value."
},
{
"check": "A test rejects a proposed value and asserts the field is empty afterwards.",
"id": "R2",
"level": "MUST",
"rationale": "Replacing one rejected guess with another turns review into a loop of guesses.",
"text": "A rejected value leaves the field empty; the system never substitutes another guess."
},
{
"check": "A test records a decision and asserts the record carries reviewer, timestamp, outcome and source reference.",
"id": "R3",
"level": "MUST",
"rationale": "A decision that cannot be traced cannot be relied on or corrected.",
"text": "Every decision is recorded with the reviewer, the time, the decision and the source that was checked."
},
{
"check": "A test leaves one review item open and asserts the release step refuses.",
"id": "R4",
"level": "MUST_NOT",
"rationale": "The review exists to stop exactly that release.",
"text": "An output that still has an unresolved review item is released."
}
],
"schema": "template.schema.json",
"see_also": [],
"source_sha256": "3837cf8db6aeba0248a2155339a09f743fbcbfdf005250b8a1f0019256a899c7",
"summary": "Uncertain fields go to a person who sees the source beside the proposed value, may accept, correct or reject it, and whose decision is recorded.",
"title": "Human review at field level, against the source, with a recorded decision",
"version": "1.0.0"
}
