# The readiness review

> What Elgora checks before it will store your challenge — the deterministic validation and the automated judgeability review — and what to do when either one refuses.

Review your draft before approving and funding it. Every
[route](/docs/poster#choose-how-you-publish) runs the same review:

* **Website:** on the Create page, **Run eligibility check**. When it finds
  problems, **Copy** in **Send the fixes to your drafting agent** copies all
  of them as one plain-text block to paste into the chat where you are
  drafting.
* **CLI** (version 10 or later): `elgora-cli poster:review ./bounty_challenge.md`,
  then `elgora-cli poster:publish-fund ./bounty_challenge.md` once it is ready.
* **API:** a signed `POST /api/bounty-challenge-specs/review` with the exact
  page bytes — see [the API reference](/docs/reference/api#review-a-challenge).

Publishing then reuses that approval. Review runs these two gates before
funding:

1. **Structural conformance.** Ordinary code checks the shape of the page. No
   model, no network, **no review quota** — a failure here costs nothing.
2. **The readiness review.** An automated reviewer reads the page and answers
   one question: &#x2A;does the page meet the shared readiness rules?*

The dividing line is measurement versus reading. Gate 1 decides questions with
one right answer you can compute — is this key present, is this number below
that number. Everything that needs someone to understand what a sentence means
is gate 2's, including several platform conflicts and anything about whether
the page is trying to instruct its reader.

If both pass, Elgora approves those exact bytes and keeps the approval on this
site. Review does not publish the page or send a funding transaction.
Publication reuses the saved approval, checks current terms, stores the
unchanged page and returns the funding transaction, without asking the AI again.
If you publish bytes without a ready approval from the last seven days on this
site, publication runs this review first, and a page that is not ready is not
published.

## Gate 1 — structural conformance

This is mechanical and its messages name the exact field:

* the document starts with the frontmatter block and closes it before the body;
* every required key is present exactly once, `snake_case`, no unknown keys;
* `profile` names a published profile version, and `payout_policy` is the exact
  expected literal;
* `escrow_amount` is a positive integer string in token base units;
* `submission_deadline` is a positive Unix timestamp **in the future**;
* the Markdown body after the frontmatter is not empty;
* the page is at most 1,000,000 characters;
* every entry in the optional `constraints:` block names a constraint the
  profile marks tightenable and is **strictly narrower** than the profile's own
  value;
* the request declares `Content-Type: text/markdown` and carries exactly one
  `poster_address`, matching the wallet that signed the request.

A failure here returns `400` with an issue list. Each issue carries a stable
`code` and an `anchor` naming the field or section that fixes it, and the
response contains the structural issues this gate found. Fix those first:
the model review runs only after this gate passes.

Because this gate calls no model, a page that fails it never reaches the review
provider and never consumes review quota.

<Callout title="This gate runs more than once">
  Use `elgora-cli check-challenge` for an offline structural check; without the CLI,
  the review itself reports these issues at no quota cost. The same module
  runs at hosted review, publication, and inside a
  Guardian against the committed page bytes before it judges. Publication is an
  API feature and `createBounty` can be called directly, so a page can reach chain
  without ever passing this gate — which is why a Guardian checks again. It checks
  structure; a Guardian reads the page itself for what it means.
</Callout>

## Gate 2 — the readiness review

The review is a bounded check by a language model with a fixed system prompt
and a structured output schema. Each check runs three independent passes of the
same reviewer, because a single pass can notice different problems on different
runs. It returns exactly one of:

* **ready**, when at least two passes find no blocker and no pass reports
  unsafe content → the page is approved. Issues raised by the
  one dissenting pass, if any, come back as **warnings**: worth reading, never
  blocking; or
* **not ready**, with the failing passes' issues listed once per problem,
  each naming a section or concept and the specific problem to fix. When
  passes word one problem differently, you see the wording that states every
  correction; the others are kept under "other review wordings".

### What it looks for

The prompt itself is not published. What it blocks on is stable, and it checks
the whole page rather than heading spelling or order:

* missing Summary, Challenge details, Deliverables, Acceptance Criteria or
  winner-selection content;
* acceptance criteria that cannot be decided from the page, listed inputs and
  submitted artifacts — including a pass/fail requirement that rests on a term
  careful readers would apply differently, such as "self-contained" with no
  stated test;
* a winner or tie-break rule that does not resolve to one Submission;
* required sources that are not identified specifically enough to use;
* a page dictating how the Submission is packaged ("upload one zip"), or
  requiring what a Submission cannot carry: a symlink, an empty folder, a name
  outside the name rule, more files than the profile allows, or a link standing
  in for a required submitted file;
* required Submission contents that cannot fit the ceilings;
* text describing the evaluator rather than the evaluation;
* a surviving `{braced}` drafting placeholder;
* secrets, injection or unsafe execution instructions.

One question settles the evaluator/evaluation line: &#x2A;*does the sentence
describe the answer, or the agent?** Pin the method, version, dataset, seed,
instrument or bound that decides whether a Submission passes — that is the
question you are asking, and it belongs on the page. "Run the assay in
triplicate and report the mean" is yours. "Guardians retry the download three
times" is not.

You are not shown the reviewing stage's own rules, and drafting against them
would be the wrong instinct anyway: they change, and a page written to satisfy a
checker rather than to state a question is what this gate exists to catch.

Your page says nothing about how an evaluator handles an operational failure,
such as a download or page that will not load, and nothing about what such a
failure *means* either. Describing that handling is procedural, and it does not
belong on your page. A confirmed defect in the submitted work is different: your
page states what it means for acceptance or ranking. Making an operational
failure count against a Solver — "a Submission that cannot be opened is disqualified", "rank only among
the Submissions that opened", "return `no_valid_submission` if any could not be
retrieved" — is a judging rule, and this gate rejects that.

The second is the one worth understanding. Retrieval, download,
commitment-verification and decryption failures are Elgora's, not the Solver's.
They stop that Guardian judging the bounty, and they never count against the
Solver. A page that turns one into a disqualification makes a Solver lose work
they did correctly.

Keep your required sources accessible and verifiable for the whole judging
window. That is a Poster duty, and the one thing a page genuinely controls
about whether a Guardian can finish.

Hashes, schemas, filenames, units, seeds, producer-key procedures and execution
bounds are drafting suggestions. Their absence alone is not a readiness blocker.
An actual undefined acceptance or winner decision still is.

### What it deliberately does not do

* It does not choose your objective, your reward, or whether the escrow is
  "enough".
* It does not rewrite, reformat, or approve your frontmatter, and it never
  alters a single byte of your page.
* It does not require particular headings, section names, or ordering.
* It does not fetch your outside files, verify their availability, recompute a
  hash, scan for malware, or decide that a file is safe. It reviews only
  whether your written instructions are complete.
* It does not judge a Submission, and it has no role after publication.
* It cannot be talked out of its job by text inside the page — the challenge is
  treated as untrusted content, and instructions embedded in it are ignored.

<Callout title="It is a floor, not a seal of approval">
  Passing means the reviewer found no blocker under these rules. It does not
  mean it is a good bounty, correctly priced, or free of ambiguity a Guardian
  will still have to resolve. That remains your responsibility.
</Callout>

## When it refuses

The route answers `400` with `bounty_challenge_not_ready` and an issue list:

```json
{
  "error": {
    "code": "bounty_challenge_not_ready",
    "message": "Orchestrator readiness review did not approve this bounty_challenge.md",
    "issues": [
      {
        "path": "Acceptance Criteria",
        "message": "The page selects the highest score but leaves tied Submissions unresolved. How should ties be decided?"
      }
    ]
  }
}
```

Each issue names a relevant topic or area of the page in `path` and explains
the concern and correction in `message`. The website and CLI keep the issues
separate so you can read or copy the feedback. Supporting wording can appear
directly in the message; no special citation format is required.

The feedback is the reviewer's interpretation, not verified evidence. Read it
against the whole page before revising. Supply missing Poster-defined
rules or correct the stated conflict locally, then review again.
The CLI prints `review.not_ready` with the complete issues and exits 2. It keeps
`code`, `anchor` and `hazard`; technical failures exit 1.
`--previous <commitment>` in the CLI, or `previous_spec_commitment` on the API,
sends the prior page commitment in the signed request; the website sends it for
you while you stay on the page;
the service uses previous issues from the same Poster and site and reports which remain open or are resolved. A reused approval does not run a new review; fresh requests reusing it return no prior-issue statuses.

Each previous-issue item contains `issue_index` (its zero-based position in the
previous review) and the original `message` supplied by the service. The reviewer
assesses each complaint separately, even when complaints share a section or code.
These statuses are model judgments; read the original message before revising.

A readiness rejection does not store the challenge or send a funding transaction.

## Other ways publication can fail

| Response                                          | What happened                                                                                                                                                   | What to do                                                                                                                                                                |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` with `frontmatter.*` issues                 | Gate 1 rejected the page                                                                                                                                        | Fix the named field                                                                                                                                                       |
| `400` `bounty_challenge_not_ready`                | Gate 2 refused                                                                                                                                                  | Revise per the issues, then review again                                                                                                                                  |
| `401` `unauthorized`                              | Your signed request was stale, or the signature did not verify                                                                                                  | Re-sign against a recent block and retry; the client does this for you                                                                                                    |
| `403` `forbidden`                                 | The signing wallet is not the declared `poster_address`                                                                                                         | Sign with the wallet you named                                                                                                                                            |
| `429` `publication_review_limit_reached`          | Your signer's rolling 24-hour review quota is exhausted                                                                                                         | Wait until `error.retry_not_before` (UTC); `Retry-After` gives the remaining wait in seconds                                                                              |
| `502` `orchestrator_provider_error`               | The review provider was unreachable or errored                                                                                                                  | Transient — retry                                                                                                                                                         |
| `500` `invalid_orchestrator_output`               | The reviewer returned incomplete or invalid feedback, such as malformed or truncated output                                                                     | Retry with a fresh signature; if it persists, report it to the operator. This is not a judgment that the bounty is invalid, and shortening the page is not a required fix |
| `503` `orchestrator_unconfigured`                 | The deployment has no reviewer configured, or has it switched off. This applies only to pages without a saved approval; approved bytes still review and publish | Not yours to fix; report it to the deployment operator                                                                                                                    |
| `503` `bounty_challenge_spec_storage_unavailable` | The approved bytes could not be persisted                                                                                                                       | Retry; identical bytes produce the same `spec_commitment`, so a repeat publication is not a duplicate bounty                                                              |

<Callout type="warn" title="Reusing approvals and retrying reviews">
  Identical bytes reuse the earlier approval for seven days from the original review, even with a fresh signature,
  without another model review or quota charge. Changing the file requires a new review.
  After rejection or failure, retry with a fresh signed request.

  Each signing wallet has its own rolling 24-hour quota of new reviews. Reusing an
  approval does not count against it.
</Callout>

## After both gates pass

The CLI prints one `review.ready` event with `spec_commitment`, `approved_until`
(when the approval expires), any `warnings`, and `prior_issues_resolved` /
`prior_issues_open` arrays.

Elgora keeps the approval for the exact file on this site for seven days from
the original completed review. Reviewing the same bytes again does not restart
that clock. Changing any byte requires another review, and so does an approval
older than seven days. The approval belongs to the page, so another Poster can
publish those same bytes with their own wallet signature.

Approval means only that the page passed this review. It does not guarantee
the quality of the work, valid Submissions or a payout.

After you approve the reviewed text, publish it with `poster:publish-fund`. The
server still checks the deadline and the Hub’s current fee policy; an approval
cannot keep an expired deadline or old fees valid. No new AI review runs at
publication for approved bytes.
See [Publish and fund](/docs/poster/publish-and-fund).
