Revise the architecture plan to reflect an input -> chunk -> process -> merge -> normalize -> output workflow

This commit is contained in:
2026-07-03 08:54:23 -05:00
parent 32be4ee85e
commit 88042174b3
10 changed files with 426 additions and 160 deletions

View File

@@ -25,17 +25,27 @@ contracts that can be exercised by tests and real modules.
The core framework must remain source-agnostic and domain-agnostic. The core framework must remain source-agnostic and domain-agnostic.
Source-format details belong in input adapters. Transcript-specific concepts Source-format details belong in input modules. Transcript-specific concepts
such as segments, speakers, timestamps, and transcript schemas must not spread such as segments, speakers, timestamps, and transcript schemas must not spread
into runner, extractor, or validator framework code. into runner, extractor, or validator framework code.
Extraction-domain details belong in extractor packages. D&D-specific concepts Extraction-domain details belong in process modules. D&D-specific concepts
such as spells, NPCs, items, combat turns, and encounters must not spread into such as spells, NPCs, items, combat turns, and encounters must not spread into
core source, runner, or LLM framework packages. core source, runner, or LLM framework packages.
Extracted facts should be grounded with source references. Source references Extracted facts should be grounded with source references. Source references
should point to generic source units, not to transcript-only structures. should point to generic source units, not to transcript-only structures.
The application workflow is:
```text
input -> chunk -> process -> merge -> normalize -> output
```
These stages should remain explicit in the architecture. Chunking, merging, and
normalization must not be hidden inside domain process modules when they represent
general pipeline behavior.
## Dependency Policy ## Dependency Policy
Prefer the Go standard library where practical. Prefer the Go standard library where practical.
@@ -69,16 +79,15 @@ Core deterministic model and policy:
- `internal/core/inputcatalog`: known input adapter keys and metadata. - `internal/core/inputcatalog`: known input adapter keys and metadata.
- `internal/core/extractorcatalog`: known extractor keys and metadata. - `internal/core/extractorcatalog`: known extractor keys and metadata.
External source and provider adapters:
- `internal/adapters/input/<name>`: source-format adapters that parse external input into core source documents.
- `internal/transport/http`: shared HTTP client code, if needed by provider integrations.
Reusable framework plumbing: Reusable framework plumbing:
- `internal/framework/contracts`: core interfaces and transport-neutral request/response contracts. - `internal/framework/contracts`: core interfaces and transport-neutral request/response contracts.
- `internal/framework/runner`: orchestration across adapters, extractors, validators, and artifact output. - `internal/framework/runner`: orchestration across adapters, extractors, validators, and artifact output.
- `internal/framework/pipeline`: shared pipeline-stage orchestration types, when needed.
- `internal/framework/extraction`: shared extraction helper code. - `internal/framework/extraction`: shared extraction helper code.
- `internal/framework/merge`: shared merge-stage behavior.
- `internal/framework/normalize`: shared normalization-stage behavior.
- `internal/framework/output`: output encoding contracts and shared helpers.
- `internal/framework/validators`: shared validator runtime behavior and decision checks. - `internal/framework/validators`: shared validator runtime behavior and decision checks.
- `internal/framework/llm`: LLM runtime, scheduling, and provider adapters. - `internal/framework/llm`: LLM runtime, scheduling, and provider adapters.
- `internal/framework/responseschema`: embedded structured-output schema registry. - `internal/framework/responseschema`: embedded structured-output schema registry.
@@ -88,35 +97,62 @@ Reusable framework plumbing:
Domain implementations: Domain implementations:
- `internal/extractors/<domain>/<extractor>`: domain-specific extractor packages. - `internal/modules/input/<name>`: input-stage modules that parse external input into core source documents.
- `internal/modules/chunk/<name>`: chunk-stage modules.
- `internal/modules/process/<domain>/<name>`: process-stage extractor modules.
- `internal/modules/merge/<name>` or `internal/modules/merge/<domain>/<name>`: merge-stage modules.
- `internal/modules/normalize/<name>` or `internal/modules/normalize/<domain>/<name>`: normalize-stage modules.
- `internal/modules/output/<name>`: output-stage modules.
- `internal/validators/<validator>`: built-in validator implementations. - `internal/validators/<validator>`: built-in validator implementations.
- `internal/prompts`: embedded prompt assets and prompt metadata registry. - `internal/prompts`: embedded prompt assets and prompt metadata registry.
- `internal/transport/http`: shared HTTP client code, if needed by provider integrations.
Package-private implementation constants may live near the package that owns Package-private implementation constants may live near the package that owns
them, preferably in `constants.go` when useful. them, preferably in `constants.go` when useful.
## Input Adapters ## Stage Modules
Concrete business logic should live under `internal/modules/<stage>/...`.
Stage-oriented module layout is preferred because it makes the application
workflow visible in the filesystem:
```text
internal/modules/input/...
internal/modules/chunk/...
internal/modules/process/...
internal/modules/merge/...
internal/modules/normalize/...
internal/modules/output/...
```
Use short, lowercase, idiomatic Go package names. Prefer names such as
`dndtranscript`, `appendorder`, and `spells` over names like `dnd_transcript`,
`serial_merge`, or `spell_extractor` that repeat parent-stage context.
## Input Modules
Use a hexagonal architecture style for source input. Use a hexagonal architecture style for source input.
Input adapters translate external source formats into the core source model. Input modules translate external source formats into the core source model.
Adapters may know about external schema details, source-specific metadata, and They may know about external schema details, source-specific metadata, and
format-specific validation rules. They should not own extraction-domain format-specific validation rules. They should not own extraction-domain
decisions. decisions.
Other packages should interact with source input through adapter contracts and Other packages should interact with source input through adapter contracts and
core source types. Adapter implementation details and external dependency types core source types. Input module implementation details and external dependency
must not leak into framework or extractor packages. types must not leak into framework or process module packages.
Adapter metadata may preserve source-specific facts such as transcript speaker, Input module metadata may preserve source-specific facts such as transcript speaker,
timestamps, Markdown heading path, page number, or block ID. Framework code may timestamps, Markdown heading path, page number, or block ID. Framework code may
carry metadata through, but should not require a specific adapter's metadata carry metadata through, but should not require a specific adapter's metadata
shape. shape.
## Extractors ## Extractors
Extractors are independent modules that produce one kind of structured artifact. Extractors are independent modules that process source chunks or whole source
Each extractor package owns: documents and produce one kind of structured artifact candidate.
Each process module owns:
- its artifact semantics; - its artifact semantics;
- its prompt usage; - its prompt usage;
@@ -124,8 +160,13 @@ Each extractor package owns:
- its validator chain; - its validator chain;
- any domain-specific mapping or interpretation. - any domain-specific mapping or interpretation.
Extractors should depend on framework contracts and core source/artifact types. Process modules should depend on framework contracts and core source/artifact
They should not depend on concrete input adapter packages. types. They should not depend on concrete input module packages.
Extractors should not be the only place where chunking, merging, or
normalization happens. They may choose processing mode or provide domain-specific
merge/normalization behavior when generic behavior is insufficient, but the
pipeline stages themselves are framework concepts.
The runner should be able to compose, skip, resume, or run individual extractors The runner should be able to compose, skip, resume, or run individual extractors
when their prerequisites are satisfied. Ordering should be explicit through when their prerequisites are satisfied. Ordering should be explicit through
@@ -134,6 +175,31 @@ configuration, a default sequence, or documented orchestration rules.
Extractor selection must go through a registry or equivalent mechanism rather Extractor selection must go through a registry or equivalent mechanism rather
than scattered conditionals. than scattered conditionals.
## Pipeline Stages
The pipeline has six conceptual stages:
1. input: external source material becomes a `SourceDocument`;
2. chunk: a `SourceDocument` becomes ordered source chunks;
3. process: extractors produce artifact candidates from chunks or whole documents;
4. merge: per-chunk candidates become a merged candidate collection;
5. normalize: merged candidates are reconciled for duplicates, aliases, consistency, or cross-chunk issues;
6. output: final artifacts are serialized.
Chunking is first-class because source documents may be too large for a single
LLM pass. Chunkers should preserve source-unit order and produce stable chunk
metadata.
Merge and normalize are separate concerns. Merge combines per-chunk results into
a deterministic collection. Normalize performs semantic reconciliation after
merge. Generic append-in-chunk-order merge and no-op normalization should be
available for simple artifact types, while domain-specific behavior can be
provided where needed.
The framework should allow serial and parallel chunk processing. The first
implementation may execute chunks serially for determinism, but contracts should
not prevent later parallel execution.
## Validators ## Validators
Validators should be independently testable and composable. Validators should be independently testable and composable.
@@ -181,8 +247,8 @@ Configuration files should not contain raw secrets unless the application is
explicitly designed for that. Prefer environment variables or secret files for explicitly designed for that. Prefer environment variables or secret files for
secrets. secrets.
Adapter-specific and extractor-specific configuration should remain grouped by Stage-module-specific configuration should remain grouped by the module that
the adapter or extractor that owns it. owns it.
## Embedded Assets ## Embedded Assets
@@ -242,12 +308,12 @@ focused on implemented behavior. Put future, planned, or aspirational work only
under `docs/roadmap/`. under `docs/roadmap/`.
Core documentation should use generic terms such as source document, source Core documentation should use generic terms such as source document, source
unit, source reference, input adapter, extractor, artifact, validator, and run unit, source reference, input adapter, extractor, chunker, merger, normalizer,
manifest. artifact, validator, and run manifest.
Source-format details belong in adapter or integration docs. Domain-specific Source-format details belong in input module or integration docs.
extraction details belong in extractor or artifact docs. Domain-specific extraction details belong in process module or artifact docs.
When changing architecture, config, CLI behavior, adapters, extractor contracts, When changing architecture, config, CLI behavior, stage modules, extractor
validator contracts, LLM runtime behavior, or artifact schemas, update the contracts, validator contracts, LLM runtime behavior, or artifact schemas, update
relevant docs and examples in the same change. the relevant docs and examples in the same change.

View File

@@ -25,8 +25,8 @@ In scope:
Out of scope: Out of scope:
- real input adapters; - real input modules;
- real extractors; - real process modules;
- LLM provider calls; - LLM provider calls;
- prompt or response-schema assets; - prompt or response-schema assets;
- diagnostics run directory; - diagnostics run directory;
@@ -47,7 +47,7 @@ contract packages:
structured LLM interfaces used by later checkpoints. structured LLM interfaces used by later checkpoints.
The contracts should be proven with fake implementations in tests. Those tests The contracts should be proven with fake implementations in tests. Those tests
should demonstrate composition without real source adapters, real extractors, should demonstrate composition without real input modules, real process modules,
LLM provider calls, prompt assets, or diagnostics infrastructure. LLM provider calls, prompt assets, or diagnostics infrastructure.
Implementation staging belongs in Implementation staging belongs in

View File

@@ -6,8 +6,8 @@ This document describes planned work, not implemented behavior.
## Goal ## Goal
Prove the core contracts compose before adding real adapters, real extractors, Prove the core contracts compose before adding real stage modules or portable
or portable Audita infrastructure. Audita infrastructure.
This checkpoint should produce a minimal runner that can execute fake registered This checkpoint should produce a minimal runner that can execute fake registered
components from source input to artifact output in tests. components from source input to artifact output in tests.
@@ -26,6 +26,8 @@ In scope:
Out of scope: Out of scope:
- real input parsing; - real input parsing;
- real input modules;
- real process modules;
- real LLM calls; - real LLM calls;
- prompt assets; - prompt assets;
- response schema assets; - response schema assets;
@@ -47,8 +49,8 @@ The repository should contain a minimal framework composition layer:
artifacts. artifacts.
The runner should operate on already parsed source documents in this checkpoint. The runner should operate on already parsed source documents in this checkpoint.
Raw input parsing and concrete input adapter behavior remain deferred to the Raw input parsing and concrete input module behavior remain deferred to the
Seriatim adapter checkpoint. Seriatim input module checkpoint.
Implementation staging belongs in Implementation staging belongs in
[`implementation.md`](implementation.md). [`implementation.md`](implementation.md).
@@ -58,7 +60,7 @@ Implementation staging belongs in
- `go test ./...` passes. - `go test ./...` passes.
- Fake adapter/extractor/validator registrations work in tests. - Fake adapter/extractor/validator registrations work in tests.
- The runner operates on `SourceDocument`, not transcript-specific structures. - The runner operates on `SourceDocument`, not transcript-specific structures.
- The runner does not import concrete D&D extractor packages. - The runner does not import concrete D&D process module packages.
## Review Questions ## Review Questions

View File

@@ -0,0 +1,132 @@
# Checkpoint 3: Pipeline Stages, Chunking, Merge, And Normalize
## Status
This document describes planned work, not implemented behavior.
## Goal
Make Notarius's application workflow first-class before adding real input
modules or process modules.
The workflow should be:
```text
input -> chunk -> process -> merge -> normalize -> output
```
Checkpoint 3 should define the contracts and minimal fake-tested framework
behavior for chunking, per-chunk processing, merging, and normalization. It
should not add real input modules, real domain process modules, LLM provider code,
or output encoders.
## Scope
In scope:
- source chunk model;
- chunker contract;
- process-stage contract for extractors operating on chunks;
- merge-stage contract;
- normalize-stage contract;
- output-stage contract shape, if useful for pipeline completeness;
- runner/pipeline updates that exercise these stages with fake components;
- generic append/chronological merge behavior for artifact candidates when
appropriate.
Out of scope:
- Seriatim parsing;
- D&D spell extraction;
- LLM provider calls;
- prompt assets;
- response schema assets;
- diagnostics run directory;
- production output serialization.
## Target End State
The repository should contain explicit pipeline-stage contracts:
- `InputAdapter`: external source input to `SourceDocument`.
- `Chunker`: `SourceDocument` to ordered `SourceChunk` values.
- `Extractor` or processor: `SourceChunk` to artifact candidates.
- `Merger`: per-chunk candidates to merged candidates.
- `Normalizer`: merged candidates to normalized candidates.
- `OutputEncoder`: final artifact bundle to bytes, if introduced in this
checkpoint.
The runner should orchestrate fake implementations through chunk, process,
merge, normalize, and approval/validation behavior in tests.
## Design Intent
Chunking is a core application concern because many source documents, especially
transcripts, will be too large for a single LLM extraction pass.
Chunk processing may be serial or parallel depending on extractor needs. The
architecture should support both, but the first implementation can execute
deterministically in series until a later checkpoint introduces concurrency.
Merge and normalize are separate stages:
- merge combines per-chunk extracted candidates into one stream or collection;
- normalize reconciles the merged output by checking duplicates, consistency,
ordering, identity resolution, or other cross-chunk concerns.
For some artifact types, merge may be generic append-in-source-order behavior.
For other artifact types, merge may be domain-specific. Normalization is where
deduplication and consistency checks should live.
## Processing Modes
The architecture should leave room for extractor-level processing modes:
- whole-document processing;
- serial chunk processing;
- parallel chunk processing.
The first implementation may model these modes without implementing parallel
execution. It should not bake in a single-pass assumption.
## Generic Merge Behavior
A generic merger should be able to concatenate candidates in deterministic
chunk order and candidate order. This is likely sufficient for early spell-cast
extraction, where chronological serialization is useful.
Domain-specific mergers may be added later when generic ordering is not enough.
## Generic Normalize Behavior
A no-op normalizer should be available as the default.
Domain-specific normalizers may later:
- deduplicate repeated extracted facts;
- resolve aliases;
- reconcile conflicting candidate fields;
- enforce chronological or source-reference consistency;
- attach normalization warnings.
## Done Criteria
- `go test ./...` passes.
- Pipeline-stage contracts are explicit and source/domain agnostic.
- Fake tests prove input source documents can be chunked, processed, merged, and
normalized.
- Merge and normalize are distinct concepts in code and tests.
- The runner no longer implies whole-document-only extraction as the core
application model.
- No concrete input module, process module, LLM provider, prompt, response schema,
diagnostics, config, or D&D artifact code is added.
## Review Questions
- Is the workflow clearly represented as input, chunk, process, merge,
normalize, and output?
- Are merge and normalize cleanly separated?
- Can a generic merger handle simple chronological artifact streams?
- Can a later domain-specific normalizer handle duplicates and consistency
without changing core runner contracts?
- Does the design allow serial and parallel chunk processing later?

View File

@@ -1,4 +1,4 @@
# Checkpoint 3: Portable Audita Infrastructure # Checkpoint 4: Portable Audita Infrastructure
## Status ## Status
@@ -72,7 +72,7 @@ The registry should track:
- prompt hash. - prompt hash.
Do not add D&D prompt assets here unless the implementation naturally overlaps Do not add D&D prompt assets here unless the implementation naturally overlaps
with checkpoint 5. Test prompts are acceptable for registry tests. with checkpoint 6. Test prompts are acceptable for registry tests.
### Stage 4: Diagnostics Run Directory ### Stage 4: Diagnostics Run Directory
@@ -94,7 +94,7 @@ Add config structs and defaults only for infrastructure that now exists.
Initial config areas: Initial config areas:
- input adapter key; - input module key;
- extractor keys; - extractor keys;
- primary LLM settings; - primary LLM settings;
- validation LLM settings if needed; - validation LLM settings if needed;

View File

@@ -1,4 +1,4 @@
# Checkpoint 4: Seriatim Input Adapter # Checkpoint 5: Seriatim Input Module
## Status ## Status
@@ -7,7 +7,7 @@ This document describes planned work, not implemented behavior.
## Goal ## Goal
Add the first real input source while keeping transcript-specific behavior Add the first real input source while keeping transcript-specific behavior
isolated inside an input adapter. isolated inside an input-stage module.
This checkpoint should allow Seriatim minimal transcript JSON to become a This checkpoint should allow Seriatim minimal transcript JSON to become a
generic `SourceDocument`. generic `SourceDocument`.
@@ -16,13 +16,13 @@ generic `SourceDocument`.
In scope: In scope:
- `internal/adapters/input/seriatim`; - `internal/modules/input/seriatim`;
- parser for Seriatim minimal output JSON; - parser for Seriatim minimal output JSON;
- mapping into `SourceDocument` and `SourceUnit`; - mapping into `SourceDocument` and `SourceUnit`;
- source-document validation; - source-document validation;
- adapter registry wiring; - input adapter registry wiring;
- fixtures and tests; - fixtures and tests;
- CLI/config path to select the adapter if the CLI shell exists. - CLI/config path to select the input module if the CLI shell exists.
Out of scope: Out of scope:
@@ -33,9 +33,9 @@ Out of scope:
## Proposed Stages ## Proposed Stages
### Stage 1: Seriatim Source Model ### Seriatim Source Model
Define adapter-local structs for the Seriatim minimal output schema. Define module-local structs for the Seriatim minimal output schema.
Expected external shape: Expected external shape:
@@ -47,9 +47,9 @@ Expected external shape:
- segment `speaker`; - segment `speaker`;
- segment `text`. - segment `text`.
Keep these structs in the adapter package. Keep these structs in the Seriatim input module package.
### Stage 2: Parse And Validate ### Parse And Validate
Implement parser and validation behavior. Implement parser and validation behavior.
@@ -62,9 +62,9 @@ Validation should cover:
- non-empty segment text; - non-empty segment text;
- valid start/end values as appropriate. - valid start/end values as appropriate.
Prefer clear adapter-specific errors. Prefer clear module-specific errors.
### Stage 3: Map To SourceDocument ### Map To SourceDocument
Map Seriatim data into the generic source model: Map Seriatim data into the generic source model:
@@ -77,9 +77,9 @@ Map Seriatim data into the generic source model:
The resulting `SourceDocument` should pass core source validation. The resulting `SourceDocument` should pass core source validation.
### Stage 4: Registry And CLI Wiring ### Registry And CLI Wiring
Register the adapter under a stable key, likely `seriatim`. Register the module under a stable input adapter key, likely `seriatim`.
If CLI support exists, add provisional selection: If CLI support exists, add provisional selection:
@@ -87,9 +87,9 @@ If CLI support exists, add provisional selection:
notarius extract ./transcript.json --input seriatim notarius extract ./transcript.json --input seriatim
``` ```
The command may still use fake extractors until checkpoint 5. The command may still use fake extractors until checkpoint 6.
### Stage 5: Fixtures And Tests ### Fixtures And Tests
Add fixtures and tests for: Add fixtures and tests for:
@@ -105,12 +105,12 @@ Add fixtures and tests for:
- `go test ./...` passes. - `go test ./...` passes.
- Seriatim minimal transcript JSON maps into `SourceDocument`. - Seriatim minimal transcript JSON maps into `SourceDocument`.
- Transcript fields do not appear in core runner contracts. - Transcript fields do not appear in core runner contracts.
- The adapter is selectable through the registry. - The input module is selectable through the registry.
- Tests prove transcript-specific assumptions are isolated to the adapter. - Tests prove transcript-specific assumptions are isolated to the input module.
## Review Questions ## Review Questions
- Are segment, speaker, and timestamp assumptions contained inside the adapter? - Are segment, speaker, and timestamp assumptions contained inside the input module?
- Are unit IDs stable and suitable for source references? - Are unit IDs stable and suitable for source references?
- Does the adapter preserve enough metadata for transcript-oriented output later? - Does the input module preserve enough metadata for transcript-oriented output later?
- Should the adapter accept only Seriatim minimal output for now? - Should the input module accept only Seriatim minimal output for now?

View File

@@ -1,4 +1,4 @@
# Checkpoint 5: D&D Spells Extractor # Checkpoint 6: D&D Spells Extractor
## Status ## Status
@@ -6,8 +6,8 @@ This document describes planned work, not implemented behavior.
## Goal ## Goal
Implement the first useful extraction module: D&D spell casts from a Seriatim Implement the first useful process-stage module: D&D spell casts from a
transcript source document. Seriatim transcript source document.
This checkpoint should produce the first meaningful vertical slice from real This checkpoint should produce the first meaningful vertical slice from real
source input to validated artifact output. source input to validated artifact output.
@@ -19,7 +19,7 @@ In scope:
- D&D spell artifact schema and Go structs; - D&D spell artifact schema and Go structs;
- structured response schema asset; - structured response schema asset;
- prompt assets; - prompt assets;
- `internal/extractors/dnd/spells`; - `internal/modules/process/dnd/spells`;
- source-reference and schema validators in the extractor chain; - source-reference and schema validators in the extractor chain;
- fake LLM tests; - fake LLM tests;
- CLI-level integration test if the CLI path is ready. - CLI-level integration test if the CLI path is ready.
@@ -50,8 +50,8 @@ type SpellCast struct {
} }
``` ```
Keep this schema inside the D&D spells extractor or a D&D artifact package, not Keep this schema inside the D&D spells process module or a D&D artifact package,
inside core framework packages. not inside core framework packages.
### Stage 2: Structured Response Schema ### Stage 2: Structured Response Schema
@@ -74,14 +74,14 @@ Prompts should:
- avoid relying on transcript-specific fields except as optional metadata; - avoid relying on transcript-specific fields except as optional metadata;
- request only spell-cast artifacts. - request only spell-cast artifacts.
### Stage 4: Extractor Implementation ### Stage 4: Process Module Implementation
Implement `internal/extractors/dnd/spells`. Implement `internal/modules/process/dnd/spells`.
The extractor should: The extractor should:
- satisfy the framework `Extractor` contract; - satisfy the framework `Extractor` contract;
- build LLM messages from a source document or source slice; - build LLM messages from a source document or source chunk;
- call the structured LLM client; - call the structured LLM client;
- return artifact candidates with source references; - return artifact candidates with source references;
- attach its validator chain. - attach its validator chain.
@@ -117,13 +117,13 @@ The test should use fake LLM wiring and fixture input.
- `go test ./...` passes. - `go test ./...` passes.
- Seriatim input can flow through the runner into the D&D spells extractor. - Seriatim input can flow through the runner into the D&D spells extractor.
- Spell artifacts include valid source references. - Spell artifacts include valid source references.
- D&D concepts are contained in extractor/artifact packages and docs. - D&D concepts are contained in process module/artifact packages and docs.
- The first meaningful vertical slice is available through tests, and through - The first meaningful vertical slice is available through tests, and through
CLI if the CLI path is ready. CLI if the CLI path is ready.
## Review Questions ## Review Questions
- Is the spell extractor domain-specific without making the framework - Is the spell process module domain-specific without making the framework
D&D-specific? D&D-specific?
- Are source references valid and useful for downstream validation? - Are source references valid and useful for downstream validation?
- Is prompt/schema ownership clear? - Is prompt/schema ownership clear?

View File

@@ -10,8 +10,8 @@ not describe implemented behavior.
Notarius documentation should make three boundaries obvious: Notarius documentation should make three boundaries obvious:
- source-format support belongs to input adapters; - source-format support belongs to input-stage modules;
- extraction-domain behavior belongs to extractor packages; - extraction-domain behavior belongs to process-stage modules;
- core framework behavior is source-agnostic and domain-agnostic. - core framework behavior is source-agnostic and domain-agnostic.
Documentation should avoid making the MVP look more transcript-specific or Documentation should avoid making the MVP look more transcript-specific or
@@ -35,6 +35,10 @@ Core architecture docs should prefer:
- source reference; - source reference;
- input adapter; - input adapter;
- extractor; - extractor;
- chunker;
- merger;
- normalizer;
- output encoder;
- artifact; - artifact;
- validator; - validator;
- run manifest. - run manifest.
@@ -43,11 +47,12 @@ Core docs should avoid transcript-specific terms such as segment, speaker,
timestamp, and transcript range unless discussing an input adapter or an example. timestamp, and transcript range unless discussing an input adapter or an example.
Core docs should avoid D&D-specific terms such as spell, NPC, item, combat, and Core docs should avoid D&D-specific terms such as spell, NPC, item, combat, and
encounter unless discussing extractor packages or examples. encounter unless discussing process modules, artifact docs, or examples.
### Adapter Docs Own Source Formats ### Input Module Docs Own Source Formats
Each implemented input adapter should have a canonical integration document. Each implemented input-stage module should have a canonical integration
document.
Likely future files: Likely future files:
@@ -56,32 +61,33 @@ docs/integrations/seriatim-transcript.md
docs/integrations/markdown-source.md docs/integrations/markdown-source.md
``` ```
Adapter docs should cover: Input module docs should cover:
- accepted external schema or file shape; - accepted external schema or file shape;
- mapping into `SourceDocument` and `SourceUnit`; - mapping into `SourceDocument` and `SourceUnit`;
- metadata preserved by the adapter; - metadata preserved by the module;
- validation rules and failure behavior; - validation rules and failure behavior;
- examples. - examples.
The Seriatim adapter doc should reference the Seriatim schema it supports and The Seriatim input module doc should reference the Seriatim schema it supports and
explain how transcript segment IDs become source-unit IDs. explain how transcript segment IDs become source-unit IDs.
### Extractor Docs Own Domains ### Stage Module Docs Own Business Logic
Each implemented extractor family should have canonical internal or integration Each implemented stage-module family should have canonical internal or
docs. integration docs.
Likely future files: Likely future files:
```text ```text
docs/internal/extractors.md docs/internal/stage-modules.md
docs/integrations/artifacts-dnd.md docs/integrations/artifacts-dnd.md
``` ```
Extractor docs should cover: Stage module docs should cover:
- extractor key; - module key;
- stage;
- artifact type; - artifact type;
- schema version; - schema version;
- required source-reference behavior; - required source-reference behavior;
@@ -89,13 +95,14 @@ Extractor docs should cover:
- prompt and response-schema ownership; - prompt and response-schema ownership;
- examples. - examples.
D&D concepts should be documented in D&D extractor docs, not in generic runner D&D concepts should be documented in D&D process-module or artifact docs, not in
or framework docs. generic runner or framework docs.
### CLI Docs Should Reflect Extensibility ### CLI Docs Should Reflect Extensibility
The CLI reference should present input adapters and extractors as selectable The CLI reference should present input modules, chunk modules, process modules,
components. merge modules, normalize modules, and output modules as selectable or
configurable components as they become user-facing.
Provisional command shape: Provisional command shape:
@@ -106,8 +113,9 @@ notarius extract ./source.json --input seriatim --extractors dnd.spells --output
Once implemented, `docs/cli.md` should document: Once implemented, `docs/cli.md` should document:
- positional source input path; - positional source input path;
- input adapter selection; - input module selection;
- extractor selection; - process module selection;
- chunk/merge/normalize/output selection when configurable;
- config path behavior; - config path behavior;
- output path behavior; - output path behavior;
- diagnostics and report behavior; - diagnostics and report behavior;
@@ -117,15 +125,17 @@ Once implemented, `docs/cli.md` should document:
`docs/config.md` should group fields by responsibility: `docs/config.md` should group fields by responsibility:
- input adapter selection and adapter-specific options; - input module selection and module-specific options;
- extractor selection and extractor-specific options; - chunk module selection and module-specific options;
- process module selection and module-specific options;
- merge module selection and module-specific options;
- normalize module selection and module-specific options;
- output module selection and module-specific options;
- LLM runtime; - LLM runtime;
- validation runtime; - validation runtime;
- source chunking; - diagnostics.
- output and diagnostics.
Adapter-specific and extractor-specific config should not leak into unrelated Module-specific config should not leak into unrelated core config sections.
core config sections.
### Examples Should Stay Real ### Examples Should Stay Real
@@ -154,8 +164,8 @@ When the first vertical slice is implemented, add or update:
- `docs/troubleshooting.md`: common failures. - `docs/troubleshooting.md`: common failures.
- `docs/internal/overview.md`: implemented package map. - `docs/internal/overview.md`: implemented package map.
- `docs/internal/pipeline.md`: implemented extraction flow. - `docs/internal/pipeline.md`: implemented extraction flow.
- `docs/internal/adapters.md`: adapter contract and implemented adapters. - `docs/internal/stage-modules.md`: stage contracts and implemented modules.
- `docs/internal/extractors.md`: extractor contract and built-ins. - `docs/internal/input-modules.md`: input adapter contract and implemented input modules.
- `docs/internal/validators.md`: validator contract and built-ins. - `docs/internal/validators.md`: validator contract and built-ins.
- `docs/integrations/seriatim-transcript.md`: Seriatim input contract. - `docs/integrations/seriatim-transcript.md`: Seriatim input contract.
- `docs/integrations/artifacts.md`: output artifact envelope. - `docs/integrations/artifacts.md`: output artifact envelope.
@@ -165,10 +175,10 @@ When the first vertical slice is implemented, add or update:
Before merging docs, check: Before merging docs, check:
- Does the document describe implemented behavior outside `docs/roadmap/`? - Does the document describe implemented behavior outside `docs/roadmap/`?
- Are source-format details isolated to adapter docs? - Are source-format details isolated to input module or integration docs?
- Are D&D details isolated to extractor or artifact docs? - Are D&D details isolated to process module or artifact docs?
- Is there one canonical home for the topic? - Is there one canonical home for the topic?
- Do command examples match implemented CLI syntax? - Do command examples match implemented CLI syntax?
- Are examples valid, maintained, and free of secrets? - Are examples valid, maintained, and free of secrets?
- Did any architecture, config, CLI, adapter, extractor, validator, or artifact - Did any architecture, config, CLI, stage module, validator, or artifact
contract change require a docs update? contract change require a docs update?

View File

@@ -6,10 +6,10 @@ This is a staged implementation plan for
[`2-framework-composition.md`](2-framework-composition.md). It is intended for [`2-framework-composition.md`](2-framework-composition.md). It is intended for
an LLM coding agent to follow stage by stage. an LLM coding agent to follow stage by stage.
This plan implements only checkpoint 2. Do not implement real input adapters, This plan implements only checkpoint 2. Do not implement real input modules,
real extractors, source chunking, LLM provider clients, prompt assets, response real process modules, source chunking, LLM provider clients, prompt assets,
schema registries, diagnostics run directories, production config loading, or response schema registries, diagnostics run directories, production config
D&D artifact schemas in this pass. loading, or D&D artifact schemas in this pass.
## Policy Context ## Policy Context
@@ -21,8 +21,8 @@ Follow:
Required boundaries: Required boundaries:
- framework packages must stay source-agnostic and domain-agnostic; - framework packages must stay source-agnostic and domain-agnostic;
- input adapter registry code must not import concrete adapter packages; - input adapter registry code must not import concrete input module packages;
- extractor registry and runner code must not import concrete extractor - extractor registry and runner code must not import concrete process module
packages; packages;
- runner code should operate on `SourceDocument`, not transcript-specific - runner code should operate on `SourceDocument`, not transcript-specific
structures; structures;
@@ -130,7 +130,7 @@ Cover:
- sorted `RegisteredKeys`; - sorted `RegisteredKeys`;
- nil registry behavior. - nil registry behavior.
Use fake adapters only. Do not add concrete adapter packages. Use fake adapters only. Do not add concrete input module packages.
### Validation ### Validation
@@ -196,7 +196,7 @@ Cover the same cases as the input adapter registry:
- sorted `RegisteredKeys`; - sorted `RegisteredKeys`;
- nil registry behavior. - nil registry behavior.
Use fake extractors only. Do not add concrete extractor packages. Use fake extractors only. Do not add concrete process module packages.
### Validation ### Validation
@@ -478,7 +478,8 @@ go test ./...
### Goal ### Goal
Prove the extractor registry and runner compose without adding real extractors. Prove the extractor registry and runner compose without adding real process
modules.
### Files To Add ### Files To Add
@@ -501,7 +502,7 @@ Assertions:
- extractor execution follows configured key order; - extractor execution follows configured key order;
- approved artifacts are in deterministic order; - approved artifacts are in deterministic order;
- rejected artifacts are in deterministic order; - rejected artifacts are in deterministic order;
- no concrete adapter or extractor packages are imported. - no concrete input module or process module packages are imported.
### Validation ### Validation
@@ -527,7 +528,7 @@ Check:
- no package names mention transcripts, Seriatim, D&D, spells, NPCs, items, or - no package names mention transcripts, Seriatim, D&D, spells, NPCs, items, or
combat; combat;
- no concrete adapter or extractor package exists; - no concrete input module or process module package exists;
- no LLM provider code exists; - no LLM provider code exists;
- no prompt, response schema, diagnostics, config, or source chunking package - no prompt, response schema, diagnostics, config, or source chunking package
was added; was added;

View File

@@ -11,21 +11,21 @@ Notarius should extract structured JSON artifacts from primary source inputs
using modular, LLM-backed extractors. using modular, LLM-backed extractors.
The first MVP should target audio transcripts generated by Seriatim. That The first MVP should target audio transcripts generated by Seriatim. That
choice should be implemented as an input adapter, not as a transcript-specific choice should be implemented as an input-stage module, not as a
assumption in the application core. Later input sources, such as unstructured transcript-specific assumption in the application core. Later input sources,
Markdown notes or Obsidian documents, should be addable through new adapters and such as unstructured Markdown notes or Obsidian documents, should be addable
extractors without reshaping the framework. through new input and process modules without reshaping the framework.
The first extraction domain should be D&D session analysis, starting with spell The first extraction domain should be D&D session analysis, starting with spell
casts. That domain should live in extractor packages and related schemas, not in casts. That domain should live in process-stage modules and related schemas, not
core framework packages. in core framework packages.
The application should follow the same broad architecture as Audita: The application should follow the same broad architecture as Audita:
- deterministic core packages for config, source documents, artifacts, diagnostics, and reporting; - deterministic core packages for config, source documents, artifacts, diagnostics, and reporting;
- input adapters that translate external source formats into a small internal source model; - input-stage modules that translate external source formats into a small internal source model;
- reusable framework packages for contracts, orchestration, LLM runtime, structured output, and validation; - reusable framework packages for contracts, orchestration, LLM runtime, structured output, and validation;
- independent extractor packages that own domain-specific behavior; - independent process-stage modules that own domain-specific behavior;
- independent validator packages; - independent validator packages;
- embedded prompt and JSON schema assets; - embedded prompt and JSON schema assets;
- CLI orchestration that wires the pieces together without owning domain logic. - CLI orchestration that wires the pieces together without owning domain logic.
@@ -36,8 +36,8 @@ artifacts rather than proposing and applying transcript corrections.
## Architectural Principles ## Architectural Principles
- Keep the core input model generic: ordered text units plus metadata. - Keep the core input model generic: ordered text units plus metadata.
- Keep source-format details in hexagonal input adapters. - Keep source-format details in hexagonal input modules.
- Keep extraction-domain details in extractor packages. - Keep extraction-domain details in process modules.
- Treat evidence as source references, not transcript references. - Treat evidence as source references, not transcript references.
- Prefer narrow, useful abstractions over a universal document model. - Prefer narrow, useful abstractions over a universal document model.
- Preserve enough provenance for validation, replay, and downstream inspection. - Preserve enough provenance for validation, replay, and downstream inspection.
@@ -57,12 +57,13 @@ internal/core/reporting
internal/core/extractorcatalog internal/core/extractorcatalog
internal/core/inputcatalog internal/core/inputcatalog
internal/adapters/input/seriatim
internal/adapters/input/markdown
internal/framework/contracts internal/framework/contracts
internal/framework/extraction internal/framework/extraction
internal/framework/runner internal/framework/runner
internal/framework/pipeline
internal/framework/merge
internal/framework/normalize
internal/framework/output
internal/framework/validators internal/framework/validators
internal/framework/llm internal/framework/llm
internal/framework/responseschema internal/framework/responseschema
@@ -70,10 +71,24 @@ internal/framework/structuredoutput
internal/framework/promptcontext internal/framework/promptcontext
internal/framework/warnings internal/framework/warnings
internal/extractors/dnd/spells internal/modules/input/seriatim
internal/extractors/dnd/items internal/modules/input/markdown
internal/extractors/dnd/npcs
internal/extractors/dnd/combat internal/modules/chunk/generic
internal/modules/chunk/dndtranscript
internal/modules/process/dnd/spells
internal/modules/process/dnd/items
internal/modules/process/dnd/npcs
internal/modules/process/dnd/combat
internal/modules/merge/appendorder
internal/modules/merge/dnd/spells
internal/modules/normalize/noop
internal/modules/normalize/dnd/spells
internal/modules/output/json
internal/validators/source_refs internal/validators/source_refs
internal/validators/schema_validity internal/validators/schema_validity
@@ -85,9 +100,9 @@ examples
docs/internal docs/internal
``` ```
The `markdown` adapter is listed as a likely future package. The MVP should only The `markdown` input module and D&D-specific chunk, merge, normalize, and
implement the Seriatim adapter unless a second adapter is needed to test the output modules are listed as likely future packages. The MVP should implement
boundary. only the stage modules needed by the checkpoint sequence.
## Core Concepts ## Core Concepts
@@ -123,7 +138,7 @@ Initial source-unit assumptions:
- adapter-specific metadata may carry speaker, timestamps, heading paths, page - adapter-specific metadata may carry speaker, timestamps, heading paths, page
numbers, or other source details. numbers, or other source details.
### Input Adapter ### Input Module / Adapter Contract
Hexagonal boundary for external source formats. Hexagonal boundary for external source formats.
@@ -134,7 +149,7 @@ type InputAdapter interface {
} }
``` ```
The MVP adapter should target Seriatim minimal transcript JSON. Seriatim segment The MVP input module should target Seriatim minimal transcript JSON. Seriatim segment
fields should map as follows: fields should map as follows:
- `id` becomes `SourceUnit.ID`; - `id` becomes `SourceUnit.ID`;
@@ -178,17 +193,44 @@ type Extractor interface {
ArtifactType() string ArtifactType() string
SchemaVersion() string SchemaVersion() string
Validators() []Validator Validators() []Validator
Extract(ctx context.Context, req ExtractionRequest) (ExtractionResult, error) Process(ctx context.Context, req ProcessRequest) (ProcessResult, error)
} }
``` ```
An extractor should receive either a whole source document or a source slice, An extractor should receive either a whole source document or a source chunk,
depending on runner configuration. It should return typed artifact candidates depending on processing mode. It should return typed artifact candidates plus
plus warnings. It should not mutate the source document. warnings. It should not mutate the source document.
Extractor packages own domain concepts. For example, D&D spell extraction should Process modules own domain concepts. For example, D&D spell extraction should
live under `internal/extractors/dnd/spells`; a future to-do extractor for notes live under `internal/modules/process/dnd/spells`; a future to-do extractor for
should live under a different domain path and use the same framework contract. notes should live under a different process-module path and use the same
framework contract.
### Chunker
Reusable stage contract for splitting a source document into ordered source
chunks.
Chunking is a first-class pipeline concern because source documents may exceed a
single LLM extraction pass. Chunkers should preserve source-unit order and
produce stable chunk metadata suitable for diagnostics and replay.
### Merger
Reusable stage contract for combining per-chunk artifact candidates into one
merged candidate collection.
Merge should combine outputs without doing semantic reconciliation. A generic
append-in-chunk-order merger should be sufficient for many artifact streams,
including the likely first D&D spell-cast extractor.
### Normalizer
Reusable stage contract for reconciling merged artifact candidates.
Normalize is distinct from merge. Normalizers may deduplicate repeated facts,
resolve aliases, reconcile conflicting fields, check cross-chunk consistency,
or attach normalization warnings.
### Validator ### Validator
@@ -303,27 +345,37 @@ The architecture should support extractors outside the D&D domain. Examples:
- decisions and action items from meeting transcripts; - decisions and action items from meeting transcripts;
- named people, places, and dates from research notes. - named people, places, and dates from research notes.
These should be addable as extractor packages without changing runner, These should be addable as process modules without changing runner,
validator, source-reference, or LLM framework contracts. validator, source-reference, or LLM framework contracts.
## Proposed Runner Flow ## Proposed Pipeline Flow
The application workflow should be first-class:
```text
input -> chunk -> process -> merge -> normalize -> output
```
Proposed runner flow:
1. Load effective config. 1. Load effective config.
2. Create diagnostics run directory. 2. Create diagnostics run directory.
3. Resolve the configured input adapter. 3. Resolve the configured input module through the input adapter registry.
4. Read source input. 4. Read source input.
5. Parse source input into a `SourceDocument`. 5. Parse source input into a `SourceDocument`.
6. Validate source-document invariants. 6. Validate source-document invariants.
7. Chunk source units into deterministic source slices. 7. Resolve the configured chunker.
8. Resolve configured extractor instances through a registry. 8. Chunk source units into deterministic source chunks.
9. Execute extractor instances in configured order. 9. Resolve configured extractor instances through a registry.
10. Run deterministic validators before LLM-backed validators. 10. Process chunks in extractor-defined mode.
11. Retain approved artifacts and rejected-artifact diagnostics. 11. Merge per-chunk artifact candidates deterministically.
12. Merge approved slice artifacts deterministically. 12. Normalize merged artifact candidates.
13. Serialize final output JSON. 13. Run deterministic validators before LLM-backed validators.
14. Write run manifest, diagnostics, and optional report JSON. 14. Retain approved artifacts and rejected-artifact diagnostics.
15. Serialize final output JSON.
16. Write run manifest, diagnostics, and optional report JSON.
The runner should operate on source documents and source slices only. Any The runner should operate on source documents and source chunks only. Any
transcript-specific behavior should happen before the runner, inside the input transcript-specific behavior should happen before the runner, inside the input
adapter, or after the runner, inside output rendering that understands source adapter, or after the runner, inside output rendering that understands source
metadata. metadata.
@@ -335,6 +387,7 @@ Reuse these architectural patterns:
- deterministic parsing and schema validation style; - deterministic parsing and schema validation style;
- deterministic chunking of ordered source units; - deterministic chunking of ordered source units;
- explicit extractor registry; - explicit extractor registry;
- explicit pipeline stage contracts;
- `contracts` package for transport-neutral interfaces; - `contracts` package for transport-neutral interfaces;
- OpenAI-compatible structured LLM client; - OpenAI-compatible structured LLM client;
- scheduler for bounded LLM concurrency; - scheduler for bounded LLM concurrency;
@@ -358,17 +411,18 @@ extraction-report concepts.
## Checkpoint Roadmap ## Checkpoint Roadmap
The initial implementation should proceed through five coherent checkpoints. The initial implementation should proceed through six coherent checkpoints.
Each checkpoint should leave the repository in a reviewable state, with the code Each checkpoint should leave the repository in a reviewable state, with the code
compiling and targeted tests covering the newly introduced contracts or behavior. compiling and targeted tests covering the newly introduced contracts or behavior.
1. [Core Contracts And Skeleton](1-core-contracts-and-skeleton.md) 1. [Core Contracts And Skeleton](1-core-contracts-and-skeleton.md)
2. [Framework Composition](2-framework-composition.md) 2. [Framework Composition](2-framework-composition.md)
3. [Portable Audita Infrastructure](3-portable-audita-infrastructure.md) 3. [Pipeline Stages, Chunking, Merge, And Normalize](3-pipeline-stages-chunking-merge-normalize.md)
4. [Seriatim Input Adapter](4-seriatim-input-adapter.md) 4. [Portable Audita Infrastructure](4-portable-audita-infrastructure.md)
5. [D&D Spells Extractor](5-dnd-spells-extractor.md) 5. [Seriatim Input Module](5-seriatim-input-module.md)
6. [D&D Spells Extractor](6-dnd-spells-extractor.md)
The first useful vertical slice should arrive at checkpoint 5: Seriatim The first useful vertical slice should arrive at checkpoint 6: Seriatim
transcript input to validated D&D spell artifact output. Earlier checkpoints are transcript input to validated D&D spell artifact output. Earlier checkpoints are
intentionally contract-first and may not produce useful user output yet. intentionally contract-first and may not produce useful user output yet.
@@ -383,10 +437,11 @@ intentionally contract-first and may not produce useful user output yet.
artifact metadata be allowed without source references? artifact metadata be allowed without source references?
- Should overlapping source-reference ranges be merged, preserved exactly, or - Should overlapping source-reference ranges be merged, preserved exactly, or
both? both?
- Should extraction run independently per source slice only, or should some - Should extraction run independently per source chunk only, or should some
extractors receive whole-document context? extractors receive whole-document context?
- Should a later reconciliation stage deduplicate entities and events across - Which artifact types can use a generic append-in-chunk-order merger?
source slices? - Which artifact types need domain-specific normalization for deduplication,
identity resolution, or consistency?
- Should LLM review be part of each extractor's validator chain or a separate - Should LLM review be part of each extractor's validator chain or a separate
review phase? review phase?
- Should the Seriatim adapter accept only its minimal schema initially or also - Should the Seriatim adapter accept only its minimal schema initially or also