Ordered collections¶
A renderflow/v2 collection names immutable local artifacts in the exact order a
collection-input transform receives them. The public renderflow spec validate,
renderflow build --dry-run, renderflow build, and Rust
planning::{resolve, execute} surfaces use the same canonical plan and run
evidence. The exact print-interior PDF and
fixed-layout EPUB routes each consume homogeneous PNG or
JPEG page collections under separate policies. Neither route takes an implicit
file-system directory order as publication order.
schema: renderflow/v2
sources:
- id: source.page001
path: pages/001.md
format: markdown
media_type: text/markdown
sha256: "<64 lowercase hex characters for the exact file bytes>"
geometry: { width: 210, height: 297, unit: mm }
- id: source.page002
path: pages/002.md
format: markdown
media_type: text/markdown
sha256: "<64 lowercase hex characters for the exact file bytes>"
geometry: { width: 210, height: 297, unit: mm }
- id: source.pages
kind: collection
members: [source.page001, source.page002]
targets:
exact:
- format: html
role: web
transforms: transforms.yaml
output:
bundle_root: dist
Each member ID must be unique. Its path is relative to the spec directory,
with no absolute path, .., . component, or symlink in the path. A member
must declare a known common format, a media type supported for that format,
and its exact SHA-256 digest. Geometry is optional at this stage, but if
declared it must have positive dimensions and participates in identity. The
selected collection must name every declared artifact exactly once. Nested or
multiple collection sources are unsupported. No glob or directory discovery
chooses membership for you.
The transform registry must provide a collection-input edge from the common member format to a distinct output format:
transforms:
- name: synthetic.ordered-pages
program: python3
args: ["aggregate.py", "{output}", "{inputs}"]
input_kind: collection
from: markdown
to: html
cost: 1.0
quality: 1.0
The example command is a synthetic fixture, not a publication capability.
The runnable fixture and parameterized 44-member recipe are exercised by
ordered_collection and ordered_collection_cli tests. A real transform
must provide its own output validation and provider contract.
Planning imports each source into temporary content-addressed staging and
freezes the ordered member IDs, locators, media types, format, geometry,
digests, sizes, and intake profiles in plan.source_collection. The plan
digest names the collection cache namespace and, with the full source-spec
digest, binds checkpoint context and run evidence; the ordered input artifact
list binds transform checkpoints. Execution checks
paths again and imports every member into the durable artifact store before
running a transform. A changed or substituted member produces failed run
evidence and no committed target output.
Run artifact evidence records each member's renderflow.source_id,
renderflow.collection.id, renderflow.collection.index, locator, and
geometry. Aggregated outputs list input artifact IDs in declared order. When
identical member bytes share one content-addressed artifact ID, the distinct
member IDs and indices remain in the frozen plan and source evidence. The
source files are never written by this lifecycle. Resume accepts only a
checkpoint whose plan, source spec, inputs, and provider evidence remain
compatible; otherwise it recomputes or refuses under the existing checkpoint
rules.
The currently supported canonical execution path requires all root collection members to share a format and the first edge to consume a collection. Mixed media, same-format aggregation output, arbitrary root fan-out, and publication approval remain outside this checkpoint. The bounded image-based PDF and EPUB routes enforce their own input, metadata, and output constraints.