Files
notarius/docs/adr/0005-cache-canonical-chunk-plans-by-source.md

7.2 KiB

ADR-0005: Cache one canonical chunk plan per source

Status: Accepted Date: 2026-07-17

Context

Notarius may run several extraction passes over the same source. A D&D transcript, for example, may first produce NPC artifacts and later produce spell or combat artifacts, with output from an earlier pass supplied as a reference to a later pass.

An LLM-backed chunker may process an entire, potentially large source in one expensive request. Recomputing boundaries for every pipeline or pass repeats that cost and can make otherwise comparable extraction runs use different source partitions. Stable chunk material also gives later extraction requests a better opportunity to benefit from provider-side prompt caching.

Chunk boundaries can affect extraction quality. Evidence may span a boundary, overlap may produce duplicates, and different partitions may change the context available to a model. Merge and normalization should remove structural signs of chunking from durable output, but they cannot guarantee recovery of evidence that an extractor did not receive.

Notarius therefore needs an explicit policy for choosing between automatically applying the latest chunking configuration and preserving one stable partition for repeated work on the same source.

Decision

Notarius assigns one active canonical chunk plan to a source and reuses that plan by default across pipelines and invocations.

The canonical source identity is derived from the validated generic source document and covers the source-unit identity, order, and content needed to interpret plan boundaries. Input-adapter and chunk-producer identities are recorded as provenance, but the active-plan lookup does not vary with:

  • pipeline identity or selected artifact lanes;
  • the configured chunk module or its options;
  • references;
  • LLM provider, model, profile, prompt, or response schema; or
  • configuration for later pipeline stages.

When an active plan exists, Notarius uses it even if the current pipeline configures a different chunk module or different chunk-module settings. The configured chunk module generates a plan only when none exists or when the operator explicitly requests recomputation.

The framework-owned minimum plan contract is an ordered, non-empty set of source-unit ranges. Each range identifies the inclusive start and end unit for one chunk. A chunk module may also provide namespaced, domain-specific annotations at plan or range scope. Those annotations are stored with the plan and passed through the pipeline when present, but they remain optional. Downstream stages must not assume that annotations associated with the currently configured chunk module are present on a reused plan produced by a different module.

The cache stores the plan rather than fully materialized chunks. The framework validates a reused plan against the current source and deterministically materializes its ranges into chunks. The same source and plan must produce byte-stable chunk input for later stages.

Canonical plan storage is a distinct cache surface with an independently configurable location. It is not coupled to the roots or lifecycles of invocation checkpoints, diagnostics, debug artifacts, or durable output. This allows per-user and system-service deployments to apply cache-specific ownership, permissions, placement, and cleanup policy without relocating other Notarius state.

One mutable active plan is stored under the canonical source identity and retains provenance for the module and relevant runtime inputs that produced it. Refreshing the active plan atomically replaces that one mutable record; readers must observe either the previous complete plan or the replacement complete plan, never a partial update. The effective plan producer is reported separately from the chunk module requested by the current pipeline; reuse must not attribute cached boundaries or annotations to a module that did not produce them.

Reuse is enabled by default. Operators can explicitly:

  • bypass cached plans for an invocation without changing the active plan; or
  • recompute a plan with the configured chunk module and make it active for later work.

Exact storage layout, configuration fields, CLI syntax, publication mechanics, recovery behavior, and diagnostics are implementation and operational contracts rather than part of this decision.

Alternatives considered

  • Recompute chunks on every invocation. This always applies the current chunking configuration, but repeats the most expensive stage and weakens provider-side caching and cross-pass comparability.
  • Cache every distinct chunking request by including module options, references, prompts, profiles, and other runtime inputs in its identity. This closely associates a cached result with its producing request, but reduces reuse and permits boundary drift across operationally different passes.
  • Key plans by source plus chunk module and options. This shares plans across pipelines using the same strategy, but changing the configured strategy silently selects a different partition rather than preserving one canonical partition for the source.
  • Require operators to name or supply a plan for every run. Explicit selection is reproducible and may be useful as an advanced operation, but adds friction to the default workflow and does not provide automatic reuse.
  • Store fully materialized chunks. This simplifies loading, but duplicates source content and couples durable state to the current chunk representation rather than the stable boundary decision.
  • Store canonical plans beneath the general workspace root. This would reuse an existing location setting, but it couples a reusable application cache to checkpoint, diagnostic, and debug state that have different ownership, sensitivity, retention, and deployment requirements.

Consequences

Independent pipelines and passes over the same source use stable boundaries by default. This reduces repeated LLM work, improves cross-pass comparability, and increases the opportunity for cached provider reads.

The configured chunk module may not execute, and its settings may have no effect, when an active plan already exists. Domain-specific annotations reflect the plan's original producer and may be absent or differ from those the current module would produce. User-visible provenance must make the effective plan clear.

A poor or outdated partition remains active until an operator replaces it. This can preserve suboptimal context boundaries and affect extraction recall or duplication even when merge and normalization hide the partition structure in durable output. Stable reuse is an intentional priority over automatically incorporating later chunk-strategy changes.

The framework gains a durable minimal chunk-plan contract and deterministic materialization responsibility. Chunk modules must separate required boundary output from optional annotations, and downstream modules may rely only on the minimal boundary contract unless a future decision introduces an explicit plan compatibility mechanism.

Operators must configure and secure canonical plan storage independently from other workspace state when the per-user default is not appropriate. Removing that cache remains recoverable because Notarius can regenerate it from the source, but doing so may repeat an expensive LLM operation.