RFC 0020: The workflow
On this page
- Amendment of 2026-10-15: a research stage
- Amendment proposal: current artifact encodings and failed attempts
- Summary
- Problem
- Evidence
- Where it lives
- Specification
- 1. Terms and canonical forms
- 2. The workflow document and bounds
- 3. Stages and projected cases
- 4. Bindings and influence across stages
- 5. Output records and closed sets
- 6. Selection records
- 7. Execution records, instances and attempts
- 8. Admission, recovery and commitment
- 9. The workflow verifier
- 10. What a workflow establishes
- 11. The two-stage fixture to record
- Alternatives
- Compatibility
- Security and privacy
- Conformance
- Implementation
- Unresolved questions
- Status: Draft
- Type: Standards track (a companion document of the specification, with a reader conformance class; fixtures recorded from a two-stage run)
- Created: 2026-10-15
- Amended: 2026-10-15 (a research stage, issue #174)
- Issue: #160
This is an open proposal. Its companion text is present for review, normative for nothing. No implementation or workflow fixture exists. The Type names the evidence to obtain, not evidence already held. RFC 0000 governs its review and acceptance.
Amendment of 2026-10-15: a research stage
This amendment records the maintainer's four decisions on issue #174, on pull request 177, RFC 0020: a research stage. Its review is round 2 of this RFC, recorded in the pull request's first comment, with the maintainer's dispositions in its second comment. The one HIGH, five MEDIUM and six LOW findings are accepted and applied below. The status stays Draft.
This is the workflow revision anticipated by RFC 0018's round-8 amendment,
the research contract.
Section 4 conditionally admits a stage whose dialect binds a research source at import, with
generated AI and any web profiles under that contract; question 2 is resolved. Freezing and
verification wait for a research-capable release form and encoding to be pinned. The published
dialect's own admission holds its model-served targets. Section 11 keeps the operation acceptance
construction and names the implementation work needed for an additional research recording
beside it. Workflow version 1's document form is unchanged. Replay checks retained bytes under
the profiles then bound and never asks a model or the web again.
This revision supersedes the dialect's statement that workflow version 1 admits no research stage (fixture 8 in dialect §11, RFC 0018's question 15 and its round-8 paragraph), pending the dialect's own amendment filed as judgment-pack-spec#179. Fixture 8's statement that the research plan does not replace the operation demonstration stands: the research recording is additional, beside that demonstration.
Amendment proposal: current artifact encodings and failed attempts
This proposal keeps RFC 0020 Draft. It pins Runner 66e264e and Runtime 785ea589, explicitly
selects legacy or named Dialect formats, and gives failed Core evaluations a separately pinned
error envelope. It does not claim an executor, fixture or conformance. Runner #130 implements
private document/projection/selection primitives; full execution remains Runner #121.
Named 2.0.0 and 3.0.0 keep their existing dialect family meanings. The proposed attempt
member evaluationErrorDigest changes this still-Draft closed form; there are no published
workflow instances to migrate. Existing preparations and run exports are unchanged.
Two independent readers must agree on integer/named variants and on missing, malformed,
changed and misassociated error-envelope variants before any conformance claim.
Summary
A workflow declares how one dialect runs for each record selected from another stage's outputs. Each stage pins its own published dialect and pack, names its input and output projection, and declares the relation between its outputs and their parent. Selection records bind the whole offered set and the chosen subset; output records preserve parentage; an execution record closes the instance inventory, including zero-output and unsuccessful work.
This is option A of the design memo recorded on issue #160: a standalone companion document,
spec/workflow.md, with a workflow-verifier reader class. The Runner executes, the Desk
reviews, and the Runtime and Gateway keep their existing semantics. Verification establishes
consistency of recorded stages and selections, without authenticating reviewer identity or which
published dialect and binding produced the signed preparation. Acceptance needs the two-stage
run the maintainer's decision requires; it does not exist yet.
Problem
A pack decides one case. A dialect prepares one case's facts and evidence. Neither says how to run a second dialect once for each record a reviewer selected from the first one's discovery. An installation importing that research needs the two dialects and packs by digest, the root case, the exact offered collection and selected subset, the projection into each child case, and the relation back to the selected parent. It also needs its own source bindings.
Issue #160 motivates this with organisation discovery followed by people research at selected
organisations, from the Desk's research line (#369 and #371). The design memo recorded on
issue #160, §1, finds that chain to be a motivating requirement, not a demonstrated execution.
The Desk's web/src/research/run.ts (judgment-pack-desk at 6b8a46c) sequences researchTurn and
casesAndCheck in AuthoringRun.start: it researches and checks a candidate pack. Its budgets,
conversation state and sequencing are Desk-private. They do not establish an organisation/person
workflow. Copying a prompt or transcript would leave selection and iteration implicit.
The judgment graph is the dataflow between decisions: an outcome becomes a fact or evidence availability for another evaluation. It supplies neither acquisition nor record iteration. RFC 0011, named as a graph in the issue, is instead the currency-anchor proposal. Neither substitutes for the missing contract, and pinning a pack's bytes does not establish that it is current policy.
Evidence
No workflow implementation or fixture exists. No verifier has been written for this format, no two readers have agreed on it, and no vector or conformance claim is made. The acceptance fixture is a recorded two-stage run from the Desk's research line. The maintainer's decision on issue #160 explicitly permits the Draft to land without it and requires its layout to be defined. Specification §11 names those files and the positive, negative, boundary and recovery recordings to obtain. They are a plan, not generated evidence standing in for a run.
Prior art to reuse. Judgment-pack-desk at 6b8a46c, web/src/research/ledger.ts, defines
SourceRecord as a search or page: a request, exact acquisition response, receipt, verification
state and excerpts. At the same commit, web/src/research/run.ts's researchRecord writes
researchRecordVersion: '1', pack and check digests, sessions, registries, cases, citations and
source responses beside the authored pack. That research record is useful retained evidence; it
is not this workflow's selection, output or execution record. It supplies neither the
demonstrated two-stage chain nor its closed selection and child inventory. Import must not
invent those absent facts.
The Runner's internal/runner/mapping_v2_export.go at 89cf441 recomputes preparation at
retained time under historical profiles, and can separately rehearse evaluation under a pinned
Runtime. At that commit, cmd/jpack-runner/main.go distinguishes verified inputs from verified
disposition, and internal/runner/run_chain.go binds completed runs to audit bytes and
preceding entries; completion order does not establish a workflow dependency. These are reusable
components, not workflow verification already implemented.
The prerequisite's standing. The maintainer's decision records version-3 import/binding as
delivered by judgment-pack-runner #83, merged as 89cf441 and released as the Runner's
v0.12.0: the reference Runner reads a version-3 document and binds an unbound source at import
through a binding document. This Draft does not claim to have run that implementation. The first recording must use the version-3 binding semantics;
this amendment pins the current implementation of those semantics in §1.
Historical reference evidence. The Runner's docs/MAPPING-V2.md at 89cf441,
"Dialect version 3" and "Release checks, runtime and offline verification", documented the
binder and run-export form used by the earlier draft.
Judgment-pack-runtime v0.32.0 at 80a8176, README.md, "Experimental evaluation behavior",
names the Core §8.4 error-envelope member evaluationError.class; its
docs/building-with-packs.md, "Keeping a record of what you decided", says refusals write no
audit record. The Runner's internal/runner/mapping_v2_export.go at 89cf441 reads the audit's
disposition member. The current amendment replaces these reference pins in §1 and defines
the separate error-envelope artifact in §7; question 8 now retains the implementation and
recorded-agreement requirement rather than the earlier undefined retention contract.
Condition 2's path. This Draft chooses to demonstrate the chain through operation sources.
Specification §11 gives the concrete two-stage construction, including the generated profiles,
projections, reviewer selection and empty child. It is a construction to record, not a recorded
demonstration. It uses the dialect §4.4's operation binding; that section also defines the
research binding conditionally admitted by §4 below. Condition 2's operation demonstration
remains due with the acceptance fixture. The research recording follows fixture 8's plan beside
it and uses §11's workflow bundle layout. The published dialects' generated-only admissions
refuse record-class bindings using the existing dialect, without extending it. The installation
still classifies what each channel actually serves; the verifier cannot detect an undeclared
model behind a channel the installation calls a record source.
Where it lives
On acceptance, spec/workflow.md would be a companion document of the specification beside
Core, normative for its reader class only. The text is present now to make the proposal reviewable
and to support a separately written reader. The Specification below and the companion's numbered
sections are held equal, with headings one level apart, as RFC 0018's are. Until acceptance,
.gitattributes export-ignores the companion, as it did for RFC 0018's Draft: no release bundle
carries it. The site publishes its text through this RFC's page.
The Runner interprets the definition, freezes bindings and releases, admits and executes
instances, and retains records. The Desk reviews selections and shows the pinned definitions,
projected cases and relations. These boundaries follow judgment-pack-desk at 6b8a46c,
docs/design/job-file-inputs.md and docs/design/jobs-mapping-v2.md. The Runtime evaluates
each case and records its audit; the Gateway acquires under its existing profiles and receipts.
Neither gains workflow semantics.
The Exchange gains a workflow entry kind only through a later explicit revision of RFC 0019 §3. Version 1 is closed and names one pack with its input/output dialect documents; it has no workflow member. This RFC adds none to it.
Specification
This section is the proposed companion document's §§1–11, word for word, with each heading one level down. The companion adds only its title and Status. Its rules are proposed, not adopted.
1. Terms and canonical forms
A workflow declares stages over selected records. A stage pins one dialect and one pack; an instance prepares and evaluates one case. A workflow runner interprets the workflow, admits and executes instances, and retains their records; its reference is the Runner. A review interface, such as the Desk, reviews selections and displays the pinned definitions. A workflow changes neither Core evaluation nor the dialect. Its output records are new envelopes around data.
The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT and MAY have
their BCP 14 meanings only in capitals. All forms below are closed; every listed member is
required unless expressly conditional. Unknown members, duplicate object names and duplicate ids
are refused. An id is [a-z][a-z0-9-]{0,63}. A digest is sha256: and 64 lowercase hexadecimal
characters, compared exactly. A timestamp has the form and valid instant of the dialect §1.
JSON is strict as in the dialect, §1: one value, well-formed Unicode and
number literals retained. The workflow, selection, output, set and execution objects use its canon
form: object members ordered by code point, arrays preserved, no whitespace or inserted defaults,
all supplied members included, integers from −(2⁵³−1) to 2⁵³−1, and -0 written 0.
Non-integer number literals have no form here. Their digests are SHA-256 of those canonical bytes.
A digest member lives outside the object it names; an object never contains its own digest.
Cases and output payloads are objects serialized in the dialect §9.5 form, restricted to that
integer domain: number literals, including -0, survive; strings escape the additional characters
that §9.5 names. Their digests name those bytes. Preparations retain that same existing form;
acquired responses and audit records retain their original bytes. These forms are not exchanged.
Pack digests name exact retained bytes, explicitly adopting
RFC 0001's still-Draft choice, with no normalization.
Published and bound dialects and binding documents use the dialect's canonical digests.
The required reference Runner encoding is judgment-pack-runner at
66e264e1e44f665e52b056be1b70864a27927338, including its research preparer and named Dialect
reader. This source pin does not assert that a workflow executor is shipped. Its release digest
is SHA-256 of canonical(encode(r)), where r is the decoded
Release, not the whole retained JSON object: the typed encoding can omit members. The required
encoding references at that pin are internal/runner/model.go (Release),
internal/runner/source_inputs.go (InputMapping), internal/runner/dialect_v3.go
(InputMapping.MarshalJSON), internal/runner/dialect_artifact.go (marshalArtifact) and
internal/runner/mapping_v2_export.go (releaseDigest).
It is not a file-byte digest.
The Runner's docs/MAPPING-V2.md at 66e264e, "Dialect version 3", documents the version-3
encoding; "Release checks, runtime and offline verification" documents the run export (§7).
The runtime reference is judgment-pack-runtime v0.34.0 at
785ea58927255b775a774e29952c560591429cd3. Its README.md,
"Experimental evaluation behavior", names disposition in the Core §8.3 result payload and
evaluationError.class in a Core §8.4 error envelope. Its docs/building-with-packs.md,
"Keeping a record of what you decided", and docs/architecture.md, "Packages", describe an
audit retaining the canonical disposition and no record for a refused evaluation. The Runner's
internal/runner/mapping_v2_export.go at 66e264e reads the audit member disposition, hence
run.audit.disposition; this member name is established by that source. Runtime
docs/adr/0027-pin-the-evaluation-trace-contract.md at 785ea589 keeps trace outside the
disposition and discards it on evaluation error. Section 7 applies these distinct forms.
2. The workflow document and bounds
workflow.json is exactly {workflowVersion, stages, result, limits}. workflowVersion is the
integer 1; stages is an ordered array of 1 to limits.maxStages stages (§3), with distinct
ids. Exactly the first stage is a root. Every other stage names an earlier stage; all are thereby
reachable from the root. result is a stage id naming a terminal stage, one with no consumers.
It names that stage's ordered outputs, without aggregating dispositions or discarding other stages.
limits is exactly the following integer members; each is at least 1 and at most the ceiling:
| Member | Ceiling | Applies to one execution branch |
|---|---|---|
maxStages |
32 | stages |
maxRecords |
4096 | output envelopes across all stages |
maxInstances |
4096 | logical instances, including failures and cancellations |
maxAttempts |
16 | attempts per instance |
maxBytes |
1073741824 | supplied bundle bytes, each file counted once |
The bounds below and §1's integer domain apply to workflow, selection, output, set and execution
objects and to cases and payloads; packs, acquisitions, preparations, audits and run exports keep
their own formats' bounds and number domains, within the branch's aggregate byte and file limits.
Those workflow objects have at most 64 container levels; cases and payloads have at most 32.
The dialect §12 counting convention applies. Every object has at most 4096 members, every array
at most 4096 elements, every decoded string and member name at most 65536 UTF-8 bytes, and every
number literal at most 128 characters. Smaller bounds stated here or by a referenced format win.
The bundle has at most 65536 files. The workflow is at most 262144 bytes; each selection and
output envelope at most 65536; each case and payload at most 1048576; each set and the execution
record at most 8388608. Dialect §12's smaller artifact and combined-input bounds
also apply separately to every preparation, including retained attempts. Counts include empty
containers and unsuccessful work; nothing is truncated to fit. The same bounds hold canonical
bytes and input bytes. A workflow runner refuses admission before acquisition when a known bound
fails. Account for results in instance order: stage order, then selected parent-record order,
then output index, regardless of acquisition or completion order. The first instance whose
outputs would exceed a branch bound and every later instance of that stage record
limit-exceeded, emitting no outputs. Earlier completed siblings' outputs remain in the closed
set with those failures explicit. Nothing is truncated to fit.
3. Stages and projected cases
A stage is exactly {id, dialect, pack, input, execution, caseBindings, outputs, relation} and
the conditional selection below. dialect selects exactly one of two closed forms:
{version, digest}for an integer-format dialect, whereversionis integer2or3;{formatVersion, id, version, digest}for a named dialect, whereformatVersionis exactly"2.0.0"or"3.0.0", andidand string artifactversionhave dialect §2.1's forms.
For a named reference, the consumer MUST check the supplied published document's formatVersion,
id, artifact version and canonical digest, all exactly. The format selector is not an
artifact version or a version range. A formatVersion member selects the named form; without
it, integer version selects the legacy form. An unknown or unread selector value is
version-unread before closed-form checking. A named reference with a non-string or invalid
artifact version is input-malformed, never a legacy fallback. Missing selectors are
input-malformed. Never infer a named format from an integer family or an artifact name.
The digest names the whole published document in its selected format, including named identity.
pack is {id, digest}:
its Core absolute-URI id, at most 2048 UTF-8 bytes, and exact-byte digest. Loaded identities MUST
match every declared pin. A version label alone, job id or catalog name cannot substitute for
the independently supplied digest. Each stage has its own pins, even when stages share bytes.
The root's input is exactly {root: true}, execution is once, and caseBindings is [].
It receives the supplied root case once. A dependent stage's input is exactly
{fromStage: S, selected: true}: input.fromStage names the earlier producing stage, and
input.selected requires its selection; the dependent stage's execution is
each-selected-record. It gets exactly one instance per selected upstream output envelope,
including when equal payloads have distinct record identities. There is one parent per instance.
No join, recursion, cross-product, entity deduplication or implicit input sharing is admitted.
For a dependent stage, caseBindings holds 1 to 64 objects, each exactly
{from, to, type, required}. from is a pointer into the selected record's payload, never its
envelope; to is a non-empty pointer into a fresh {} case. Both are RFC 6901 pointers of at
most 1024 UTF-8 bytes and 32 decoded tokens; escapes are only ~0 and ~1. Reading follows
the dialect §1 pointer rule. Writing creates object members only, including numeric tokens.
Destinations MUST NOT equal or prefix one another by decoded whole tokens, regardless of whether
a value exists. The source pointer may be empty, explicitly naming the whole payload.
type is string, integer, timestamp, boolean, object, array or null, with the
JSON meanings and the dialect §1 integer and timestamp meanings. required is a boolean.
Only an absent optional value is omitted. An absent required value or any present mistyped value
fails projection before acquisition; null is present and matches only null. Copies preserve
literals and disclose only the named values, including their descendants for a container copy.
No coercion, default, template, expression or script runs here. The resulting case contains exactly
these copies, with no inherited root members. Overlap is a document refusal; a value failure is
an instance failure. The verifier recomputes both, rather than trusting the retained case.
Failing a present mistyped optional value is a deliberate departure from the design memo recorded
on issue #160, which failed only missing or mistyped required values.
outputs is {pointer, cardinality}. The pointer is non-empty, has the bounds above and resolves
in the prepared facts document, not an acquisition or an audit record. cardinality is one or
many: one requires an object; many requires an array of objects. An empty array succeeds
with zero outputs. An absent value, null, a wrong type or a non-object array member fails the
instance; none means an empty array. A many-output invocation evaluates one case about the
collection and supplies records for review, not a disposition for each candidate.
selection belongs to the producing stage whose outputs are offered. It is present exactly when
another stage consumes that stage, and absent on a stage no stage consumes (a terminal stage).
It is {mode: "reviewer"}, or {mode: "disposition", rule: R}. R is exactly
{kind: "outcome", outcomeId: O}, {kind: "unresolved"} or {kind: "not-applicable"}.
O is a declared pack outcome id, 1 to 256 UTF-8 bytes. This is equality on the recorded Core
§8.3 disposition's kind and, for outcome, its outcome id; reasons and handoff remain unchanged.
Disposition mode requires outputs.cardinality: "one". Evaluation errors have no disposition
and no outputs. Rules do not select a batch's members by the batch's disposition.
relation is {label, direction}: label is an id, and direction is output-to-parent or
parent-to-output. A root's parent is the root case; a dependent output's parent is its selected
record. The label declares provenance, not a verified identity, employment or other domain fact.
4. Bindings and influence across stages
Before the root runs, the installation freezes each stage's published dialect, binding document
when required, resulting bound dialect and release (§7). Unbound operation and research
sources are bound at import and expanded exactly as the dialect §4.4 specifies. An operation's
expansion names its bound profile; a research source's expansion names its bound AI profile
and any web profiles, all of class generated. Its fields, model and capabilities remain
as published. The dialect's declared model, capability and class checks apply, with incompatible
research profiles giving profile-mismatch (dialect §§4.4 and 5.1). The workflow verifier reports
that finding as preparation-mismatch when it arises in a preparation and as
stage-binding-mismatch from §9's check 1. A workflow runner refuses to freeze a stage with
incompatible research profiles, so no instance is admitted.
A dialect with no unbound source has a null binding-document digest and an unchanged bound
digest; a superfluous binding document is refused as in the dialect §4.4.
The reference encoding in §1 retains research sources and their bound AI and web profiles.
A research stage may be frozen only when the installation reads that complete source contract
and its selected dialect format; named 2.0.0 remains family 2 and cannot carry research.
Named 3.0.0 retains its published identity during binding under dialect §2.1. No fallback to
an integer-format reserialization is permitted. This removes the earlier release-encoding
prerequisite, not the requirement to implement and record the workflow.
The two-stage operation construction in §11 remains the acceptance demonstration of issue #160's
condition 2; the research recording is additional, beside it.
An operation's profile declares the installation's classification of its channel. A published
dialect whose source serves a model's answers MUST declare admits exactly ["generated"] at
every target of that source. A record-class binding then fails the dialect's
§8.2 admission at preparation; §9's check 1 confirms the bound profile's class against that
published admission. A published dialect MUST declare admits exactly ["generated"] at every
target of a research source; §9's check 1 confirms it (stage-binding-mismatch).
This checks declared classes, not whether the channel actually serves a model: that still depends
on the installation's classification. Using the operation kind does not establish authorship.
Copied values remain case assertions in the unchanged dialect. The workflow adds a check
outside its preparation: it carries the upstream classes and generated influence across each
copy. For a payload, take all preparation fact-lineage entries whose target overlaps its full
facts pointer by decoded tokens, plus inherited workflow influence on those targets. Retain the
union of classes, sorted asserted, generated, record, and OR the generated-influence flags.
No contributor gives classes: [] and generatedInfluence: false. A container or mixed output
conservatively carries every contributor's influence, also for a copy of only one of its fields.
Each copied value carries that parent summary. A case fact or evidence copy is affected if its
source overlaps a copied destination; a case parameter is affected on the same rule. Affected
targets include every target of every source in whose scope an affected case parameter lies,
whether or not its request or rule names it, and transitively every target of a source that
declares a source parameter from an affected target. Every affected target retains the parent
summary in workflow reasoning, in addition to its local dialect lineage. If generated influence
is true, the bound dialect's admits MUST explicitly include generated at each affected fact
and evidence target, as well as admit its ordinary class. Refuse admission before acquisition
otherwise. This conservative rule uses declared dependencies, including unused parameters.
A reviewer's selection cannot convert generated material into record or erase its influence.
The published, binding-document and bound digests are separate record members. The binding
document's dialect content-binds the published digest. What remains unauthenticated is that the
signed preparation and record came from this published dialect under this binding: two published
dialects differing only in catalog names bind to one bound dialect (RFC 0018 §4.4). The preparation
binds only that bound dialect; its binding is unchanged. Re-expansion checks consistency only.
5. Output records and closed sets
An output record is {outputRecordVersion: 1, payloadDigest, lineage}; the payload is a separate
object in §1's literal-preserving bytes. Its identity is the envelope's canonical digest, not
the payload digest: duplicate payloads can be distinct records. lineage is exactly:
workflowDigest,execution,stage,instance: the workflow digest and three ids;publishedDialectDigest,bindingDocumentDigest,boundDialectDigest: digests, with onlybindingDocumentDigestnullable under §4;packDigest,releaseDigest,preparationDigest,auditDigest: digests of the stage pack, frozen release, successful attempt's preparation and exact audit bytes without their newline;outputPointer,index: the declared facts pointer and an integer from 0 to 4095;oneuses index 0,manyits array index. Together they identify the projected value;rootCaseDigest: the root case's digest on every output;caseDigest: this output's own instance's case digest;parentRecordandselectionDigest, both null for the root and both digests for a dependent stage;relation: exactly the stage's relation; andinfluence: exactly{classes, generatedInfluence}, the distinct 0 to 3 classes and boolean computed in §4.
All pins agree with the stage and instance, and the payload's literal-preserving bytes equal
the corresponding prepared value's bytes. The successful attempt is the only output-producing
attempt. The full pointer for many appends the index token to outputPointer; for one it
is outputPointer. Lineage names the execution id, never the enclosing execution record's
digest. These edges are acyclic. Workflow lineage is never appended to preparation lineage or
Core's disposition, whose forms remain closed (dialect §9.3; Core §8.3).
A closed output set is the canonical object {workflowDigest, execution, stage, records}:
one digest, two ids, and the array of output-envelope digests, at most limits.maxRecords.
Records follow instance order (§7), then array index, with no duplicate envelope digest. Its
digest binds the whole offered set, selected or not. Failed instances contribute no outputs,
but remain in the inventory. The set is closed only after every expected instance is terminal;
it is never presented as complete discovery. Every stage, even one with no instances, has a set.
6. Selection records
A selection is exactly {selectionVersion: 1, workflowDigest, execution, upstreamStage,
outputSetDigest, selected, mode, revision} and the conditional members below. execution and
upstreamStage are ids; both digest members are digests. selected contains 0 to
limits.maxRecords distinct output-envelope digests, all in that closed set, in upstream order.
revision is an integer from 1 to 16. Revisions increase by one for each replacement selection
of the same execution and upstream stage; the first is 1. The bytes of each revision are retained.
upstreamStage names the producing stage whose outputs are offered. mode equals that stage's
selection.mode. In disposition mode the additional member rule equals that stage's
selection.rule, and selected is exactly every output whose evaluated case's recorded
disposition satisfies it. A dependent stage consumes this selection through input.fromStage
and input.selected (§3).
In reviewer mode the additional member review is exactly {actor, assertion, at}: an
installation-local actor string of 1 to 256 UTF-8 bytes, an assertion of 1 to 1024 UTF-8 bytes,
and a timestamp. They are the installation's assertion of a review and its time, not proof of a
real person's identity or intent. An empty selection is explicit, never inferred from silence.
The conditional member refusal, when present, is exactly "limit-exceeded": the selection was
refused at admission (§8), remains unconsumed, and blocks its consumers for that recorded reason.
Once consumed by a downstream admission, a selection is immutable. A change writes a new revision, with a new digest, and a new branch. All consumers within a branch use the same selection of an upstream stage. Existing children remain attached to their original selection. Branches share an execution id and unchanged ancestor instances; an execution record closes exactly one branch, identified by its ordered selection digests, without overwriting earlier branch records. Changed downstream output sets require new selections before any further children are admitted.
7. Execution records, instances and attempts
An execution record is exactly {executionVersion: 1, workflowDigest, execution, rootCaseDigest,
frozen, instances, outputSets, selections}. The digest members are digests and execution an id.
frozen has one entry per stage in document order, exactly {stage, publishedDialectDigest,
bindingDocumentDigest, boundDialectDigest, packDigest, releaseDigest, runtimeDigest}. These are
an id and digests, with only the binding nullable under §4. Retain the named documents. The
release pins the same pack, bound dialect and runtime executable as these entries; runtimeDigest
names exact executable bytes. No profile, binding, release or runtime substitution is allowed.
Read the release's packDigest and runtimeDigest, and its embedded inputMapping, not a mapping
digest member. Compute boundDialectDigest from that mapping's dialect canon bytes under its
selected format's encoding: integer version 2 writes provider, facts and evidence;
integer version 3 omits those legacy members. Named formats use dialect §2.1's closed
identity-bearing form; do not insert legacy members, remove identity, or substitute the integer
family before digesting. The release form and encoding are pinned by §1, including its named
dialect identity when present and research source members. Decode and encode using that exact
reference; do not normalize the forms alike or silently use a newer installed writer.
instances holds 1 to limits.maxInstances entries, ordered by stage, then selected parent
order. Each is exactly {id, stage, parentRecord, selectionDigest, inputDigest, caseDigest,
state, failure, attempts}. Ids are unique within the execution. Parent and selection are null
together for the single root instance and otherwise digests. The root's input digest is
rootCaseDigest; a dependent input digest is the digest of
canon({parentRecord, selectionDigest, caseBindings}),
using the stage's bindings. It commits the projection's inputs even if projection fails.
caseDigest is the projected case's digest, null only when projection failed or was never begun.
Every expected instance appears, even if it was cancelled before acquisition. Its terminal state
is completed-zero, completed, failed, interrupted or cancelled. Completed states
require a successful preparation and evaluation, and respectively zero or one or more outputs.
completed-zero is possible only with many. An evaluation error is failed, never an
empty success. interrupted includes uncertain acquisition; cancelled records stopped work.
None of these three states emits outputs. Failed projection has state failed and no attempts.
failure is null except for failed, when it is projection-invalid, admission-refused,
acquisition-failed, preparation-failed, evaluation-error, output-invalid or
limit-exceeded. Recompute projection, admission, output and bound failures; compare evaluation
errors to the retained runtime error envelope under the rule below.
Acquisition availability and stopping are installation
assertions, not independently verified events. A successful evaluation with valid in-bound
outputs cannot be recorded as failed without another retained failure of these kinds. A dialect
admission refusal after acquisition is recorded admission-refused, the dialect's own code,
not preparation-failed.
attempts has 0 to limits.maxAttempts entries in attempt order. Each is exactly
{number, state, failure, preparationDigest, auditDigest, runDigest, evaluationErrorDigest, retry}. number starts at 1
and increments by one. state has the instance state's five values. runDigest names exact bytes
of a retained run export, including a failure export when no evaluation happened; it is null
exactly when the attempt has no run export. Preparation and audit digests are null exactly when
those artifacts do not exist; completed attempts require both. A failed preparation is not
retained as a valid preparation pin: its inputs and failure
are in the run export, with preparationDigest: null. Every referenced valid preparation,
including an unsuccessful attempt's, is checked under §9. failure follows the instance rule.
retry is null on attempt 1 and otherwise {actor, at}, with §6's actor and timestamp bounds,
the installation's explicit retry assertion. Earlier attempts must be failed or interrupted;
only the last may complete; its state and failure equal the instance's. With no attempts the state
is failed, interrupted or cancelled. Acquisitions, including uncertain ones, stay in their exports.
For a run export, read run.input.preparation and run.audit as dialect §11 specifies, using
the original audit bytes in standard-base64 run.auditBytes when present. In export version 2,
take the value bytes of run.audit exactly as written, with no re-encoding. Compare the separately
retained preparation and audit with these values; use the preparation's own verifiedAt.
The Runner's docs/MAPPING-V2.md at 66e264e, "Release checks, runtime and offline verification",
names the export {version, releaseDigest, release, run} and exports a mapped run without audit
bytes, including a failed run, as version 2. "Exact bytes of the audit record" documents
run.audit and run.auditBytes; internal/runner/model.go at that pin names
run.input.preparation. Read the Core §8.3 disposition from run.audit.disposition, the exact
member read by internal/runner/mapping_v2_export.go at the same pin. The runtime's README.md,
"Experimental evaluation behavior", at 785ea589 (v0.34.0) names the error envelope's
evaluationError.class for Core §8.4. Refusals write no audit record under its
docs/building-with-packs.md, "Keeping a record of what you decided"; the error class is read
from the error envelope. The reference Runner's internal/runner/runtime.go at 66e264e retains
that envelope in attempt diagnostics but returns no run.result on evaluation failure.
The workflow writer MUST retain that exact complete stdout separately as evaluation-error.json;
evaluationErrorDigest is its exact-byte digest, including any final newline. It is non-null
exactly for a failed attempt whose failure is evaluation-error, and null otherwise. A missing
non-null error artifact is an inventory refusal. The bounded envelope MUST be one strict JSON
object in Runtime output version "2", with command: "experimental evaluate", status: "error" or "unsupported" as the pinned
Runtime envelope form permits,
no disposition, and an evaluationError with the Core §8.4 class, matching phase and
evaluatorSpecVersion: "0.2.0-draft". Read it under the Runtime envelope form at the §1 pin;
its diagnostics and tool version do not change the class. Its bytes are at most 8 MiB and count
towards the branch aggregate. No audit is retained for that attempt. A reader checks the
recorded envelope and its pin, not that the Runtime truly emitted it or would repeat it.
An ordinary invocation failure without such a complete Core error cannot be called
evaluation-error or a zero-output success; retain the attempt as interrupted when no
completed evaluation can be established. An explicit cancellation remains cancelled.
Existing run exports and their result members are unchanged by this workflow side artifact.
outputSets has one entry per stage in stage order, exactly {stage, status, records}. status
is closed or blocked; records is the digest array of §5. Its closed-set digest is derived
using the execution's workflow digest and id. selections has one entry per stage in that same
order: a selection digest, or null. A stage with consumers may lack a selection only when the
branch ends before review or selection completes. Its consumers are blocked, with no instances,
outputs or selection, transitively; a selection carrying refusal blocks them in the same way,
with its digest retained in selections. A stage with a consumed upstream selection is closed,
including an empty selection yielding zero instances. Root is closed. Terminal stages have null
selections.
For each non-blocked dependent stage, reconstruct one expected instance for every selected
parent. Missing, extra, repeated or foreign-parent instances are findings. A consumed selection
cannot justify omitting a child; cancellation reserves that child with its explicit terminal state.
The record distinguishes blocked work, completed-zero and unsuccessful work. A branch is complete
only when all stages are closed, every required selection is consumed and every instance is in a
completed state (completed or completed-zero).
8. Admission, recovery and commitment
The workflow runner admits one logical instance per (execution, stage, selection digest,
parent-record digest), using null for the last two at the root. It stores that key, the input
digest and instance id transactionally. A duplicate with the same input returns the same
instance; changed input is refused. This also holds for shared ancestors across branches. All
selected children are reserved before their stage acquires, or the stage is refused as over
bound without partial admission. A successful selection enters the execution's selections only
atomically with reservation of all its direct consumers' children. A bound refusal instead
writes a selection record carrying refusal: "limit-exceeded" and retains its digest there,
without reserving children. It is unconsumed and its consumers are blocked. The inventory
survives interruption or cancellation.
A retried acquisition is a new recorded attempt under the same instance, with new retained
responses and receipts, never an offline replay. Uncertain acquisitions are not retried
automatically. A retry in place is allowed from failed or interrupted only while its output
set is unconsumed. Once consumed, a retry opens a new branch with its own selection digest; the
retried instance is a new instance of that branch, in a new branch-local admission scope; only
unchanged ancestors reuse their existing instances. Earlier branch instances and sets remain
unchanged. A completed instance is not rerun in place; a new execution is required. Verification
recomputes derivations over retained answers and never calls a model or a source. Transactional
admission is a writer rule; an offline reader checks the resulting inventory, not the history of
every side effect. There is no end-to-end exactly-once claim.
The execution record commits outputs and selections without a digest cycle. It is unsigned in
this version. Existing audit signatures cover their own audit bytes and preparation bindings,
not these new envelopes or which published dialect and binding produced the preparation. An
independently held execution digest can expose subsequent replacement, but this version
specifies no authenticated execution commitment. The Runner's journal is unsigned and unchained
(judgment-pack-runner at 66e264e, internal/runner/events.go); its actor verifies no person.
9. The workflow verifier
The workflow-verifier reads the workflow, its expected digest, one execution record and its
expected digest, and all referenced current-branch artifacts. Other branches and earlier selection
revisions are retained by the writer but not traversed. The reader checks the chosen revision's
form; it cannot establish an unprovided revision history or enforce transactional immutability.
The runtime executable is supplied separately only for optional replay; this reader compares the
release's runtime pin to the independently given runtime pin without claiming to run the binary.
It is also given independently trusted historical profiles and runtime pins, never trusted by
their presence in an export. Digest expectations name bytes to compare, not an authenticated
source. The reader takes no network access or acquisition permission.
The reference phase refuses, in order: byte/aggregate/nesting bounds (input-over-bound);
strict JSON and the integer domain scoped by §2 (input-malformed); count/string bounds
(input-over-bound); versions it cannot read (version-unread); closed forms and reference
ordering (input-malformed); absent artifacts with non-null pins (inventory-mismatch, a
refusal); and dialect kinds it cannot read (kind-unread). A binding document whose dialect
is not the published digest is input-malformed in the form phase, as dialect §4.4 requires.
Within a phase, use workflow order, instance order, attempt order and member code-point order.
Unknown format selectors are version-unread, never guessed forms. For a stage dialect,
scan formatVersion when present, otherwise the legacy integer version. A named artifact's
string version is identity checked in the form phase, not a format discriminator; a mistyped
or malformed named artifact version is input-malformed.
Core disposition well-formedness is part of the form phase for a completed evaluation; invalidity
is input-malformed. An evaluation error has no disposition. A retained evaluation-error
envelope that does not have §7's form is input-malformed; a valid envelope whose pin or
attempt association disagrees is checked in semantic phase 1 or 4 respectively.
Next run the dialect's preparation-verifier for every referenced preparation, in instance
and attempt order, at its own saved verifiedAt, with its acquisitions, trusted profiles and
audit when present. Require binding for completed attempts and every audit given; an unsuccessful
attempt without an audit checks derivation only. Preparation refusals retain their codes and
precede all semantic findings; report the first refusal in instance and attempt order. If there
is none, the first preparation finding maps to preparation-mismatch, including the dialect's
profile-mismatch and disagreement with audit facts, evidence or citations. Only after every
preparation passes do the checks below run. Influence uses the recomputed lineage, never the
unchecked retained lineage. No freshness check substitutes today's clock.
Then perform checks 1 to 4 in order, stopping at the first finding. Within each check use stage
order, then instance and attempt order; finish one instance's listed clauses before the next.
Within check 1, workflow and execution pins come first, then frozen stage pins, then instance
artifacts; within an instance, digest-mismatch precedes stage-binding-mismatch. Within
check 3, an earlier instance's influence-mismatch precedes a later one's case-mismatch.
- The workflow and record digests and every artifact pin (
digest-mismatch); frozen published dialect expansion against each binding, profile, bound digest and release, including the bound profile's class against the published dialect's admission (stage-binding-mismatch). For aresearchsource, check each assigned AI and web profile against the dialect §4.4's declared model, capability and class rules under the trusted profiles, and confirmadmitsis exactly["generated"]at every target of that source. These checks cover every frozen stage, with or without a preparation; failures, including the dialect'sprofile-mismatch, givestage-binding-mismatch. A workflow runner refuses to freeze a stage with incompatible research profiles, so no instance is admitted (§4). - Each selection's full offered set, revision and exact ordered membership; recompute the closed
disposition predicate against the retained Core disposition (
selection-mismatch). - Every projected case against its parent and bindings, including expected projection failures
(
case-mismatch), then inherited classes, influence and explicit admission (influence-mismatch). - The expected instance inventory, admission keys, attempts, terminal states, selection refusals,
deterministic bound accounting and stage closure (
inventory-mismatch); then re-extract all outputs, compare payload bytes, order, complete sets, parent/selection references, relation and lineage pins (output-mismatch). Neither failure nor missing data becomes[].
Predicate checking establishes agreement with the recorded disposition, not its recomputation. Runtime replay and verification of signatures or checkpoints are separate checks; this class claims none of them. Checking embedded runs alone is not workflow verification.
The report is one closed JSON object, in the dialect §9.5 serialization, followed by one newline.
A refusal is {result: "refusal", refusal: C} and a finding is {result: "finding", finding: C},
C one code above. A reading is exactly {result: "reading", workflowDigest, executionDigest,
consistency: "agrees", completion, preparations: "agree", authentication: "not-established",
dispositions: "not-replayed", counts}. completion is complete or partial by §7; counts
is {stages, instances, outputs, selections}, nonnegative integers within §2's bounds (selections
at most stages). A partial reading is consistency of an explicitly incomplete execution, not
successful completion. Reports are at most 4096 bytes. A program exits 0 for a reading, 1 for a
refusal, 2 for a finding, and 3 with no report when it could not run, including an existing file
that cannot be read or an invalid command argument. A missing pinned artifact is instead the
inventory-mismatch refusal above. A library exposes the same outcomes in its own idiom.
A conforming reader gives these answers for every admitted input and all fixtures published
with the specification version its claim names. Its claim names workflow-verifier, workflow
version 1, that specVersion, and the dialect versions, kinds and shapes the published fixtures
exercise. This is a reader class, not an executor, preparation writer or Core conformance class;
none implies another. No claim is available while this text is Draft or until such fixtures are
published. No fixtures or vectors have been recorded for it.
10. What a workflow establishes
A reading establishes that these stages ran over these selections by their records, consistently: the definitions, preparations, offered sets, projections, inventory and relations agree. A partial reading names incomplete work. Without authentication, rewriting the whole recorded bundle consistently can yield another reading. No reading establishes good research, a real person's approval, completeness of discovery, true identities, current policy, correct model answers, which model answered, or exactly-once execution. Digest pins establish content identity, not currency. Generated-only admission checks a profile's declared class. The installation's classification of what its channel actually serves remains a trust assumption; a reading cannot detect an undeclared model behind a record-class channel (§4; dialect §5.1).
11. The two-stage fixture to record
Nothing in this section is recorded yet. The first fixture is a run from the Desk's research
line using two version-3 unbound operation dialects, bound by the Runner at import. This remains
the acceptance construction for issue #160's condition 2. An additional research-stage recording
follows fixture 8's selected-parent-child plan in
RFC 0018 §11 beside that demonstration.
Its layout is the workflow bundle below, with fixture 8's gtm-company-person and
work-item-triage examples as its dialects. The research preparer and readers are available
(judgment-pack-runner#88, judgment-pack-spec#176);
§§1, 4 and 7 now pin their reference encoding. This additional recording still requires
a workflow executor and verifier; those are not established by single-stage preparation. The concrete operation construction to demonstrate is:
organisations: root,once, pack and published dialect independently pinned; a casequeryparameter supplies an operation request. Platformresearch-test, operationorganisations, shapehttp, recordadapter-httpbind to a generated profile. Its read copies the response's/organisationsto facts/organisations. Outputs are that pointer,many; this producing stage'sselectionis{mode: "reviewer"}, with relationdiscovered-for,output-to-parent. The answer has three synthetic objects with ids.people: input{fromStage: "organisations", selected: true},each-selected-record, its own pack and dialect pins; binding{from: "/id", to: "/organisationId", type: "string", required: true}. That case parameter supplies a request to operationpeopleon the same platform and shape. Its generated profile's read copies/peopleto facts/people; outputs are that pointer,many, with noselectionbecause no stage consumes it; relationperson-at-organisation,output-to-parent. The published dialects declareadmitsexactly["generated"]at/organisationsand/people, respectively, so a record-class binding fails dialect §8.2 admission. Both explicitly admit generated influence at every affected target.resultispeople. A reviewer selects the first and third organisation in upstream order; one child returns two synthetic people objects, the other an empty array. The inventory holds three instances, onecompleted-zero, five output records and the complete three-record offered set. The relation says which organisation was researched, not that employment is true.
A recording carries exactly one branch: one set per stage and only the selection revision that branch names. Other revisions and branches are retained separately. Its directory contains the following files; angle-bracket components are ids or decimal attempt/index numbers within the bounds above, not literal path characters:
workflow.json,workflow.sha256,execution.json,execution.sha256,root-case.json;stages/<stage>/pack.json,dialect.json,binding.json,bound-dialect.json,profiles.jsonandrelease.json; the binding file is present exactly when §4 requires it;instances/<instance>/case.json, andattempts/<number>/sources.json,preparation.json,preparation.sha256,verified-at.txt,audit.json,audit-signatures.json,run.jsonandevaluation-error.jsonunder that instance; artifacts, including the case, are absent exactly when their pins are null;outputs/<stage>/<instance>/<index>/payload.jsonandrecord.json;selections/<stage>/<revision>.json,sets/<stage>.json,expected-report.json,trust.json(declared public test trust material) andREADME.md(recording commands and independent pins).
Each .sha256 file holds one digest and a newline; verified-at.txt holds the preparation's
timestamp and a newline. The preparation's own verifiedAt and digest computed from its bytes
govern; these side files must agree and never override them. workflow.json, execution.json,
selection files, set files and output record.json hold their canon bytes, with no newline;
so do dialect.json, binding.json, bound-dialect.json and profiles.json in their own forms.
root-case.json, case.json, payload.json and preparation.json hold the dialect §9.5 bytes,
with no newline. pack.json, sources.json, release.json, run.json, audit.json and
audit-signatures.json, evaluation-error.json and trust.json retain original bytes, the audit
line without its newline. Evaluation-error stdout retains any final newline and is never
reconstructed from diagnostic text or an omitted run result.
expected-report.json holds §9's report in §9.5 serialization followed by one newline.
Retain exact requests, answers, salts, receipts and supporting page responses in sources.json,
and the runtime and release pins; include no credentials, personal data or executable. Provision
the digest-matching runtime separately for optional offline disposition replay. Trust comes from
the recording protocol, not trust.json alone. A verifier must be able to run with acquisition
disabled; replay never asks an AI source to reproduce an answer. Optional chain/checkpoint files
remain separate evidence with their own verifier's report, outside this class's report.
Record variants for a second synthetic installation, preserving workflow/published digests and
changing bindings and releases; disposition selection of one-output cases for matching and
nonmatching outcomes, unresolved, not-applicable and errors; no selection; maximum fan-out and
one over it; missing versus null; duplicate payloads; reordered arrays; -0 and escaped strings.
Keep independent expected commitments fixed when altering bindings, packs, answers, selections,
revisions or relations, adding an unselected child, omitting or repeating a selected child, or
laundering generated influence. Include a record-class downstream operation parameterised from a
generated payload without generated admission, refused before acquisition, including an affected
case parameter its request never names. Include two siblings of six outputs when ten records
remain, completed in both orders: the second and every later sibling record limit-exceeded.
Include interruption after atomic admission, uncertain acquisition, a recorded selection bound
refusal, and retries before and after consumption. Freeze expected reports with the recordings.
Add integer and named family-3 variants with matching published identities, and refuse changed
selectors, identity-stripped bound documents, missing/tampered error envelopes, error envelopes
attached to successful attempts and ordinary invocation errors mislabeled as Core errors.
This layout supplies no evidence of those runs today.
Alternatives
- A standalone companion, chosen. A definition and records travel independently of a catalog. Domain labels are data, so the interpreter needs no organisation or person special case.
- An Exchange entry program, option B. This saves no execution work and ties the execution contract to a publication container. Extracting its digested program recreates the standalone document. The maintainer declined it.
- No format change; product composition, option C. Runner jobs and triggers, plus private controller code, can serve one installation. A graph can carry a resulting decision downstream. Neither defines the reviewed subset, child inventory or output relation portably. The maintainer declined C as the standard, leaving it open as a product path that might supply the recording.
- A pack extension or profile. The contract spans several packs and prepares fresh cases; it neither extends one pack's evaluation nor constrains packs to a domain. A Core extension or a profile would put it under a reader that does not acquire or iterate records.
Compatibility
The earlier research amendment left the document form unchanged. This proposed amendment adds
an explicit named-Dialect selector and the required nullable evaluationErrorDigest attempt
member to workflow version 1's still-Draft forms. There are no published workflow instances or
conforming readers to migrate. Readers of the earlier draft must refuse these additions rather
than silently dropping them. Research release encoding is now pinned in §1; its additional
acceptance recording remains due beside the operation demonstration.
Core, the dialect, the graph and the Runner's existing API are unchanged. A standalone pack or
dialect keeps its existing meaning. This RFC defines documents and records, not new endpoints,
trigger kinds or a reinterpretation of a current Runner job. The Runner's openapi.json fixes
jobs to releases and names run input, state and audit at 89cf441; a controller can reuse them.
Workflow admission and retention need implementation of their own.
Output lineage is a new workflow envelope. It is never appended to the dialect's preparation
lineage (RFC 0018 §9.3) or
Core's disposition, whose members
are closed. The separation follows the design memo recorded on issue #160, §3, and
spec/dialect.md §§8.2 and 9: case values stay asserted, source influence within one preparation
stays as specified, and the workflow adds the check across stages.
RFC 0018 §4.4's preparation binding stays unchanged. Workflow records separately retain the
published dialect's digest, the binding document's digest and the resulting bound dialect's
digest. The binding document content-binds the published digest, but no signature establishes that
the signed preparation and record came from that published dialect under that binding (§4).
The Runner's docs/MAPPING-V2.md at 89cf441, "Release checks, runtime and offline verification",
says audit signatures do not cover the export envelope; they gain no workflow-envelope coverage.
Old readers refuse the new envelope; verifying only its embedded preparations is not workflow verification. Existing Desk records remain their own form and can be cited as prior evidence, without inventing selections or receipts during migration. Acceptance and publication will need their own landing changes and a decision about the fixtures' corpus and version; this Draft changes neither Core's artifact list nor any conformance corpus.
Security and privacy
Case bindings disclose only explicitly named values, with a container copy disclosing that container's descendants. Fresh cases inherit nothing else. A selection cannot cite records outside the offered set its digest binds; nothing shows that this set is the only one the installation obtained or offered (§10; dialect §13). Retaining that set exposes unselected records to holders of the bundle too. The proposed fixture uses synthetic opaque ids and no personal data. A digest is not an access-control decision.
There is no workflow script. Earlier-stage dependencies and finite bounds constrain fan-out and resource use; exceeding a bound cannot yield a truncated success. Pack and dialect pins establish content identity only. Relations remain provenance assertions, not proof of the domain statement their labels suggest. Generated-only admission at model-served targets refuses record-class bindings; preserved influence prevents selection from erasing a declared model's contribution. The installation's classification of what a channel actually serves remains a trust assumption. Neither admission nor influence establishes the model's correctness.
A reviewer actor is an installation's assertion, not a verified identity. The Runner's
internal/runner/events.go at 89cf441 states that its actors name mechanisms or the installation,
never a person, and that the journal is unsigned and unchained. Its progress entries are not an
authenticated execution commitment. The operator can rewrite a consistent bundle; existing audit
signatures and run checkpoints cover only their own subjects. The report keeps consistency,
partial completion, preparation agreement and the absence of workflow authentication explicit.
Conformance
Specification §9 defines the reader class; no conformance claim is available while this text is Draft or before fixtures are published. No workflow reader or fixture exists. Section 11 defines one branch's recording layout, with independent expected commitments and expected reports frozen from actual recordings. It requires the positive two-stage run, a second installation, disposition selection, empty outputs, missing and null values, duplicate payloads, ordering and numeric bytes; negative mutations of pins, selections, inventory and influence; bound and fan-out cases; and interruption after admission, uncertain acquisition and retries on either side of consumption. The generated-payload parameter case and deterministic sibling-bound case hold the rules of §§4 and 2 respectively. These are recordings to obtain, not evidence already held.
Implementation
Implementation follows this order; none of these additions is implemented by this Draft:
- Specification: the companion grammar,
workflow-verifierreader contract and fixture layout first. A Runner reader and a separately written specification reader are two plausible implementations. The second should be written from the companion and recorded fixtures without sight of the first reader's code, in another language, with its sources and authorship protocol recorded. That is a proposed independence protocol, not independence already demonstrated. - Runner: the interpreter, durable instances, transactional selection admission, retries, frozen bindings/releases, workflow export and verification. This is the largest part of the cost. Reuse release admission, retained acquisitions, preparation verification and audit replay, preserving their separate claims. Version-3 binding precedes the operation acceptance demonstration. The additional research recording follows fixture 8's plan beside it, using §11's workflow bundle layout, and waits for research preparation, pinned release forms and encoding, and readers of the contract as §§4 and 11 require.
- Desk: generic stage review and relation views, pinned definition display and explicit reviewer assertions. Record the required run from the research line, retaining the answers and the complete offered set, without organisation/person special cases in the Runner.
- Exchange: a versioned workflow entry referencing the standalone definition and its fixtures, last, through a revision of RFC 0019. Runtime and Gateway require no semantic change.
This is the allocation in option A's cost paragraph of the design memo recorded on issue #160. No reader code is added here. Repository tests hold the RFC's Specification equal to the companion, hold the companion's preface to its title and Status, and keep the Draft out of release bundles. They are not workflow conformance tests. The round-1 cross-vendor review and the maintainer's dispositions are recorded on pull request 168; round 2's review and dispositions are the first and second comments on pull request 177. This text applies both rounds' dispositions and the maintainer's producing-stage selection rule, with the runtime-form question addressed by this proposed amendment. Acceptance is not claimed.
Unresolved questions
- An authenticated execution commitment. Which signature or independently retained commitment authenticates the closed execution, selections and the published-dialect/binding association? The binding document content-binds the published digest, but nothing authenticates that the signed preparation and record came from that dialect under that binding (§4). Existing preparation binding remains unchanged; reviewer authentication is separate. The record has an execution id so a future outer commitment need not introduce a digest cycle.
- Published research binding, deferred through operations. How does a published
researchrecipe bind to an installation's AI source? This RFC chooses condition 2's operation path and defines the construction to record in §11; it does not settle research binding or extend its unbound form. The actual two-stage operation demonstration is still missing. What subsequent dialect revision will give research sources a portable binding contract remains open. Resolved 2026-10-15, by decision 2 of issue #174: The dialect §4.4 defines the research binding: the binding document assigns AI and any web profiles, all of classgenerated, against the published model and capabilities. Section 4 conditionally admits that binding for a workflow stage, pending a pinned research-capable release form and encoding. The two-stage operation demonstration remains due under §11; the research recording is additional beside it. - Selection beyond one output per evaluated case. Version 1 permits a closed disposition
predicate only for
one. A many-output case judges the collection; per-candidate decisions need separately prepared cases. Whether to specify a richer rule or a stage for such decisions waits for recordings; no batch disposition stands in for them now. - Joins, recursion and cross-products. All are excluded from version 1, which admits one earlier-stage parent per invocation. Whether any is necessary for portable research, without designing a general workflow engine, requires evidence beyond the motivating chain.
- A non-terminal result. Version 1 requires
resultto name a terminal stage. Whether a published workflow should expose an intermediate result while other stages continue is open. - Evidence and publication. Which Desk implementation supplies the acceptance run, and when do independently written readers agree on the positive, negative and recovery recordings? What specification version and fixture corpus carry their claims? Nothing is recorded yet; repository equality and link checks cannot answer these questions.
- Identity and conservative influence. Version 1 uses record-instance identity, with no inferred entity deduplication, and carries a container's influence into each copied field. Whether narrower field lineage is needed should be decided from recorded cases without weakening generated admission or assigning unproved identities.
- Pinned runtime forms. The proposed amendment names current Runner and Runtime encodings in §1, and §7 defines a separately pinned, exact-byte evaluation-error artifact without changing run exports. Implementation and two-reader agreement on the failure variants remain due; the contract text alone does not close the demonstration requirement.