material_change asks whether an edit to a contract section changed what the parties must do. Your legal team reviews the edit to section sec_118 and finds that it changed the payment terms. You post true as the outcome for sec_118.
Outcomes are data. Brussle keeps each one beside the exact answer it measures, which names its document revision, judgment version and engine version. Each outcome counts for the judgment version and engine epoch of the answer it joins. There are two kinds:
- Labelled examples: a person’s answer to the question for a document, as of a time. Use them to measure a judgment before you rely on it. This page shows how.
- Results that come later: what happened after the answer, such as “this invoice went overdue”. These need a
horizonon the judgment. See outcomes that arrive later.
Post labelled examples
A labelled example is an outcome on a judgment with the defaulthorizon of 0s. It records what was true of the document at observed_at.
- Write the documents.
- Post their labels to
POST /namespaces/{ns}/outcomes.
value is what was true of the document at observed_at:
How a label joins its answer:
- It joins the answer for the revision that was current at
observed_at. A label that you post before that answer exists still joins it when it arrives. - A label observed while its document was deleted joins nothing, because no revision was current. A document that you write again remembers the last 8 deletions of its
id, so this holds however late you post the label, as long as the deletion is still recorded when you post or read the label, or when you write theidagain. - An answer keeps one label. A later label for the same answer replaces the earlier one in the correction, the report and the recommender: the label with the latest
observed_atcounts, and of two with the sameobserved_at, the one you posted last. A document that you label each period without a change counts once. Brussle still stores every label, and the report counts the replaced ones inunmatched_outcomes.same_window. A labelling-queue label is counted apart: an answer also keeps one queue label. - Outcomes are append-only, and retries are safe. The same document, judgment, value and
observed_atis stored once. - Outcomes belong to a namespace. Post them on the namespace’s own path, never on a template prefix.
- Errors. A value that does not fit the judgment’s type is
invalid_request. An unknown judgment isnot_found. A post is at most 2 MB.
Upload labels as a CSV
- In the dashboard, open the judgment.
- Go to its Labels tab.
- Upload a CSV with the header
document_id,value, and optionally anobserved_atcolumn in RFC 3339:
observed_at uses the time of the upload.
Correct an outcome
Post the correct value as of now. If the document has not changed, the correction joins the same answer and replaces the earlier label.- A correction must differ. Its value or its
observed_atmust differ from each earlier outcome of its document. The same value at the same time again is a retry, stored once at its first place. To set an outcome back to an earlier value, use a newobserved_at. - Date it now, not in the past. The correction and the report keep the label with the latest
observed_at, and so does a relation that reads the outcome. Brussle keeps a correction dated before the outcome it corrects, but a relation never reads it. - On a rule’s outcome, a posted outcome always wins in its answer or window. Post one to correct a rule by hand.
Record outcomes from your own writes
Most outcomes already reach you as ordinary writes: a ticket closes with the team that handled it, your team records which invoice a payment settles, a moderator reverses a removal. Outcome rules turn those writes into outcomes, so you get labels without posting them. A rule watches one path on the judged document. When a write changes the path to the value you name, that write is an outcome. Set rules withPATCH /namespaces/{ns}/judgments/{name}, under outcomes.
Triage. A choice judgment routes tickets to a team. When a ticket closes, the team that closed it is the right answer. from takes the outcome from the document after the write:
settles judgment chooses which open invoice a payment settles. When your team records the match in state.settles, the invoice it names is the right answer. on fires when the path gets a value for the first time:
bool judgment asks “does this post break the rules?”, and its answers cause removals. A reversed removal means the answer was wrong. An upheld removal means it was right:
How a rule fires
- Each rule has
whenoron.when.pathisattributes.<name>orstate.<key>[.<key>...]on the judged document itself: for a judgment with relations, the payment, not a related document.becomesnames one value.innames up to 16.onnames one path, and fires when its value changes from missing ornullto any other value. - It fires on the write that changes the value to that value, or into the list, from any other value. A write that keeps the value fires nothing, so an unrelated edit, a repeated sync or a retried request adds no second outcome.
- A delete never fires. A write that creates the document fires if the document has the value when it is created.
valueis the outcome:trueorfalsefor abool, an option for achoice, a level for ascore. Abooltakes onlyvalue.from(choiceandscoreonly) takes the value at that path after the write. If that value is not an option or level, or the path is missing, Brussle keeps the outcome but it counts nowhere: the report counts it inunmatched_outcomes.does_not_fit. Use that count to find a rule that points at the wrong field.- A value that changes back and forth fires each time it arrives. A status that goes overdue, then open, then overdue again gives two outcomes. On a judgment with a horizon, two outcomes in one window still count once.
- They join as posted outcomes do, and the report counts them as
ruleinoutcomes_by_source. - A posted outcome wins when you post one and a rule makes one for the same answer or window.
- With the default
0shorizon, a rule outcome joins the answer to the document as it was immediately before the write that fired the rule. That answer is the one the write responded to, not the answer the write itself causes. - Its
observed_atis the time the write was committed.
Rule limits
- Plans. Outcome rules are on the Team plan and above. Below Team, a
PATCHthat setsrulesreturnsplan_required, and one that clears them ("rules": []) always works. After a downgrade takes effect, rules keep running, but the correction leaves out what they make from then on: the report counts those outcomes inrule_outcomes_paused, and the dashboard’s Calibration section shows the count. Outcomes collected before stay in use. After an upgrade, new rule outcomes count again. See plans. - Up to 4 rules for each judgment, each on one path. Each
PATCHreplaces the wholeoutcomesobject, so sendimplicit_negativesand every rule together. - Rules apply from when you set them. Brussle does not replay earlier writes. To label the past, post outcomes for it.
- Rules read only the judged document’s own writes. A write to a payment is not an outcome for the invoice it settles. Post that outcome yourself.
- Templates. Neither a namespace that gets a judgment from a template nor the template’s prefix path can set rules. Set rules on a namespace’s own judgment.
- Errors. A rule that does not fit the judgment’s type, such as
fromon abool, and a fifth rule areinvalid_request, with the rule and the reason. - Features. A feature cannot read a path that a rule reads, because that path holds the outcome.
Post what did not happen too
Most teams record what happened: the payment was refunded, the match was reversed. Few write down what did not happen. The correction needs both: at least 15 of each kind, and the recommender 20.- For labelled examples, label documents where the answer is “no”, with
"value": false, as well as “yes”. - For results that come later, post
falsewhen an answer’s window passed without the event, or turn on implicit negatives when no outcome really means “no”.
Label more than the reviewed documents
Outcomes usually come from documents that someone already looked at, and people look at the documents that crossed a threshold. Then almost all outcomes sit on answers with a high raw probability, the fit has nothing for the rest of the range, and its corrected numbers for low-probability answers are a guess. The report warns about this for each epoch, inwarnings:
above_thresholds: more than 80% of the outcomes are on answers that meet one of the judgment’s thresholds.high_band: on abool, more than 80% of the outcomes are on answers withpof 0.7 or more.
coverage gives the lowest and highest raw value the outcomes cover, and the reliability curve shows how many outcomes fall in each band.
What to do: label a random sample of documents as well. The labelling queue draws one for you. Keep labelling the reviewed documents too; both count.
Outcomes that other judgments read
Outcomes also feed relations. Another judgment can read the newest outcome of a related document as a fact in its context. For example, a judgment on a customer can read whether the customer’s past orders were refunded.- A relation reads the outcome with the latest
observed_at. See correct an outcome. - Outcomes posted before relations could read them, including one posted before this feature existed and one posted for a document that did not exist yet: a relation reads such an outcome for the document’s current life only if no deletion of the document is recorded at or after its
observed_at. A document remembers the last 8 deletions of itsid, so a later life of a document deleted long ago can read such an outcome.
Outcomes that join nothing
Brussle keeps an outcome that joins no answer, and it counts if a later answer takes it. The report counts these inunmatched_outcomes, by reason: