pub struct Engine<'a> {
pub renderer: &'a dyn Renderer,
pub clusterer: &'a dyn WorkstreamClusterer,
pub redactor: &'a dyn Redactor,
pub render_profiles: bool,
}Expand description
The orchestration engine that wires ingestors, clusterers, redactors, and renderers.
This is the main coordination layer between the CLI and the adapter crates.
Construct one via Engine::new, then call Engine::run, Engine::refresh,
or Engine::import to execute the pipeline.
Fields§
§renderer: &'a dyn RendererThe renderer used to produce Markdown packets.
clusterer: &'a dyn WorkstreamClustererThe clusterer used to group events into workstreams.
redactor: &'a dyn RedactorThe redactor used to produce manager/public profiles.
render_profiles: boolWhether manager/public profile packets should be rendered.
Implementations§
Source§impl<'a> Engine<'a>
impl<'a> Engine<'a>
Sourcepub fn new(
renderer: &'a dyn Renderer,
clusterer: &'a dyn WorkstreamClusterer,
redactor: &'a dyn Redactor,
) -> Self
pub fn new( renderer: &'a dyn Renderer, clusterer: &'a dyn WorkstreamClusterer, redactor: &'a dyn Redactor, ) -> Self
Create a new engine with the given renderer, clusterer, and redactor.
§Examples
use shiplog_engine::Engine;
use shiplog_ports::{Renderer, WorkstreamClusterer, Redactor};
let engine = Engine::new(renderer, clusterer, redactor);Sourcepub fn with_profile_rendering(self, render_profiles: bool) -> Self
pub fn with_profile_rendering(self, render_profiles: bool) -> Self
Return an engine configured to render or skip manager/public profile packets.
Profile rendering is enabled by default. Disable it for internal-only outputs when no real redaction key is available.
Sourcepub fn run(
&self,
ingest: IngestOutput,
user: &str,
window_label: &str,
out_dir: &Path,
zip: bool,
bundle_profile: &BundleProfile,
) -> Result<(RunOutputs, WorkstreamSource)>
pub fn run( &self, ingest: IngestOutput, user: &str, window_label: &str, out_dir: &Path, zip: bool, bundle_profile: &BundleProfile, ) -> Result<(RunOutputs, WorkstreamSource)>
Run the full pipeline: ingest → cluster → render.
Uses WorkstreamManager to respect user-curated workstreams.
§Examples
use shiplog_engine::Engine;
use shiplog_ports::{IngestOutput, Renderer, WorkstreamClusterer, Redactor};
use shiplog_schema::bundle::BundleProfile;
use std::path::Path;
let engine = Engine::new(renderer, clusterer, redactor);
let (outputs, ws_source) = engine.run(
ingest,
"octocat",
"2025-01-01..2025-04-01",
Path::new("./out/run_123"),
false,
&BundleProfile::Internal,
)?;
println!("Packet written to {:?}", outputs.packet_md);Sourcepub fn run_with_profile_rendering(
&self,
ingest: IngestOutput,
user: &str,
window_label: &str,
out_dir: &Path,
zip: bool,
bundle_profile: &BundleProfile,
render_profiles: bool,
) -> Result<(RunOutputs, WorkstreamSource)>
pub fn run_with_profile_rendering( &self, ingest: IngestOutput, user: &str, window_label: &str, out_dir: &Path, zip: bool, bundle_profile: &BundleProfile, render_profiles: bool, ) -> Result<(RunOutputs, WorkstreamSource)>
Run the full pipeline with explicit control over manager/public profile rendering.
Set render_profiles to false for internal-only outputs when no real
redaction key is available. Manager and public bundle profiles require
profile rendering because those bundles include redacted packet paths.
Sourcepub fn import(
&self,
ingest: IngestOutput,
user: &str,
window_label: &str,
out_dir: &Path,
zip: bool,
workstreams: Option<WorkstreamsFile>,
bundle_profile: &BundleProfile,
) -> Result<(RunOutputs, WorkstreamSource)>
pub fn import( &self, ingest: IngestOutput, user: &str, window_label: &str, out_dir: &Path, zip: bool, workstreams: Option<WorkstreamsFile>, bundle_profile: &BundleProfile, ) -> Result<(RunOutputs, WorkstreamSource)>
Import a pre-built ledger and run the full render pipeline.
When workstreams is Some, uses them directly (writes as curated).
When None, falls through to normal clustering.
§Examples
use shiplog_engine::Engine;
use shiplog_ports::{IngestOutput, Renderer, WorkstreamClusterer, Redactor};
use shiplog_schema::bundle::BundleProfile;
use std::path::Path;
let engine = Engine::new(renderer, clusterer, redactor);
let (outputs, _) = engine.import(
ingest,
"octocat",
"2025-01-01..2025-04-01",
Path::new("./out/import_run"),
false,
None, // or Some(workstreams) to supply pre-built workstreams
&BundleProfile::Internal,
)?;Sourcepub fn import_with_profile_rendering(
&self,
ingest: IngestOutput,
user: &str,
window_label: &str,
out_dir: &Path,
zip: bool,
workstreams: Option<WorkstreamsFile>,
bundle_profile: &BundleProfile,
render_profiles: bool,
) -> Result<(RunOutputs, WorkstreamSource)>
pub fn import_with_profile_rendering( &self, ingest: IngestOutput, user: &str, window_label: &str, out_dir: &Path, zip: bool, workstreams: Option<WorkstreamsFile>, bundle_profile: &BundleProfile, render_profiles: bool, ) -> Result<(RunOutputs, WorkstreamSource)>
Import a pre-built ledger with explicit control over manager/public profile rendering.
Set render_profiles to false for internal-only outputs when no real
redaction key is available. Manager and public bundle profiles require
profile rendering because those bundles include redacted packet paths.
Sourcepub fn refresh(
&self,
ingest: IngestOutput,
user: &str,
window_label: &str,
out_dir: &Path,
zip: bool,
bundle_profile: &BundleProfile,
) -> Result<RunOutputs>
pub fn refresh( &self, ingest: IngestOutput, user: &str, window_label: &str, out_dir: &Path, zip: bool, bundle_profile: &BundleProfile, ) -> Result<RunOutputs>
Refresh receipts and stats without regenerating workstreams.
This preserves user curation while updating event data.
§Examples
use shiplog_engine::Engine;
use shiplog_ports::{IngestOutput, Renderer, WorkstreamClusterer, Redactor};
use shiplog_schema::bundle::BundleProfile;
use std::path::Path;
let engine = Engine::new(renderer, clusterer, redactor);
// out_dir must already contain workstreams.yaml or workstreams.suggested.yaml
let outputs = engine.refresh(
ingest,
"octocat",
"2025-01-01..2025-04-01",
Path::new("./out/existing_run"),
false,
&BundleProfile::Internal,
)?;Sourcepub fn refresh_with_profile_rendering(
&self,
ingest: IngestOutput,
user: &str,
window_label: &str,
out_dir: &Path,
zip: bool,
bundle_profile: &BundleProfile,
render_profiles: bool,
) -> Result<RunOutputs>
pub fn refresh_with_profile_rendering( &self, ingest: IngestOutput, user: &str, window_label: &str, out_dir: &Path, zip: bool, bundle_profile: &BundleProfile, render_profiles: bool, ) -> Result<RunOutputs>
Refresh receipts and stats with explicit control over manager/public profile rendering.
Set render_profiles to false for internal-only outputs when no real
redaction key is available. Manager and public bundle profiles require
profile rendering because those bundles include redacted packet paths.
Sourcepub fn merge(
&self,
ingest_outputs: Vec<IngestOutput>,
resolution: ConflictResolution,
) -> Result<IngestOutput>
pub fn merge( &self, ingest_outputs: Vec<IngestOutput>, resolution: ConflictResolution, ) -> Result<IngestOutput>
Merge events from multiple sources with deduplication and conflict resolution.
This function:
- Deduplicates events by ID
- Resolves conflicts for events that appear in multiple sources
- Merges coverage manifests from all sources
- Sorts events by timestamp
§Examples
use shiplog_engine::{Engine, ConflictResolution};
use shiplog_ports::{IngestOutput, Renderer, WorkstreamClusterer, Redactor};
let engine = Engine::new(renderer, clusterer, redactor);
let merged = engine.merge(
vec![output_a, output_b],
ConflictResolution::PreferMostRecent,
)?;
println!("Merged {} events", merged.events.len());