Skip to content

THE INCQL BOOK

7. Make the write decision

Turn evidence into an explicit application decision, then retain an observation about the write attempt.

Part III

Decide what happens next

Chapter 2 of 2

Goal

Read the evidence produced by the earlier stages, decide in ordinary Incan code whether the review may be written, and use write_observed(...) to retain evidence about the concrete sink attempt.

The decision belongs to the caller

IncQL exposes distinct facts:

  • Prism inspection explains the deferred plan.
  • Adapter coverage records what the selected adapter is known to cover.
  • Quality observations report whether explicit data checks passed.
  • Execution observations report what happened during a concrete attempt.

None of those records silently defines your organization's acceptance rule. This checkpoint makes the rule visible in a normal function, so readers can see exactly which evidence permits or prevents the write. Its required_quality list contains the inclusive one-to-three-row check; the deliberately failing deliberate_probe is printed for comparison but is not passed into the gate.

With this example, a rejected required_quality list returns Ok(None) deliberately: the application completed without asking for a write, rather than suffering an execution failure. On the accepted path, csv_sink(output_uri) constructs the typed sink descriptor and write_observed(...) starts a new execution of the plan for that sink attempt. The returned ObservedWrite retains an execution observation and an optional error, but it does not currently bundle the sink URI, row count, quality observations, or coverage records.

One narrow gate · one new write attempt

Show exactly what permits the write

The checkpoint prints coverage and a deliberate strict probe, but its gate reads only required_quality. If that gate passes, write_observed(...) executes the plan again.

  1. 01
    Quality inputsProduce the required check and an explanatory strict probe
    required_quality = session.observe_quality( # (1)!
        plan.clone(),
        [row_count(min_count=Some(1), max_count=Some(3))],
    )
    deliberate_probe = session.observe_quality(
        plan.clone(),
        [row_count(min_count=Some(4))],
    )
    
    1. Separate required evidence from an explanatory probe. required_quality contains the check this tutorial will pass to its gate. deliberate_probe performs another observation with a stricter minimum so you can compare a failed record, but the checkpoint only prints it; that list does not decide whether writing is allowed.

    Owner
    Session quality evaluation
    Artifact
    Passing required evidence and a failing strict probe
    Knowable now
    Each quality call collected the plan again; neither result enforces a write rule
  2. 02
    Caller gateUse only the required quality list
    if not caller_accepts(required_quality): # (1)!
        println("Caller decision: do not write")
        return Ok(None)
    
    1. Make policy ordinary and explicit. caller_accepts(...) is tutorial application code, not an IncQL enforcement hook. A rejected list returns Ok(None) because the application deliberately chose not to request a write; that outcome is distinct from an execution error.

    Owner
    Tutorial application code
    Artifact
    An explicit control-flow decision
    Knowable now
    Coverage and the strict probe are printed for inspection but do not participate in this gate
  3. 03
    Observed writeExecute the accepted plan again and attempt the sink side effect
    output_uri = "target/tutorial-orders.csv"
    written = session.write_observed(
        plan,
        csv_sink(output_uri),
    ) # (1)!
    match written.error: # (2)!
        Some(error) => return Err(error)
        None =>
            println("Caller decision: write the plan accepted by the required policy")
            println(f"wrote: {output_uri}")
    
    1. Describe the sink, then start a new attempt. csv_sink(output_uri) builds a typed CSV SinkTarget; parquet_sink(uri) is the corresponding Parquet alternative. write_observed(...) executes the deferred plan again for this sink attempt and returns an ObservedWrite alongside the file side effect.

    2. Handle the optional typed failure. written.error is Some(SessionError) when the write attempt fails and None when it succeeds. The receipt also retains an execution observation, but it does not currently bundle the URI, row count, quality records, or coverage records.

    Owner
    Session and DataFusion sink path
    Artifact
    ObservedWrite plus the CSV side effect
    Knowable now
    This write attempt returned no typed error
    tutorial-orders.csv ObservedWrite

write_observed(...) owns the sink attempt through the Session and returns an observation plus an optional error. The CSV file is the side effect. The ObservedWrite receipt does not currently carry the sink URI, row count, quality observations, or coverage records, and its observation uses a fallback Substrait-root target rather than the earlier Prism plan target. It therefore must not be presented as an uninterrupted correlation edge or a complete governed-output bundle.

Open the complete Chapter 7 checkpoint
"""Chapter 7: write an accepted plan and preserve write evidence."""

from domain import Order
from pub::incql import (
    LazyFrame,
    QualityObservation,
    QualityObservationStatus,
    Session,
    SessionError,
    csv_sink,
    inspect_lineage,
    inspect_plan,
    report_session_error,
    row_count,
)


def caller_accepts(observations: list[QualityObservation]) -> bool:
    """Return true only when every observation satisfies the caller's policy."""
    for observation in observations:
        if observation.status != QualityObservationStatus.Passed:
            return false
    return true


pub def run_chapter(mut session: Session) -> Result[None, SessionError]:
    """Run the complete typed plan, evidence, decision, and write flow."""
    orders: LazyFrame[Order] = session.read_csv("tutorial_orders", "orders.csv")?
    plan = orders.limit(3)
    inspection = inspect_plan(plan.clone())
    lineage = inspect_lineage(plan.clone())
    observed = session.collect_observed(plan.clone())

    println(f"plan id: {inspection.plan_id}")
    println(f"lineage edges: {len(lineage.edges)}")
    println(f"backend: {observed.observation.backend_name}")
    match observed.data:
        Some(frame) =>
            println(f"columns: {frame.resolved_columns():?}")
            println(f"rows: {frame.row_count()}")
            println(frame.preview_text())
        None =>
            match observed.error:
                Some(error) => return Err(error)
                None => println("collect_observed returned no data and no typed error")

    coverage = session.check_plan_coverage(plan.clone())
    println(f"coverage records: {len(coverage)}")
    for record in coverage:
        println(f"- {record.requirement.capability.value()}: {record.state.value()}")

    required_quality = session.observe_quality(plan.clone(), [row_count(min_count=Some(1), max_count=Some(3))])
    deliberate_probe = session.observe_quality(plan.clone(), [row_count(min_count=Some(4))])
    println(f"required quality: {required_quality[0].status.value()}")
    println(f"deliberate strict probe: {deliberate_probe[0].status.value()}")
    println(f"caller would accept strict probe: {caller_accepts(deliberate_probe)}")

    if not caller_accepts(required_quality):
        println("Caller decision: do not write")
        return Ok(None)

    output_uri = "target/tutorial-orders.csv"
    written = session.write_observed(plan, csv_sink(output_uri))
    match written.error:
        Some(error) => return Err(error)
        None =>
            println("Caller decision: write the plan accepted by the required policy")
            println(f"wrote: {output_uri}")
    return Ok(None)


def main() -> None:
    mut session = Session.default()
    match run_chapter(session):
        Ok(_) => println("Chapter 7: observed write completed")
        Err(error) => report_session_error("tutorial.chapter_07", error)

Run it:

incan run src/chapter_07.incn

The run reports two coverage records—null_semantics: covered and lineage_preservation: uncovered—but does not gate on them. It reports passed for the required quality check and failed for the strict probe, then writes target/tutorial-orders.csv because the required list passed. Inspect that CSV as an output artifact, not as typed Order iteration.

Read the completed system path

You have now followed one real LazyFrame through the current IncQL path:

  1. The author supplied a logical CSV source and intended row model.
  2. IncQL stored deferred relational intent in a Prism-backed plan.
  3. Local inspection exposed schema, plan, and lineage evidence before execution.
  4. Session lowered and bound the plan, then dispatched DataFusion.
  5. Execution, coverage, and quality records answered different questions about the result.
  6. Caller-owned code made the acceptance decision and asked Session to write.

Substrait remains the portable logical-plan boundary in that path. The earlier collection observation retains its plan correlation, and the quality observations reference their own execution attempts. The final write receipt currently starts from a fallback Substrait-root target, so the book does not draw a continuous evidence edge from the earlier Prism plan through that write.

Try it

Pass the coverage records into a new caller-owned gate so an Unknown state also blocks writing. Print the reason for the decision, run both branches, and restore the checkpoint. Notice that the unmodified chapter does not gate on coverage and that you changed application policy without changing the evidence record types.

Core path complete

You can build, inspect, execute, evaluate, and write one IncQL plan while explaining which layer owns each decision. Continue with Part IV to author checked SQL-familiar query blocks without method chains, Guides for task-specific transformations, Reference for exact contracts, or Architecture for the full system story.