Skip to content

Undo a rule change (restore the prior version)

POST
/v1/rules/audit/{udo_id}/undo

Restore the prior version recorded in an audit row (D11; agents may undo too). UNDO = a NEW forward supersession that re-inserts the before snapshot as the new active head (action=‘restore’); the source audit row is marked undone. Idempotent: a re-undo of an already-undone row is a clean 409. Safe under concurrent edits (the restore CASes on the lineage head). The udo_id is an AUDIT row id, hence the nesting under the audit subtree.

udo_id
required
string

Ok

A learned writing rule (rule_…) in the Review Loop (D2/D11). House-style/ general (scope=‘general’, applies across all categories) or category-scoped. Append-only by supersession: an edit is a new rev (same lineage_id) with the prior flipped to superseded. Read by the agent at compose/redraft time via the ordered get_rules ladder; we never apply it. Opaque ids only (D10).

object
id
required

Opaque rule id (rule_…).

string
rule_layer

Ownership layer (org/project model). org = house-style inherited by every project in the org; project = layered on top (the agent-plane default). Project/per-agent rules outrank broader org rules in the ordered get_rules ladder.

string
Allowed values: org project
org_id

The org this rule belongs to.

string
project_id

The project this rule belongs to; empty for an org-layer rule.

string
lineage_id
required

Stable lineage handle across versions (rln_…).

string
rev
required
integer
scope
required

General = house-style (D2).

string
Allowed values: general category
category_id

Set iff scope=category (cat_…).

string
scope_agent_id

Set for a per-agent override; empty = all org agents.

string
rule_text
required
string
kind
required

Hard = non-overridable.

string
Allowed values: soft hard
priority
required
integer
status
required
string
Allowed values: proposed active superseded retired
supersedes_id

The prior rev this row superseded (rule_…).

string
author_kind
required
string
Allowed values: agent human
created_at
required
string format: date-time
updated_at
required
string format: date-time

Invalid request.

The canonical error envelope. error is a stable machine code.

object
error
required

Stable error code (e.g. unauthorized, forbidden, not_found, invalid, quota_exceeded, rate_limited).

string
Example
forbidden
message

Human-readable detail (never leaks internals).

string
Example
missing required scope

Missing or invalid credential.

The canonical error envelope. error is a stable machine code.

object
error
required

Stable error code (e.g. unauthorized, forbidden, not_found, invalid, quota_exceeded, rate_limited).

string
Example
forbidden
message

Human-readable detail (never leaks internals).

string
Example
missing required scope

Authenticated but lacking the required scope, or out of quota.

The canonical error envelope. error is a stable machine code.

object
error
required

Stable error code (e.g. unauthorized, forbidden, not_found, invalid, quota_exceeded, rate_limited).

string
Example
forbidden
message

Human-readable detail (never leaks internals).

string
Example
missing required scope

Resource not found.

The canonical error envelope. error is a stable machine code.

object
error
required

Stable error code (e.g. unauthorized, forbidden, not_found, invalid, quota_exceeded, rate_limited).

string
Example
forbidden
message

Human-readable detail (never leaks internals).

string
Example
missing required scope

A Review Loop conflict, as problem+json. Branch on code, NOT on the 409 status; the four codes demand opposite behavior. stale: the revision/version you named is no longer current (a human moved the draft) and NOTHING was mutated; errors[] carries the current state, revision and version, so re-apply your change on top and resubmit with the new parent_revision (retry, bounded to ~3). born_stale: the redraft was built against an older rule high-water; re-read the rules and resubmit, or restamp_review if nothing genuinely changed (at most one retry per high-water). wrong_state: this VERB is illegal from the current state but the draft is still live; NEVER retry the same verb; errors[] repeats an allowed_action entry per verb that IS legal right now. terminal: the review is already sent/auto_sent/cancelled; nothing will ever succeed, stop retrying, and a front_run_next review event carries the outcome. send_needs_reconciliation: a prior attempt is unconfirmed and parked for recover-by-Message-ID; do NOT resend, poll the review.

RFC-9457 problem+json error body. code is a closed machine enum clients switch on; type is a dereferenceable URI under https://extrovert.dev/problems/. Served as application/problem+json.

object
type
required
string format: uri
title
required
string
status
required
integer
detail
string
code
required

The CLOSED machine code. The Review Loop members split what used to be a single opaque conflict, because an agent must take a DIFFERENT action on each: stale (the revision/version you named is no longer current; nothing was mutated; re-read, re-apply, resubmit; retryable, bounded) and born_stale (built against an older rule high-water; re-read the rules or restamp_review; at most one retry per high-water) are the ONLY retryable 409s. wrong_state means this VERB is illegal from the current state while the draft is still live; never retry the same verb, read the state and the repeated allowed_action hints in errors[] and pick a legal one. terminal means the review is already sent/auto_sent/cancelled and nothing will EVER succeed; stop, and drain your review events for the outcome. send_needs_reconciliation means a prior send is unconfirmed and parked. Do not resend. Poll instead. unavailable (503) is the retryable fail-closed answer when a dependency could not be read; it carries Retry-After and is distinct from not_configured, which is permanent for this deployment.

string
Allowed values: bad_request unauthorized forbidden_scope not_found conflict idempotency_conflict breadth_required quota_exceeded rate_limited domain_not_allowed recipient_blocked recipient_suppressed not_configured domain_unavailable internal intent_required wrong_state terminal stale born_stale send_needs_reconciliation graduation_locked maturity_gate_unmet scope_taken unavailable
request_id
string
errors
Array<object>
object
field
string
code
string
detail
string