RFC 0016: Outcome values — a decision that states a quantity
On this page
- Status: Draft
- Type: Standards-track (candidate specification-defined extension, or Core amendment — undecided)
- Created: 2026-09-28
This is an open proposal, not part of the specification. See RFC 0000 for the process and evidence bar. Two prototypes implement it, each behind an opt-in, and no conformance class depends on any of it.
Summary
An outcome may declare values: named members, each either a constant the author wrote or a copy
of one fact. Each has a declared type: string, decimal or boolean. When evaluation produces
that outcome, the disposition carries the values. When a value is drawn from a fact and the fact
cannot supply it, no outcome is produced: the result is unresolved with reason unknown.
Nothing is calculated, and no condition operator is added. A value names no tool and is not an instruction. The proposal does change one thing about what is decided: a declared value that cannot be supplied withholds the outcome that declares it.
Problem
Core's outcome is an identifier and a label (§6.4), and the disposition names one outcome (§8.3). That is enough when the answer is a category. Many decisions are about a quantity — a limit granted, an amount approved — and for those the result leaves the quantity out. Two cases recur.
A quantity chosen from authored tiers. "A score of 720 or more is granted a limit of 10,000; 650 to 719, a limit of 5,000." A pack can declare one outcome per tier. The number each tier means is then kept by the consumer, in a table from outcome identifier to quantity that is no part of the pack. The pack is not the whole policy, and two consumers may hold different tables for the same pack.
A quantity passed through. "Approve the proposed refund when it is 200 or less." The pack
compares the fact /proposed/refundAmount with "200" and produces approve. Which quantity was
approved is for the consumer to work out from its own copy of the facts, and the pack does not say
which fact that is. A rule that reads the quantity can refuse to decide without it, by
onUnknown: escalate. Nothing ties the quantity to the outcome itself: an outcome reached through a
forced outcome, through fallbackOutcome, or through a rule that reads other facts is produced
whether or not the quantity is present.
The affected users are pack authors, who cannot write the quantity where the policy is; consumers, who rebuild it outside the portable result; and readers of a decision record, who see that something was approved and not how much.
This RFC is not about calculated quantities. Core compares facts and does not calculate (RFC 0007), and nothing here changes that. A quantity that is calculated is prepared before evaluation and arrives as a fact; this proposal lets the result state it once it has.
Evidence
The evidence is thin, and this section says how thin.
- Two of the repository's five example packs decide over a quantity and state none.
minimal-expense-approval.jsoncompares/expense/amountwith"5000", andsupplier-invoice-approval.jsoncompares/invoice/variancePercentwith"2.5". Where either produces an outcome, the disposition names a category, such asapproveormanual-review, and does not carry the quantity compared. These packs were written by the project as illustrations. They show the shape of the gap, not how often real policy has it. - Core anticipates the need. §2.2 says that "exact decimal quantities outside ordered fact-condition operands require a future profile or declared extension."
- No study measures this. RFC 0007's figures are about what a pack could not decide. They are not evidence about what a result should state, and this proposal does not rest on them.
- A construct with a similar name is a different one. RFC 0002 records that Study 004 of the research line named "outcome-value mapping" among the constructs implicated in its edge grammar's open items. That construct belongs to composition, where one decision's outcome feeds another's inputs. This RFC does not address it (see Unresolved questions).
- Two prototypes have run rows written from this document. Implementation says what exists and what building it found. That is experience of whether the text can be built. It is not evidence of need: every pack that was run was written for the test, and no use by an author is evidenced here.
The examples in this document were written for it.
Specification
The semantics below are stated once. How a pack carries the declaration — a specification-defined extension or a Core member — is an open question; the text uses the extension form, and Alternatives gives the other.
Declaration
An outcome declares its values under the extension name org.judgmentpack.outcome-values, in the
outcome's extensions object. A pack in which any outcome carries that name MUST list it in
metadata.requiredExtensions. The extension changes what evaluation produces, which §9 forbids an
optional extension to do.
As a member name of an extensions object, the name appears on an outcome and nowhere else. The
schema admits an extensions object on the root, the decision, a rule and other objects, and §9
asks only that a required name appear in some one of them. For this extension every such place
but an outcome is an error. Its entry in metadata.requiredExtensions is a separate matter, and
is required.
An extensions object, here, is one the schema defines as a member of those objects. A member
named extensions inside the value of another extension, or inside the operand of a condition, is
data. It declares no value, and it is no value for an entry of metadata.requiredExtensions.
The extension's value on an outcome is a non-empty JSON object, the value declaration. Each member name is a value name: one lowercase ASCII letter followed by zero or more ASCII letters or digits. The whole name is held to that, so a name that ends in a line feed is not a value name, whatever a pattern's end anchor would admit. Each member value is a value source: a JSON object with these members and no others.
| Member | Required | Value |
|---|---|---|
type |
yes | string, decimal or boolean |
constant |
one of the two | the value itself, of the declared type |
fromFact |
one of the two | an RFC 6901 JSON Pointer into the facts document, as fact.path is (§7.4) |
Exactly one of constant and fromFact is present. A constant of type string is a JSON
string that is a sequence of Unicode scalar values; of type decimal, a JSON string satisfying the
decimal grammar of §2.2; of type boolean, a JSON Boolean.
A JSON string may hold an unpaired surrogate, written as an escape such as "\ud800". Such a
string is not a sequence of Unicode scalar values and is not a string value. RFC 8785 cannot
serialize it, so admitting it would leave the disposition with no canonical form.
A pack that violates this section is not semantically conforming for a consumer that supports the
extension. That covers a malformed declaration, the name as a member of any extensions object
other than an outcome's, and a declaration in a pack that does not list the name as required. For an implementation claiming evaluator conformance this is the
pack-not-conformant error of §8.4. It is found in the preflight of §8.2, before step 1 of §8
runs, and so whether or not the outcome that carries the fault would have been produced.
A pack that lists the name as required while no outcome carries a declaration is in error too,
by one of two rules. Where the name is a member of some other extensions object, it is the rule
of place above. Where it is a member of none, it is §9's rule that a required name has a value.
The name is listed in metadata.requiredExtensions once, as the schema requires of every item of
that list.
{
"id": "approve-refund",
"label": "Approve the proposed refund",
"extensions": {
"org.judgmentpack.outcome-values": {
"refundAmount": { "type": "decimal", "fromFact": "/proposed/refundAmount" },
"currency": { "type": "string", "constant": "CAD" }
}
}
}
Resolution
Resolution runs once, after §8 has produced an outcome result, whether by a forced outcome
(step 6), by true rules (step 9) or by fallbackOutcome (step 10). It does not run for a
not-applicable or unresolved result. For an outcome that carries no value declaration it does
nothing, and the result is what §8 produced.
For the produced outcome, each value source resolves as follows.
- A
constantresolves to the constant. - A
fromFactselects a value from the facts document by the pointer rules of §7.4. It resolves if and only if the pointer resolves and the selected value is admitted by the declared type: a JSON string that is a sequence of Unicode scalar values forstring; a JSON string satisfying §2.2 fordecimal; a JSON Boolean forboolean. Any other selected value does not resolve. That includes a JSON number,null, an array, an object, a string holding an unpaired surrogate and, fordecimal, a string that does not satisfy the grammar.
A value is copied exactly as it was found. Nothing is coerced, trimmed or normalized: "0.10"
stays "0.10", and a JSON number is never turned into a decimal string.
Resolution selects from a facts document that the preflight of §8.2 has admitted. The rule
above, that a string holding an unpaired surrogate does not resolve, is a rule about a document
that was admitted. Whether a conforming evaluator admits such a document is a question this
proposal met and does not answer. The two prototypes differ on it: one admits the document, and
the other refuses it as malformed-input. RFC 8259's grammar admits the text, and RFC 8259 lets
a parser limit what a string may hold. Core takes its carrier from RFC 8259 (§2.1), says that two
conforming implementations agree on which inputs are admitted (§8.2), and names one seam in the
byte-identity requirement, which is not this one (§8.3). So this proposal does not say that
refusing the document is conforming, or that admitting it is, and it does not take the
difference for an exception Core allows. It is the ninth of the Unresolved questions and an
item under What this needs from Core.
If every value source resolves, the result is the outcome with its resolved values. If any does
not, the result is unresolved with the single reason unknown. No outcome is produced and the
disposition carries no value member, whether or not the other values resolved. The result is
final: fallbackOutcome is not tried in its place.
Handoff follows §8.1 as for any other unknown. It is requested exactly when the pack has an
escalation object whose triggers name unknown, and handoff.triggeredBy is then
["unknown"]. An implementation MAY name the value that did not resolve, outside the disposition.
The disposition
The disposition gains one member.
| Member | Present | Value |
|---|---|---|
value |
iff kind is outcome and the named outcome carries a value declaration |
a JSON object with one member per declared value name, each the resolved value |
Every member of value is a JSON string or a JSON Boolean. The object holds no number, no null,
no array and no nested object, so the number rules of RFC 8785 still never engage (§8.3). The
byte-identity requirement of §8.3 extends to value. The ninth of the Unresolved questions
is no exception to it: this proposal claims none, and one could come only from a decision of
Core's that is reconciled with §§8.2–8.4 and §10.
{"handoff":{"state":"none"},"kind":"outcome","outcomeId":"approve-refund","reasons":[],"value":{"currency":"CAD","refundAmount":"149.50"}}
What a value is not
- Not an instruction. A value names no tool and requests no action. Core's statement that an outcome is "not an authorization to perform an external action" (§6.4) covers its values, and a consumer MUST NOT treat a value as authorization.
- Not calculated. A value source is one constant or one fact. There is no arithmetic, no concatenation and no choice among facts.
- Not checked for range. Resolution admits any value of the declared type. A pack that must bound a quantity does so in its rules, as it does today.
- Not evidence of origin. A value drawn from a fact is as trustworthy as that fact. The disposition does not say where the fact came from.
What this needs from Core
- The schema refuses every name beginning
org.judgmentpack.in two places: as a member name of anextensionsobject, and as an item ofmetadata.requiredExtensions. Both would admit this one name, and both would go on refusing every other reserved name. - §8.3 gives the disposition "these members and no others", and names four. The proposal admits a fifth member name, present only under the condition in the table above.
- §9 reserves names beginning
org.judgmentpack.for "future specification-defined extensions" and defines none. This would be the first, and §9 would say where such an extension's semantics are found. - Core would say whether a facts document that holds a string with an unpaired surrogate is admitted. Whether the text is a carrier-conforming one and whether a facts document may hold it are two matters: §8.2 already holds the evidence-availability document to more than the carrier does. Approaches Core could take include these, and this proposal takes none of them:
- every conforming evaluator refuses such a facts document. For a conforming pack the answer
is then
malformed-input; - every conforming evaluator admits it. This proposal's row for such a fact is then
unresolved, where the string is selected for a declared value and nothing else stops the evaluation; - Core names what every evaluator admits and lets an implementation refuse the rest under a documented restriction. Core would then have to say which inputs are outside the portable claim. §10 puts outside it an input above an implementation's limit, and a restriction on what a string holds is not a limit of that kind until Core says it is.
This is a Core question beyond outcome values: it can change the answer for an otherwise conforming pack whose evaluation reaches facts preflight.
Examples
Tiers. Three outcomes; the first two carry the limit each one grants.
"outcomes": [
{ "id": "limit-high", "label": "Approve, high limit",
"extensions": { "org.judgmentpack.outcome-values": {
"creditLimit": { "type": "decimal", "constant": "10000" } } } },
{ "id": "limit-standard", "label": "Approve, standard limit",
"extensions": { "org.judgmentpack.outcome-values": {
"creditLimit": { "type": "decimal", "constant": "5000" } } } },
{ "id": "decline", "label": "Decline" }
]
Where the pack's rules produce limit-standard, the disposition carries
"value": {"creditLimit": "5000"}. Where they produce decline, it carries no value member.
Pass-through. Take a pack whose one rule produces approve-refund when
/customer/goodStanding equals true, whose approve-refund outcome carries the declaration
shown under Declaration, and which has no escalation object. The rule does not read the
amount, which keeps the example to resolution; a real pack would also bound it.
With facts {"customer": {"goodStanding": true}, "proposed": {"refundAmount": "149.50"}} the
result is the disposition shown under The disposition.
Now take /proposed/refundAmount absent, or given as the JSON number 149.5. The same pack
without the declaration and without its entry in metadata.requiredExtensions is a pack Core
admits today, and it produces approve-refund. With them, under this proposal, the result is:
{"handoff":{"state":"none"},"kind":"unresolved","reasons":["unknown"]}
A calculated quantity. "Refund pro rata, and send refunds above 500 to a supervisor." The
calculation happens before evaluation and its result is supplied as the fact /refund/amount. The
pack compares that fact with "500" and declares {"type": "decimal", "fromFact":
"/refund/amount"} on its approving outcome. What performed the calculation, and how a record
cites it, are outside Core.
Alternatives
- No change. Consumers keep tables from outcome identifier to quantity and read pass-through
quantities from their own copy of the facts. It costs nothing in the specification. The quantity
stays outside the portable result. A rule that reads the quantity can already refuse to decide
without it, by
onUnknown: escalate(§8, step 7), as both example packs do. Core has no requirement attached to the outcome itself, so a forced outcome,fallbackOutcomeor a rule that does not read the quantity produces the outcome without it. - One outcome per quantity. Expressible today, and sufficient for a small fixed set of tiers. It does not carry the quantity, and it cannot express pass-through at all.
- A Core amendment. The outcome object gains an optional
valuesmember with the same content, and §8 gains the resolution step. It is simpler to write. It also makes resolution part of §§7–8, which every implementation claiming evaluator conformance must implement in full (§3.4.1). - An optional extension. Not available. The proposal changes the disposition and can turn an
outcome into
unresolved, and §9 forbids an optional extension from changing Core semantics. - A profile. A separate document defining a conformance class over Core plus values. Heavier than an extension for one small capability, and profile negotiation is itself open (§13).
- Product-only behaviour. An implementation attaches quantities outside the disposition, in a trace or a record of its own. Two products would then state the same decision differently, which is the interoperability problem a portable result exists to prevent.
- Carry only values drawn from facts. §8.3 keeps the escalation target out of the disposition because "carrying a copy here would let a disposition disagree with the pack it came from." A constant is pack content in the same sense, and a consumer could read it from the pack. This RFC proposes carrying both, so that a consumer reads one member without knowing which kind it was. The narrower form is a real alternative, recorded under Unresolved questions.
- JSON numbers as values. Rejected. §2.2 exists because a number's decimal identity is not preserved, and a number in the disposition would bring RFC 8785's number rules into a comparison §8.3 keeps free of them.
- A calculation vocabulary. Out of scope. RFC 0007 lists a computation profile among its candidates and notes that it is the one most likely to reopen the non-goal of a general-purpose rules language.
- An outcome that names a tool to call. Rejected. Applying an outcome is outside Core (§3, §6.4).
Compatibility
- Readers. Under the current schema a pack using the reserved name is not structurally
conforming, so a consumer of
0.2.0-draftrefuses it. Once the schema admits the name, a consumer that does not support the extension reports it as §9 requires, and an implementation claiming evaluator conformance answersunsupported-required-extension(§8.4). Neither produces a disposition without the values. - Writers. Opt-in. A pack that declares no values is unchanged.
- Semantics. For a pack that declares no values, every disposition is byte-identical to the one
produced today. For a pack that declares a value drawn from a fact, an evaluation that would
have produced the outcome without the fact now produces
unresolved. That change is the purpose of the proposal. - Records. A format that stores a disposition whole stores the new member with it. A format that stores selected members of a disposition would have to decide whether to store this one.
- Migration. A pack with one outcome per tier adds a constant to each. Its outcome
identifiers, rules and existing dispositions'
outcomeIdare unchanged.
Security and privacy
- Disclosure. A disposition has so far held identifiers and reasons. With this proposal it can
hold a copy of a fact. A
stringvalue drawn from a fact may carry personal data into every place dispositions are stored or logged. Authors should draw the least they need, and implementations should treat a disposition carryingvalueas they treat the facts. - A quantity under a caller's control. Whoever supplies the facts supplies the quantity. Resolution checks its type, not its size. A pack that approves "the proposed amount" without a rule bounding it approves any amount.
- Confusion with authorization. A result reading
approvewith an amount beside it looks like a payment instruction. It is a declared result (§6.4). The risk is in consumers, and the text above states the prohibition. - Confusion about origin. A value in a disposition may be read as verified. It is copied, not verified. Where a fact came from is recorded, if at all, outside Core.
- Resources. A value declaration adds one pointer resolution per
fromFactvalue, for the one outcome produced. §10 has an implementation define limits on collection size and evaluation work and recommends one on string size. A declaration or a selected value past a documented limit is handled as §10 handles any other.
Conformance
Document-level cases, for a consumer that supports the extension:
- Positive. A declaration with a constant of each type; one with
fromFact; one mixing both; astringconstant holding a character outside the Basic Multilingual Plane, written as a surrogate pair. - Negative. A value source with both
constantandfromFact; with neither; with an unknowntype; with a member this section does not define; adecimalconstant that fails §2.2; abooleanconstant given as the string"true"; astringconstant holding an unpaired surrogate; an empty declaration; a value name that begins with a capital or a digit; a value name that ends in a line feed; a declaration in a pack that does not list the extension as required; the extension name on the root object alone; the name on an outcome and on a rule as well.
Evaluation rows:
- Positive. A constant carried on an outcome produced by a true rule, by a forced outcome and by
fallbackOutcome; afromFactthat resolves, of each type. - Negative. A
fromFactwhose pointer does not resolve, on an outcome produced by a true rule, by a forced outcome and byfallbackOutcome, eachunresolvedwith reasonunknown; two values of which one does not resolve, where the disposition carries novaluemember at all; anot-applicableresult and anunresolvedresult, each carrying novalue. - Handoff. A value that does not resolve in a pack whose
escalation.triggersnameunknown, where handoff is requested withtriggeredByof["unknown"]; in a pack whose triggers do not name it, and in a pack with noescalationobject, wherehandoff.stateisnone. - Boundary. A decimal with trailing zeroes copied unchanged; the empty string as a
stringvalue; the Booleanfalse; two true rules naming the same outcome, which carries its values once; the same declaration with its members authored in another order, which yields the byte-identical canonical disposition. - Adversarial. Where
decimalis declared: a fact given as a JSON number, asnull, as an object, and as a string with surrounding whitespace, none of which resolves. Wherestringis declared: a fact string with surrounding whitespace, which resolves and is copied unchanged, and one holding an unpaired surrogate, which does not resolve. That last row is a row of an evaluator that admits the facts document, and whether a conforming one does is open (see Resolution). A pointer that traverses an array out of range. A produced outcome whose own values resolve while another outcome declares afromFactthe facts cannot supply: the result is the produced outcome, because only it is inspected.
Error rows:
- A malformed declaration on an outcome the evaluation would not have produced, in a pack whose
applicability is false:
pack-not-conformant, and not thenot-applicabledisposition. - A malformed declaration together with an evidence-availability document carrying an undeclared
member name:
pack-not-conformant, the first class in §8.4's order. - For an implementation that does not support the extension and whose schema admits the name, a
well-formed pack that requires it:
unsupported-required-extension. The same pack gets the same class where its declaration breaks only this extension's own rules, such as an empty declaration or an unknowntype: an implementation that does not support the extension is not required to check them. A fault Core itself defines is another matter. A duplicate member name inside the declaration makes the packpack-not-conformantfor every implementation, and that class comes first (§8.4). Under the schema of0.2.0-draft, which refuses the name, every row of this bullet ispack-not-conformant, as Compatibility says. The first three cannot be run as written until a schema admits the name.
Implementation
Two implementation paths are plausible: the Go reference runtime and the clean-room Python
evaluator, the two whose agreement RFC 0006 reports. They are not
independent evidence. RFC 0006 records that both trace to one maintainer's direction, and
GOVERNANCE.md says that two implementations by one author are not
independent. RFC 0000's bar for a stable feature still needs an implementation directed
independently of this project.
Both now implement it as a prototype (2026-09-28), each behind an opt-in that is off by default: the Go runtime under its ADR-0039, and the Python evaluator with its readings in entries 27 to 33 of its decision log. Both built the extension form. Neither claims anything by it.
How the Python prototype was written is the maintainer's account, and the record of it is the
message of the commit that brought it into the experiments repository
(5cbcf5f):
under that repository's
clean-room protocol,
by a model of a different vendor than the one that drafted the Go prototype, in a room that held
the reference texts and the Python evaluator and not the Go one. By the same account, the model
that drafted the Go prototype wrote the rows and the driver.
Sixty rows were written from this document as it stood before this revision (specification
commit 7c7abbb), each with a pack of its own and the answer that text gives, and run through
both. There is a row for every case listed under Conformance, reading "a constant of each
type" as one row to a type, and for five cases of Examples. A disposition was compared byte
for byte as each implementation wrote it, and an error by its class.
| Against the answer each row carries | Rows |
|---|---|
| Both implementations give it | 56 |
| Both agree with each other and do not give it | 3 |
| The two differ | 1 |
Of the 39 rows whose answer is a disposition, 38 are the same bytes in both and the bytes the row
carries, the example under The disposition among them. The record, the rows and the driver are
in the experiments repository:
harness/RFC0016-AGREEMENT.md.
What the rows do not run:
- Four cases of Examples: the tiers where the rules produce
limit-high; the pass-through pack without its declaration, with the amount absent and with the amount a number, which Core evaluates toapprove-refund; and the calculated quantity, for which this document gives no complete pack. - A consumer whose schema admits the name and which does not support the extension. No such schema is published, so no such consumer was run.
- An input at either prototype's limits, and a pack that uses this draft together with RFC 0008.
- What this revision adds to Declaration: a member named
extensionsinside another extension's value, the name required and carried nowhere, and the name listed twice. The Python decision log records a test of the first, in entry 29. The Go decision record records checks for the other two, in its third finding.
What building it found, and where this revision answers it:
- The one difference is about admission. A fact string that holds an unpaired surrogate:
the Python evaluator admits the facts document and the value does not resolve, which is the
answer the row carries; the Go runtime refuses the document as
malformed-input. Neither was changed to match the other. Resolution, the row under Conformance and What this needs from Core now say that the question is open. - The three rows both answer otherwise are those of a consumer that does not support the
extension. The rows carry
unsupported-required-extension, which is the answer of a consumer whose schema admits the name. Both prototypes hold a pack to the schema of0.2.0-draft, which refuses the name, and answerpack-not-conformant. That agrees with Compatibility, and with the rows under Conformance as this revision words them. - Both read "an
extensionsobject" as one the schema defines, and not as any member of that name. Declaration now says so. - The two admit the name differently. The Go runtime sets the name aside and has the published validator judge the rest. The Python evaluator admits the name in its two places and runs its other checks as they were. An implementation that sets the name aside has to check two things itself that the validator would have found in what was set aside: that a required name has a value, and that it is listed once. Declaration now states both.
- The examples are fragments. The Python implementer completed them into packs and recorded how, in entry 32. The rows carry complete packs.
- The two bound the work differently, and one of them admits the prototype together with the prototype of RFC 0008 where the other refuses the pair. Both are under Unresolved questions. Neither was run.
None of this is conformance evidence, and RFC 0000's bar for a stable feature is as far off as it
was. The two prototypes trace to one maintainer's direction. The rows are not independent of the
Go prototype, for the reason above. The agreement record reports two runs of the comparison with
the same answer on every row: one against the Go prototype's branch before it was merged, and
one against the runtime's main branch at f98d4c9 after. When this was written the comparison
was not part of the experiments repository's continuous checks.
Unresolved questions
- Extension or Core. The extension form keeps §§7–8 as they are for implementations that do
not need values. It also makes this the first specification-defined extension, which needs §9
and the schema to say how one is admitted. The Core form avoids that and binds every evaluator.
Both prototypes built the extension form, and neither found anything in the semantics that
depends on the form. What the extension form cost them is what it costs a reader of the
current schema: until a schema admits the name, no consumer can answer
unsupported-required-extensionfor it. - Should constants be carried? See Alternatives. Carrying them copies pack content into the disposition, which §8.3 otherwise avoids.
- Is
unknownthe right reason? The five generated reasons matchescalation.triggers(§6.7), andexception-escalationis admitted beside them for a direct request (§8). Reusingunknownadds nothing to either. It leaves a consumer unable to tell a quantity that was missing from a condition that was unknown, except through diagnostics outside the disposition. One prototype gives such a diagnostic: its trace names each value of the produced outcome and says whether it resolved, and never carries the value. - Decimal identity. Values are copied without normalization, so
"5000"and"5000.00"are different values. Core defines no scale, unit or decimal-aware equality (§2.2, §13), and this proposal adds none. - Units and currency. The example carries a currency as a separate constant. Whether a quantity and its unit should be one value is tied to Core's open question on units (§13).
- Lineage. How a decision record cites the origin of a value drawn from a fact belongs with the lineage record (RFC 0014) and is not proposed here.
- Composition. Whether a value may feed another decision's facts is RFC 0002's question.
- Bounds. Whether the extension should fix a maximum number of values or a maximum string size, or leave both to each implementation's documented limits as §10 does. The two prototypes left it to their limits and chose differently: one counts declared values against a limit on authored items and the other has no such count, and they charge the work of resolution by different terms. An input near either limit is not portable between them.
- Is a facts document that holds an unpaired surrogate admitted? RFC 8259's grammar admits the text and lets a parser limit what a string may hold. RFC 8785 cannot serialize such a string, which matters to Core only where the string would reach a disposition. One prototype refuses the text in any input, and the other admits it and refuses the value where it is selected. This is a Core question beyond outcome values: it can change the answer for an otherwise conforming pack whose evaluation reaches facts preflight. What this needs from Core names approaches Core could take. Until Core takes one, this proposal's row for such a fact is a row of an evaluator that admits the document, and nothing here makes the difference between the two prototypes a conforming one.
- Together with RFC 0008. Two things are undecided: whether one evaluation may run under
both drafts, and how the work of resolving values is charged under the one running budget
RFC 0008 requires of an evaluation. What a value's
pointer selects is not in doubt: RFC 0008 restores the condition root after each
where, and values are resolved against the facts document after an outcome is chosen. One prototype refuses the pair and the other admits it. Whichever is accepted second should decide both.