Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ schema: aether.architecture-document/v1
id: renderflow-roadmap
title: Renderflow Roadmap
kind: architecture-document
version: 0.1.2
version: 0.1.3
status: draft
owners:
- egohygiene
created: 2026-08-19
updated: 2026-09-25
updated: 2026-09-27
governed_by:
- architecture-roadmap
depends_on:
Expand All @@ -26,6 +26,21 @@ supersedes: []

# Renderflow Roadmap

## 2026-09-27 ordered collection review handoff

Checkpoint #415 adds canonical planning and execution for one explicitly
ordered, homogeneous local artifact collection. Members require stable IDs,
root-relative locators, declared formats/media types, and SHA-256 digests;
optional geometry enters plan identity. Planning freezes member evidence,
execution rechecks paths and bytes, and run evidence records source order and
aggregate lineage. The two-page synthetic fixture and generated 44-member
recipe prove the public SDK and CLI paths without claiming PDF or EPUB output.

After review and merge, #416 (print PDF) and #417 (fixed-layout EPUB) may
proceed independently. #418 validates the EPUB capability, and #419 publishes
the immutable release consumed by Flow #52. No real publication artifacts or
personal media were processed by the #415 tests.

## 2026-09-25 live suite handoff

> [!IMPORTANT]
Expand Down
4 changes: 4 additions & 0 deletions crates/renderflow-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ serde_json = "1"
name = "cli_tests"
path = "../../tests/cli_tests.rs"

[[test]]
name = "ordered_collection_cli"
path = "../../tests/ordered_collection_cli.rs"

[[test]]
name = "graph_integration_test"
path = "../../tests/graph_integration_test.rs"
Expand Down
2 changes: 1 addition & 1 deletion crates/renderflow-core/benches/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ fn bench_transform_cache_lookup(c: &mut Criterion) {
fn bench_transform_cache_insert(c: &mut Criterion) {
c.bench_function("transform_cache/insert", |b| {
b.iter_batched(
|| TransformCache::default(),
TransformCache::default,
|mut cache| {
cache.insert("abc123".to_string(), "transformed output".to_string());
cache
Expand Down
32 changes: 31 additions & 1 deletion crates/renderflow-core/src/graph/dag_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,36 @@ impl DagExecutor {
.into_result()
}

/// Execute an ordered collection and retain step evidence for canonical runs.
/// The root collection stays in the caller's source evidence; every derived
/// format must resolve to one artifact for the current output lifecycle.
pub fn execute_collection_with_evidence(
&self,
dag: &MultiTargetDag,
source_format: Format,
initial_artifacts: ArtifactCollection,
store: &ArtifactStore,
) -> Result<DagExecutionReport> {
let report =
self.execute_artifacts_with_evidence(dag, source_format, initial_artifacts, store)?;
let artifacts = report
.artifacts
.into_iter()
.filter(|(format, _)| *format != source_format)
.map(|(format, collection)| {
let artifact = collection.into_one().with_context(|| {
format!("Format '{format}' produced multiple artifacts where one was expected")
})?;
Ok((format, artifact))
})
.collect::<Result<HashMap<_, _>>>()?;
Ok(DagExecutionReport {
artifacts,
steps: report.steps,
diagnostics: report.diagnostics,
})
}

fn execute_artifacts_with_evidence(
&self,
dag: &MultiTargetDag,
Expand Down Expand Up @@ -1111,7 +1141,7 @@ impl DagExecutor {
output,
transform.name().to_string(),
"unstable-v1".to_string(),
sha256_text(transform.name()),
edge_configuration_digest(edge),
None,
))
}
Expand Down
22 changes: 22 additions & 0 deletions crates/renderflow-core/src/graph/execution_plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,24 @@ pub struct PlanSourceArtifact {
pub profile: ResolvedArtifactProfile,
}

/// Ordered, explicitly declared collection identity frozen at planning time.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlanSourceCollection {
pub source_id: String,
pub members: Vec<PlanCollectionMember>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlanCollectionMember {
pub source_id: String,
pub locator: String,
pub media_type: String,
pub format: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub geometry: Option<crate::publication::PageGeometry>,
pub artifact: PlanSourceArtifact,
}

impl From<&IntakeReport> for PlanSourceArtifact {
fn from(report: &IntakeReport) -> Self {
Self {
Expand Down Expand Up @@ -288,6 +306,9 @@ pub struct ExecutionPlan {
/// Source identity and multi-signal evidence established before planning.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_artifact: Option<PlanSourceArtifact>,
/// Present instead of `source_artifact` for a declared ordered collection.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_collection: Option<PlanSourceCollection>,
/// Reproducible evidence for providers selected by this exact plan.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub toolchain: Option<ToolchainSnapshot>,
Expand Down Expand Up @@ -405,6 +426,7 @@ impl ExecutionPlan {
metadata,
diagnostics,
source_artifact: None,
source_collection: None,
toolchain: None,
artifact_forest: None,
}
Expand Down
2 changes: 1 addition & 1 deletion crates/renderflow-core/src/graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub use definition::TransformDefinition;
pub use definition_registry::TransformDefinitionRegistry;
pub use execution_plan::{
ArtifactForest, DiagnosticLevel, ExecutionPlan, ForestBranch, ForestBranchState,
PlanSourceArtifact,
PlanCollectionMember, PlanSourceArtifact, PlanSourceCollection,
};
pub use format::Format;
pub use input_kind::InputKind;
Expand Down
Loading
Loading