Attempt schema
Generated from the canonical schema
schemas/attempt.schema.jsonbyscripts/generate-schema-docs.mjs— do not edit this page by hand.
Canonical (Stage 4A, owner-approved 2026-09-01). One independent workstream against exactly one immutable ProblemRevision, owned by a User. The Attempt records who owned the work, which exact specification it was against, how the owner was representing themselves at the time, how the work was produced, and how it concluded. Attempts are non-exclusive and carry NO uniqueness constraint: there are no locks, leases, or claims, and a User may hold any number of concurrent active Attempts on the same Problem — one per independent approach or agent (User ≠ workstream). Starting always creates a new Attempt; resuming means addressing an existing attempt_id. Surfaces may show a User their existing active Attempts and offer resume-or-start-another, but that is presentation, not a constraint. The pinned revision never changes: if the Problem later gains a new current revision or is archived, the Attempt and its history remain exactly as they were, judged only against the revision it pinned. Liveness (recently active / cooling off / inactive) is DERIVED from the append-only ActivityEvent history, never stored here. Attempts and their Notes are public (visible to anyone who can see the Problem); no private-work machinery exists at this stage. Submissions are a separate later object: an Attempt records the work; it does not contain the outcome artifact. Revised 2026-09-26 (owner-approved frozen-spec change, schema 0.2.0): an Attempt may CONTINUE an ended Attempt of the same User on the same Problem (continues_attempt_id). Ending stays write-once; the next round of work after review feedback or a refuted verification is a new Attempt linked to the old one, never a reopening. Continuations form a linear chain (at most one successor per Attempt) that surfaces show as one thread; each Attempt in it stays the immutable record of one round.
Schema version: 0.2.0 · $id: https://tokensforprogress.org/schemas/attempt.schema.json
Fields
id
Type: string · Required: yes · Mutable: no · Pattern: ^att_[0-9a-z]{10,32}$
Stable opaque identifier.
Example: "att_01jg2kq8xw1p"
problem_revision_id
Type: string · Required: yes · Mutable: no · Pattern: ^prv_[0-9a-z]{10,32}$
The exact immutable ProblemRevision this work is against. Pinned at start, never rewritten — an Attempt made today and one made next year against the same revision were judged against the same fixed target. The owning Problem is reached through the revision; the Attempt does not track the Problem's later evolution.
Example: "prv_01jf8y9d4rev"
user_id
Type: string · Required: yes · Mutable: no · Pattern: ^usr_[0-9a-z]{10,32}$
The User who owns this Attempt and everything attached to it. Always a person's account — agents, models, and tools are recorded as provenance, never promoted to owners.
Example: "usr_01jf8xw3tempo"
attributed_organization_id
Type: string \| null · Required: yes · Mutable: no · Pattern: ^org_[0-9a-z]{10,32}$
Optional Organization the User chose to represent for this work, selected at start from their then-active memberships and FROZEN onto the Attempt. Later membership changes (leaving, being removed, the Organization changing) never alter this value — attribution belongs to the work as it happened. Null when the work was done in a purely personal capacity.
Example: null
provenance_kind
Type: human | agent | mixed · Required: yes · Mutable: yes
Coarse declaration of how the work is being produced: by the User directly (human), by a connected agent operating under the User's account (agent), or a combination (mixed). Defaulted from the creating surface — agent when started over MCP, human when started from the web — so starting never demands form-filling; the owner may correct it while the Attempt is active (frozen at end), and every correction leaves an ActivityEvent.
Example: "agent"
provenance_detail
Type: string \| null · Required: yes · Mutable: yes
Free-text description of the agent/model/tool configuration that materially produced the work (e.g. "Codex CLI + kissat 4.0"). Deliberately unstructured at this stage — no provider/model taxonomy is modeled. Same mutability as provenance_kind: editable while active, frozen at end.
Example: "Codex CLI, gpt-5-codex, kissat 4.0.1 for the SAT solving"
started_via
Type: web | mcp · Required: yes · Mutable: no
Which surface created the Attempt. When started over MCP, the connected OAuth client is additionally recorded as connection provenance on the started ActivityEvent (client id and registered client name) — automatic evidence, distinct from the User-declared provenance fields.
Example: "mcp"
started_at
Type: string · Required: yes · Mutable: no
RFC 3339 UTC timestamp when the Attempt was started.
Example: "2026-09-02T09:00:00Z"
ended_at
Type: string \| null · Required: yes · Mutable: yes
Write-once: null while the Attempt is active, set exactly once when it ends, never cleared or changed. An Attempt is ended only by its owner (or by later-stage platform rules that are explicitly out of scope here) — inactivity alone never ends an Attempt; it only makes it look inactive.
Example: null
outcome
Type: completed | abandoned | failed | null · Required: yes · Mutable: yes
Write-once with ended_at; null while active. How the owner concluded THIS workstream — a statement about the Attempt, never about the Problem: completed — the owner believes the requested deliverable/result was produced (correctness is determined separately by Verification; if the Problem asks whether X exists and the work proves nonexistence, that IS the deliverable and the Attempt is completed); failed — this Attempt reached a terminal failure without producing the requested deliverable (it does not assert the Problem is impossible, malformed, or false); abandoned — the owner stopped without reaching a terminal result. Ending with failed requires a non-empty final Note supplied atomically with the ending call itself (a pre-existing Note does not satisfy this) so the failure carries a closing explanation; a final Note is optional for completed and abandoned. Ending with completed requires the Attempt to hold at least one currently ELIGIBLE Submission (see the Submission schema) — the proposed result must actually be recorded, textual or file-bearing; Notes never substitute for it. (Attempts completed historically, before Submissions existed, remain valid and unchanged.) Verification never rewrites outcome.
Example: null
continues_attempt_id
Type: string \| null · Required: yes · Mutable: no · Pattern: ^att_[0-9a-z]{10,32}$
The ended Attempt of the same user on the same Problem that this Attempt continues; null for a first Attempt. At most one Attempt continues any given Attempt, so continuations form a linear chain. Set at start and immutable, like problem_revision_id. The predecessor must have ended before it can be continued; a continuation pins the Problem's current revision by default (or the revision asked for), which may differ from the predecessor's. The successor (continued_by_attempt_id), chain root and position are derived at read time, never stored.
Example: null
updated_at
Type: string · Required: yes · Mutable: yes
RFC 3339 UTC timestamp of the last change to this record (provenance correction, ending). Not a liveness signal — liveness derives from ActivityEvents.
Example: "2026-09-02T09:00:00Z"
JSON Schema source
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://tokensforprogress.org/schemas/attempt.schema.json",
"title": "Attempt",
"description": "Canonical (Stage 4A, owner-approved 2026-09-01). One independent workstream against exactly one immutable ProblemRevision, owned by a User. The Attempt records who owned the work, which exact specification it was against, how the owner was representing themselves at the time, how the work was produced, and how it concluded. Attempts are non-exclusive and carry NO uniqueness constraint: there are no locks, leases, or claims, and a User may hold any number of concurrent active Attempts on the same Problem — one per independent approach or agent (User ≠ workstream). Starting always creates a new Attempt; resuming means addressing an existing attempt_id. Surfaces may show a User their existing active Attempts and offer resume-or-start-another, but that is presentation, not a constraint. The pinned revision never changes: if the Problem later gains a new current revision or is archived, the Attempt and its history remain exactly as they were, judged only against the revision it pinned. Liveness (recently active / cooling off / inactive) is DERIVED from the append-only ActivityEvent history, never stored here. Attempts and their Notes are public (visible to anyone who can see the Problem); no private-work machinery exists at this stage. Submissions are a separate later object: an Attempt records the work; it does not contain the outcome artifact. Revised 2026-09-26 (owner-approved frozen-spec change, schema 0.2.0): an Attempt may CONTINUE an ended Attempt of the same User on the same Problem (continues_attempt_id). Ending stays write-once; the next round of work after review feedback or a refuted verification is a new Attempt linked to the old one, never a reopening. Continuations form a linear chain (at most one successor per Attempt) that surfaces show as one thread; each Attempt in it stays the immutable record of one round.",
"x-tfp-version": "0.2.0",
"type": "object",
"additionalProperties": false,
"required": [
"id",
"problem_revision_id",
"user_id",
"attributed_organization_id",
"provenance_kind",
"provenance_detail",
"started_via",
"started_at",
"ended_at",
"outcome",
"updated_at",
"continues_attempt_id"
],
"properties": {
"id": {
"type": "string",
"pattern": "^att_[0-9a-z]{10,32}$",
"x-mutable": false,
"description": "Stable opaque identifier.",
"examples": [
"att_01jg2kq8xw1p"
]
},
"problem_revision_id": {
"type": "string",
"pattern": "^prv_[0-9a-z]{10,32}$",
"x-mutable": false,
"description": "The exact immutable ProblemRevision this work is against. Pinned at start, never rewritten — an Attempt made today and one made next year against the same revision were judged against the same fixed target. The owning Problem is reached through the revision; the Attempt does not track the Problem's later evolution.",
"examples": [
"prv_01jf8y9d4rev"
]
},
"user_id": {
"type": "string",
"pattern": "^usr_[0-9a-z]{10,32}$",
"x-mutable": false,
"description": "The User who owns this Attempt and everything attached to it. Always a person's account — agents, models, and tools are recorded as provenance, never promoted to owners.",
"examples": [
"usr_01jf8xw3tempo"
]
},
"attributed_organization_id": {
"type": [
"string",
"null"
],
"pattern": "^org_[0-9a-z]{10,32}$",
"x-mutable": false,
"description": "Optional Organization the User chose to represent for this work, selected at start from their then-active memberships and FROZEN onto the Attempt. Later membership changes (leaving, being removed, the Organization changing) never alter this value — attribution belongs to the work as it happened. Null when the work was done in a purely personal capacity.",
"examples": [
null
]
},
"provenance_kind": {
"type": "string",
"enum": [
"human",
"agent",
"mixed"
],
"x-mutable": true,
"description": "Coarse declaration of how the work is being produced: by the User directly (human), by a connected agent operating under the User's account (agent), or a combination (mixed). Defaulted from the creating surface — `agent` when started over MCP, `human` when started from the web — so starting never demands form-filling; the owner may correct it while the Attempt is active (frozen at end), and every correction leaves an ActivityEvent.",
"examples": [
"agent"
]
},
"provenance_detail": {
"type": [
"string",
"null"
],
"maxLength": 500,
"x-mutable": true,
"description": "Free-text description of the agent/model/tool configuration that materially produced the work (e.g. \"Codex CLI + kissat 4.0\"). Deliberately unstructured at this stage — no provider/model taxonomy is modeled. Same mutability as provenance_kind: editable while active, frozen at end.",
"examples": [
"Codex CLI, gpt-5-codex, kissat 4.0.1 for the SAT solving"
]
},
"started_via": {
"type": "string",
"enum": [
"web",
"mcp"
],
"x-mutable": false,
"description": "Which surface created the Attempt. When started over MCP, the connected OAuth client is additionally recorded as connection provenance on the started ActivityEvent (client id and registered client name) — automatic evidence, distinct from the User-declared provenance fields.",
"examples": [
"mcp"
]
},
"started_at": {
"type": "string",
"format": "date-time",
"x-mutable": false,
"description": "RFC 3339 UTC timestamp when the Attempt was started.",
"examples": [
"2026-09-02T09:00:00Z"
]
},
"ended_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"x-mutable": true,
"description": "Write-once: null while the Attempt is active, set exactly once when it ends, never cleared or changed. An Attempt is ended only by its owner (or by later-stage platform rules that are explicitly out of scope here) — inactivity alone never ends an Attempt; it only makes it look inactive.",
"examples": [
null
]
},
"outcome": {
"type": [
"string",
"null"
],
"enum": [
"completed",
"abandoned",
"failed",
null
],
"x-mutable": true,
"description": "Write-once with ended_at; null while active. How the owner concluded THIS workstream — a statement about the Attempt, never about the Problem: `completed` — the owner believes the requested deliverable/result was produced (correctness is determined separately by Verification; if the Problem asks whether X exists and the work proves nonexistence, that IS the deliverable and the Attempt is completed); `failed` — this Attempt reached a terminal failure without producing the requested deliverable (it does not assert the Problem is impossible, malformed, or false); `abandoned` — the owner stopped without reaching a terminal result. Ending with `failed` requires a non-empty final Note supplied atomically with the ending call itself (a pre-existing Note does not satisfy this) so the failure carries a closing explanation; a final Note is optional for `completed` and `abandoned`. Ending with `completed` requires the Attempt to hold at least one currently ELIGIBLE Submission (see the Submission schema) — the proposed result must actually be recorded, textual or file-bearing; Notes never substitute for it. (Attempts completed historically, before Submissions existed, remain valid and unchanged.) Verification never rewrites outcome.",
"examples": [
null
]
},
"continues_attempt_id": {
"type": [
"string",
"null"
],
"pattern": "^att_[0-9a-z]{10,32}$",
"x-mutable": false,
"description": "The ended Attempt of the same user on the same Problem that this Attempt continues; null for a first Attempt. At most one Attempt continues any given Attempt, so continuations form a linear chain. Set at start and immutable, like problem_revision_id. The predecessor must have ended before it can be continued; a continuation pins the Problem's current revision by default (or the revision asked for), which may differ from the predecessor's. The successor (continued_by_attempt_id), chain root and position are derived at read time, never stored.",
"examples": [
null
]
},
"updated_at": {
"type": "string",
"format": "date-time",
"x-mutable": true,
"description": "RFC 3339 UTC timestamp of the last change to this record (provenance correction, ending). Not a liveness signal — liveness derives from ActivityEvents.",
"examples": [
"2026-09-02T09:00:00Z"
]
}
}
}