ReviewAssignment schema
Generated from the canonical schema
schemas/review-assignment.schema.jsonbyscripts/generate-schema-docs.mjs— do not edit this page by hand.
Frozen contract (Stage 7A, 2026-09-02; seats and claims 2026-09-02; assistance declaration 2026-09-03). One claim of one seat on one review node of one ReviewProcess by a User (or one TfP-hosted agent issuance), and what came back. The assignment records exactly who judged (the accountable User for a human; the effective provider/model/config TfP executed for a hosted agent), what assistance a human declared (provenance in the reviewer's words, not identity and not an execution record), what context was supplied (SkillVersions, visible prior nodes, stage evidence, what was hidden), and the schema-validated structured response with its rationale, citations, and any declared confidence. Reduce nodes never have assignments. Review work is not a Problem: an assignment is operational work generated because another object needs adjudication.
Schema version: 0.5.0 · $id: https://tokensforprogress.org/schemas/review-assignment.schema.json
Fields
id
Type: string · Required: yes · Mutable: no · Pattern: ^ras_[0-9a-z]{10,32}$
Example: "ras_01jq8s5f2jan"
review_process_id
Type: string · Required: yes · Mutable: no · Pattern: ^rpr_[0-9a-z]{10,32}$
node_id
Type: string · Required: yes · Mutable: no · Pattern: ^[a-z][a-z0-9_]{0,39}$
reviewer
Type: object · Required: yes · Mutable: no
Who is accountable for this judgment.
reviewer.kind
Type: human | agent · Required: yes · Mutable: —
reviewer.user_id
Type: string \| null · Required: yes · Mutable: — · Default: null · Pattern: ^usr_[0-9a-z]{10,32}$
The accountable User for a human reviewer; null for an agent.
reviewer.agent
Type: object \| null · Required: yes · Mutable: — · Default: null
The exact provider/model/config for an agent reviewer; null for a human.
assistance
Type: object \| null · Required: yes · Mutable: yes · Default: null
For a human reviewer who used an agent while forming the judgment: the model and configuration, recorded as provenance. The human remains the accountable reviewer. Null for agent reviewers and for unassisted humans.
assistance.provider
Type: string · Required: yes · Mutable: —
The provider of the agent that assisted, as the reviewer names it. Any string; TfP did not invoke it.
Example: "anthropic"
assistance.model
Type: string · Required: yes · Mutable: —
The model the reviewer says assisted them, as they name it.
Example: "claude-opus-5"
assistance.config
Type: object \| null · Required: no · Mutable: — · Default: null
Optional self-declared provenance supplied by the accountable reviewer (tools, settings, how the agent was run); TfP did not independently verify these settings and does not require any. Never an execution record.
Example: {"tools":["claude-code"],"effort":"high"}
context
Type: object · Required: yes · Mutable: no
Exactly what was supplied to the reviewer, so a judgment can later be evaluated against what its author could see.
context.skill_version_ids
Type: array · Required: yes · Mutable: —
context.visible_node_ids
Type: array · Required: yes · Mutable: —
context.stage_evidence_included
Type: boolean · Required: yes · Mutable: —
context.hidden
Type: array · Required: yes · Mutable: —
independence_group
Type: string \| null · Required: yes · Mutable: no · Default: null
Reviewers in different groups on the same node cannot see one another's responses before completing. Null when the node is not independent.
status
Type: pending | accepted | completed | declined | expired | invalid · Required: yes · Mutable: yes
accepted (a human claimed the seat; the hold is running) → completed, or declined (the claim was released) or expired (the hold or the node deadline passed). Agent-kind assignments additionally use pending (issued, not yet answered) and invalid (a reply that failed the rubric; retained).
response
Type: object \| null · Required: yes · Mutable: yes · Default: null
The structured response, validated against the node's rubric.response_schema. Null until a response arrives. On an invalid assignment, the rejected response as submitted.
rationale_md
Type: string \| null · Required: yes · Mutable: yes · Default: null
The reviewer's communicable justification, required when the rubric says so. Not hidden reasoning: TfP does not request, store, or expose chain-of-thought.
citations
Type: array · Required: yes · Mutable: yes · Default: []
Structured evidence pointers, at least rubric.citations.min_items of them on a completed assignment.
citations[].resource_uri
Type: string \| null · Required: yes · Mutable: — · Pattern: ^tfp://
The material cited, by the same tfp:// Resource URI TfP handed the reviewer (an Artifact, a reference input, a Skill file). Preferred; artifact_id is derived from it for Artifacts.
citations[].artifact_id
Type: string \| null · Required: yes · Mutable: — · Default: null · Pattern: ^art_[0-9a-z]{10,32}$
The Artifact cited, when the citation is an Artifact; derived from resource_uri.
citations[].resource
Type: string \| null · Required: yes · Mutable: — · Default: null
A URI or named reference when the evidence is not an Artifact (a reference input slot, a supplied Skill, an external document).
citations[].locator
Type: string \| null · Required: yes · Mutable: — · Default: null
Page, line, section, byte range, or similar.
citations[].quote
Type: string \| null · Required: yes · Mutable: — · Default: null
confidence
Type: number \| null · Required: yes · Mutable: yes · Default: null
Overall declared confidence in [0, 1]; required when the rubric says so. Lives here, not inside response, so it reads the same across every protocol.
decline_reason
Type: string \| null · Required: yes · Mutable: yes · Default: null
created_at
Type: string · Required: yes · Mutable: no
accepted_at
Type: string \| null · Required: yes · Mutable: yes · Default: null
completed_at
Type: string \| null · Required: yes · Mutable: yes · Default: null
expired_at
Type: string \| null · Required: yes · Mutable: yes · Default: null
invalid_reason
Type: string \| null · Required: yes · Mutable: yes · Default: null
For invalid assignments: which rubric requirement the response failed.
hold_until
Type: string \| null · Required: yes · Mutable: —
When the claim lapses if no response has been recorded (claimed_at + the protocol's claim_hold_minutes). Null for agent-kind assignments.
Example: "2026-09-05T12:00:00Z"
JSON Schema source
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://tokensforprogress.org/schemas/review-assignment.schema.json",
"title": "ReviewAssignment",
"description": "Frozen contract (Stage 7A, 2026-09-02; seats and claims 2026-09-02; assistance declaration 2026-09-03). One claim of one seat on one `review` node of one ReviewProcess by a User (or one TfP-hosted agent issuance), and what came back. The assignment records exactly who judged (the accountable User for a human; the effective provider/model/config TfP executed for a hosted agent), what assistance a human declared (provenance in the reviewer's words, not identity and not an execution record), what context was supplied (SkillVersions, visible prior nodes, stage evidence, what was hidden), and the schema-validated structured response with its rationale, citations, and any declared confidence. Reduce nodes never have assignments. Review work is not a Problem: an assignment is operational work generated because another object needs adjudication.",
"x-tfp-version": "0.5.0",
"type": "object",
"additionalProperties": false,
"required": [
"id",
"review_process_id",
"node_id",
"reviewer",
"assistance",
"context",
"independence_group",
"status",
"response",
"rationale_md",
"citations",
"confidence",
"decline_reason",
"invalid_reason",
"created_at",
"accepted_at",
"completed_at",
"expired_at",
"hold_until"
],
"properties": {
"id": {
"type": "string",
"pattern": "^ras_[0-9a-z]{10,32}$",
"x-mutable": false,
"examples": [
"ras_01jq8s5f2jan"
]
},
"review_process_id": {
"type": "string",
"pattern": "^rpr_[0-9a-z]{10,32}$",
"x-mutable": false
},
"node_id": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{0,39}$",
"x-mutable": false
},
"reviewer": {
"type": "object",
"additionalProperties": false,
"x-mutable": false,
"required": [
"kind",
"user_id",
"agent"
],
"description": "Who is accountable for this judgment.",
"properties": {
"kind": {
"type": "string",
"enum": [
"human",
"agent"
]
},
"user_id": {
"type": [
"string",
"null"
],
"pattern": "^usr_[0-9a-z]{10,32}$",
"default": null,
"description": "The accountable User for a human reviewer; null for an agent."
},
"agent": {
"type": [
"object",
"null"
],
"additionalProperties": false,
"required": [
"provider",
"model",
"config"
],
"properties": {
"provider": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"description": "Model provider identifier.",
"examples": [
"anthropic"
]
},
"model": {
"type": "string",
"minLength": 1,
"maxLength": 120,
"description": "Exact model identifier.",
"examples": [
"claude-fable-5-1"
]
},
"config": {
"type": "object",
"description": "The effective configuration TfP executed for this hosted agent: the protocol's allowed spec with the provider's defaults resolved at issue time (Anthropic: `effort`, `max_tokens`). Exact, because TfP performed the invocation; what the record says is what ran.",
"examples": [
{
"effort": "high",
"max_tokens": 16000
}
]
}
},
"default": null,
"description": "The exact provider/model/config for an agent reviewer; null for a human."
}
},
"allOf": [
{
"if": {
"properties": {
"kind": {
"const": "human"
}
}
},
"then": {
"properties": {
"user_id": {
"type": "string"
},
"agent": {
"type": "null"
}
}
}
},
{
"if": {
"properties": {
"kind": {
"const": "agent"
}
}
},
"then": {
"properties": {
"agent": {
"type": "object"
},
"user_id": {
"type": "null"
}
}
}
}
]
},
"assistance": {
"type": [
"object",
"null"
],
"additionalProperties": false,
"required": [
"provider",
"model"
],
"properties": {
"provider": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"description": "The provider of the agent that assisted, as the reviewer names it. Any string; TfP did not invoke it.",
"examples": [
"anthropic"
]
},
"model": {
"type": "string",
"minLength": 1,
"maxLength": 120,
"description": "The model the reviewer says assisted them, as they name it.",
"examples": [
"claude-opus-5"
]
},
"config": {
"type": [
"object",
"null"
],
"default": null,
"description": "Optional self-declared provenance supplied by the accountable reviewer (tools, settings, how the agent was run); TfP did not independently verify these settings and does not require any. Never an execution record.",
"examples": [
{
"tools": [
"claude-code"
],
"effort": "high"
}
]
}
},
"default": null,
"x-mutable": true,
"description": "For a human reviewer who used an agent while forming the judgment: the model and configuration, recorded as provenance. The human remains the accountable reviewer. Null for agent reviewers and for unassisted humans."
},
"context": {
"type": "object",
"additionalProperties": false,
"x-mutable": false,
"required": [
"skill_version_ids",
"visible_node_ids",
"stage_evidence_included",
"hidden"
],
"description": "Exactly what was supplied to the reviewer, so a judgment can later be evaluated against what its author could see.",
"properties": {
"skill_version_ids": {
"type": "array",
"maxItems": 10,
"items": {
"type": "string",
"pattern": "^skv_[0-9a-z]{10,32}$"
},
"uniqueItems": true
},
"visible_node_ids": {
"type": "array",
"maxItems": 20,
"items": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{0,39}$"
},
"uniqueItems": true
},
"stage_evidence_included": {
"type": "boolean"
},
"hidden": {
"type": "array",
"maxItems": 5,
"uniqueItems": true,
"items": {
"type": "string",
"enum": [
"submitter_identity",
"submitter_organization",
"prior_scores",
"attempt_notes"
]
}
}
}
},
"independence_group": {
"type": [
"string",
"null"
],
"maxLength": 40,
"x-mutable": false,
"default": null,
"description": "Reviewers in different groups on the same node cannot see one another's responses before completing. Null when the node is not independent."
},
"status": {
"type": "string",
"enum": [
"pending",
"accepted",
"completed",
"declined",
"expired",
"invalid"
],
"x-mutable": true,
"description": "accepted (a human claimed the seat; the hold is running) → completed, or declined (the claim was released) or expired (the hold or the node deadline passed). Agent-kind assignments additionally use pending (issued, not yet answered) and invalid (a reply that failed the rubric; retained)."
},
"response": {
"type": [
"object",
"null"
],
"x-mutable": true,
"default": null,
"description": "The structured response, validated against the node's rubric.response_schema. Null until a response arrives. On an invalid assignment, the rejected response as submitted."
},
"rationale_md": {
"type": [
"string",
"null"
],
"maxLength": 50000,
"x-mutable": true,
"default": null,
"description": "The reviewer's communicable justification, required when the rubric says so. Not hidden reasoning: TfP does not request, store, or expose chain-of-thought."
},
"citations": {
"type": "array",
"maxItems": 100,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"resource_uri",
"artifact_id",
"resource",
"locator",
"quote"
],
"description": "A structured pointer to evidence supporting a judgment: which Artifact or resource, where in it, and optionally the passage.",
"properties": {
"resource_uri": {
"type": [
"string",
"null"
],
"pattern": "^tfp://",
"maxLength": 500,
"description": "The material cited, by the same tfp:// Resource URI TfP handed the reviewer (an Artifact, a reference input, a Skill file). Preferred; artifact_id is derived from it for Artifacts."
},
"artifact_id": {
"type": [
"string",
"null"
],
"pattern": "^art_[0-9a-z]{10,32}$",
"default": null,
"description": "The Artifact cited, when the citation is an Artifact; derived from resource_uri."
},
"resource": {
"type": [
"string",
"null"
],
"maxLength": 500,
"default": null,
"description": "A URI or named reference when the evidence is not an Artifact (a reference input slot, a supplied Skill, an external document)."
},
"locator": {
"type": [
"string",
"null"
],
"maxLength": 200,
"default": null,
"description": "Page, line, section, byte range, or similar."
},
"quote": {
"type": [
"string",
"null"
],
"maxLength": 2000,
"default": null
}
}
},
"x-mutable": true,
"default": [],
"description": "Structured evidence pointers, at least rubric.citations.min_items of them on a completed assignment."
},
"confidence": {
"type": [
"number",
"null"
],
"minimum": 0,
"maximum": 1,
"x-mutable": true,
"default": null,
"description": "Overall declared confidence in [0, 1]; required when the rubric says so. Lives here, not inside response, so it reads the same across every protocol."
},
"decline_reason": {
"type": [
"string",
"null"
],
"maxLength": 500,
"x-mutable": true,
"default": null
},
"created_at": {
"type": "string",
"format": "date-time",
"x-mutable": false
},
"accepted_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"x-mutable": true,
"default": null
},
"completed_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"x-mutable": true,
"default": null
},
"expired_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"x-mutable": true,
"default": null
},
"invalid_reason": {
"type": [
"string",
"null"
],
"maxLength": 2000,
"x-mutable": true,
"default": null,
"description": "For invalid assignments: which rubric requirement the response failed."
},
"hold_until": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When the claim lapses if no response has been recorded (claimed_at + the protocol's claim_hold_minutes). Null for agent-kind assignments.",
"examples": [
"2026-09-05T12:00:00Z"
]
}
}
}