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

142 lines
7.2 KiB
Markdown

# 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.