142 lines
7.2 KiB
Markdown
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.
|