281 lines
14 KiB
Markdown
281 lines
14 KiB
Markdown
# Module And Validator Internals
|
|
|
|
Production module and validator implementations live under their domain-first
|
|
trees in `internal/modules`.
|
|
The selectable keys, configuration options, reference slots, and default
|
|
validator chain are canonical in the
|
|
[module](../config.md#implemented-production-modules) and
|
|
[validator](../config.md#implemented-production-validators) catalogs in
|
|
Configuration.
|
|
|
|
## Extension Pattern
|
|
|
|
A stage module package provides a stable key, constructor, contract
|
|
implementation, `ModuleSpec`, `Register`, and focused behavior and registration
|
|
tests. A validator package follows the same pattern with `ValidatorSpec` and the
|
|
validator registry. Package-family registrars compose those leaf registrations
|
|
into the production catalog and own family-level policy such as default
|
|
validator chains and prompt asset collection.
|
|
|
|
Production input, chunk, output, and D&D spell-extract packages register strict
|
|
option decoders and run-local builders. Preparation decodes their options into
|
|
implementation-owned values and injects dependencies plus the materialized
|
|
reference set for the selected target. Each builder receives an isolated clone
|
|
of that set; input and output builders receive no references. The spell
|
|
extractor is typed over the canonical D&D model. D&D validators, merge, and
|
|
normalize use typed variants; JSON representation validators use serialized
|
|
requests; and unconditional validators expose separate chunk and typed
|
|
variants. The D&D production registrar registers only the canonical typed spell
|
|
implementations.
|
|
|
|
Prepared extractors, extract validators, and codecs may be reused concurrently
|
|
by the run-wide extract pool. Production implementations are immutable after
|
|
construction: they retain only typed options, immutable assets, or the shared
|
|
concurrency-safe LLM client. Implementations that introduce mutable state must
|
|
synchronize that state without creating a separate provider scheduler.
|
|
|
|
Specs expose capability and execution metadata without constructing an
|
|
implementation. Registry entries separately expose option validation and
|
|
run-local construction. Chunk, extract, merge, and normalize modules that accept
|
|
auxiliary material declare identical reference slots from both
|
|
`ReferenceSlots()` and `ModuleSpec().ReferenceSlots`; registration tests enforce
|
|
that agreement. Runtime delivery uses the corresponding stage request's
|
|
`References` field.
|
|
|
|
LLM-backed extensions own their prompt definitions and response schemas under
|
|
package-local embedded assets. Shared filesystem composition belongs in
|
|
`internal/framework/promptfs`; reusable D&D prompt fragments, reference
|
|
declarations, prompt-input assembly, and source-unit helpers belong in
|
|
`internal/modules/dnd/shared`. Stage contracts expose only Notarius structured-
|
|
completion types, not Scriptorium public types.
|
|
|
|
Reference material may inform a module or prompt but must not become source
|
|
evidence. The resolver and materializer behavior is described in
|
|
[Pipeline Internals](pipeline.md#reference-materialization).
|
|
|
|
## Domain Reference Data
|
|
|
|
### `internal/modules/dnd/spells/catalog`
|
|
|
|
The spell catalog package owns the embedded, versioned D&D 5e 2014 SRD spell
|
|
reference data. Its strict JSON asset contains one canonical record per spell,
|
|
including spell level and all applicable class memberships. `LoadSRD5E2014`
|
|
validates catalog identity, provenance metadata, ordering, uniqueness, levels,
|
|
classes, aliases, and lookup-key collisions before exposing immutable copies.
|
|
|
|
Lookup is case-insensitive and normalizes whitespace and common apostrophe
|
|
variants while preserving source punctuation in canonical display names. The
|
|
catalog contains 319 unique spells and 779 class memberships. Source and
|
|
license details live beside the asset in `SOURCES.md`. This domain-owned data is
|
|
separate from `internal/modules/dnd/shared`, which is reserved for reusable
|
|
prompt and source-reference machinery.
|
|
|
|
`ResolveEffectiveCatalog` builds the immutable recognition view used by later
|
|
D&D consumers. It starts with the embedded SRD catalog and optionally applies
|
|
one strict JSON overlay from the `spell_catalog` item in a materialized
|
|
reference set. Overlay catalogs are ordered by ID, may add names and aliases,
|
|
and may augment an existing canonical spell without replacing its display
|
|
name. Cross-spell lookup collisions are errors. The effective view exposes
|
|
sorted canonical names, normalized lookup, overlay identities, and a semantic
|
|
digest; overlay content remains contextual reference material rather than
|
|
source evidence. Its external JSON contract is defined in the
|
|
[spell-catalog overlay contract](../integrations/dnd-spell-catalog-overlays.md).
|
|
|
|
## Input Adapter
|
|
|
|
### `internal/modules/seriatim/input/transcript`
|
|
|
|
The adapter decodes the supported transcript JSON, selects the source identity,
|
|
computes canonical source provenance, validates segments, and maps each segment
|
|
into a generic source unit with a self-reference plus speaker and timestamp
|
|
metadata. It accepts no module options. Its spec advertises the transcript
|
|
capabilities consumed by D&D modules.
|
|
|
|
Parsing is strict about required values and duplicate unit IDs but deliberately
|
|
ignores unrelated Seriatim fields. The external format and derived-identity
|
|
rules are defined in the
|
|
[Seriatim contract](../integrations/seriatim.md).
|
|
|
|
## Chunkers
|
|
|
|
Chunkers implement `contracts.Chunker.Plan`. A plan identifies ordered source
|
|
unit ranges and may carry optional namespaced JSON annotations; it does not
|
|
contain materialized chunk content. The framework canonicalizes annotations,
|
|
validates ranges against the current source, and materializes chunk IDs,
|
|
indexes, references, content, units, and generic metadata. Materialized source
|
|
unit metadata is independently owned. Annotation
|
|
namespaces remain optional data: generic framework code and downstream modules
|
|
must not require D&D scene annotations or import `dnd/scenes`.
|
|
|
|
### `internal/modules/generic/chunk/units`
|
|
|
|
The generic chunker validates the source document and returns ranges over units
|
|
in configured windows. Overlap changes the next window start but never reorders
|
|
units. Framework materialization derives the resulting chunk identity and
|
|
generic metadata from those ranges.
|
|
|
|
The accepted options and defaults are defined in
|
|
[Configuration](../config.md#implemented-production-modules). Generic
|
|
framework validation canonicalizes the returned unit slices before extraction.
|
|
The chunker decodes its options during construction and retains only the typed
|
|
window settings used by `Plan`.
|
|
|
|
### `internal/modules/dnd/chunk/scenes`
|
|
|
|
The scene chunker prepares a structured Scriptorium request from the full
|
|
transcript, session, and optional D&D reference inputs. It validates the model's
|
|
scene boundaries against source-unit IDs and converts them into deterministic
|
|
plan ranges with optional scene annotations. Preparation injects the shared
|
|
structured LLM client into the chunker; `Plan`
|
|
supplies only the run-specific profile, session, source, references, and
|
|
metadata.
|
|
|
|
Scene validation requires sequential, contiguous, non-overlapping coverage from
|
|
the first source unit through the last. Scene descriptions, boundaries,
|
|
confidence, and participants are module-owned annotations. Boundary caveats
|
|
become warnings. Malformed
|
|
structured output is returned as an error; there is no fallback chunker.
|
|
|
|
The package embeds its prompt and response schema and reports their non-secret
|
|
identity and hashes through singleton module metadata. Shared D&D assets supply
|
|
reference declarations and prompt inputs; their user-facing keys and accepted
|
|
file types remain canonical in [Configuration](../config.md).
|
|
|
|
## Extractor
|
|
|
|
### `internal/modules/dnd/extract/spells`
|
|
|
|
The spell extractor prepares a structured request from one chunk, the
|
|
chunk-scoped source input, the session, and optional D&D reference inputs. It
|
|
decodes the model response, assigns the generic source identity to every source
|
|
reference, canonicalizes duplicate references, orders spell casts by their
|
|
earliest cited unit, and returns `dnd.SpellList`.
|
|
|
|
The extractor owns its private model-response DTO, embedded prompt, LLM response
|
|
schema, strict option decoder, injected shared LLM client, and prompt/schema
|
|
manifest metadata. The separate `internal/modules/dnd/codec/spells` package
|
|
owns the durable schema and stable JSON representation for artifact kind
|
|
`dnd/spell-list`. The runner keeps the result typed through validators and later
|
|
stages, using the codec only for checkpoint, debug, and output boundaries.
|
|
Shared D&D helpers keep prompt input
|
|
names and source-unit reference conversion consistent with the scene chunker.
|
|
|
|
The durable payload and manifest metadata shapes are defined in the
|
|
[D&D spell artifact contract](../integrations/dnd-spell-artifacts.md).
|
|
|
|
## Merger And Normalizer
|
|
|
|
### `internal/modules/generic/merge/appendorder`
|
|
|
|
The merger passes typed values to an injected combine function in framework
|
|
source-chunk order. The D&D registrar specializes it with a spell-list append
|
|
function.
|
|
|
|
### `internal/modules/generic/normalize/noop`
|
|
|
|
The normalizer returns the merged domain value unchanged and is reusable for
|
|
any registered artifact type.
|
|
|
|
## Output Encoder
|
|
|
|
### `internal/modules/generic/output/json`
|
|
|
|
The JSON encoder sorts normalized results by lane, derives collision-checked
|
|
safe logical names, pretty-prints JSON payloads, and assembles the logical index,
|
|
manifest, rejected-result, warning, and lane files. Invalid JSON, unsupported
|
|
media types, unsafe names, and sanitized-name collisions are errors.
|
|
|
|
The encoder returns logical files only. The CLI places them on disk, and the
|
|
[JSON output contract](../integrations/json-output.md) defines their external
|
|
paths and schemas.
|
|
|
|
## Generic Validators
|
|
|
|
The generic validator implementations live under
|
|
`internal/modules/generic/validate`.
|
|
|
|
The unconditional accept and reject validators provide explicit chunk and
|
|
typed-artifact variants used primarily for controlled composition and tests.
|
|
|
|
The serialized JSON syntax validator uses `encoding/json` to reject malformed
|
|
representation bytes. The serialized JSON Schema validator requires schema
|
|
bytes, parses the instance and schema with `jsonschema`, and distinguishes
|
|
payload rejection from schema loading or compilation errors. The framework
|
|
serialized-validation request carries either canonical chunk bytes or artifact
|
|
codec bytes according to its target context. Neither validator calls the LLM.
|
|
|
|
## D&D Spell Validators
|
|
|
|
All three validators receive `dnd.SpellList` directly. The shape validator
|
|
rejects missing or empty spell fields and empty reference lists. The
|
|
source-reference validator applies generic source-reference validation to every
|
|
cited range. The relatedness validator warns when a case-insensitive spell name
|
|
is absent from all cited source text.
|
|
|
|
These validators are deterministic. Their selectable keys and production order
|
|
are defined in
|
|
[Configuration](../config.md#implemented-production-validators); their durable
|
|
payload rules are defined in the
|
|
[artifact contract](../integrations/dnd-spell-artifacts.md).
|
|
|
|
## Production Registration
|
|
|
|
Production composition occurs through family registrars. The CLI allocates one
|
|
complete framework registry set and one LLM asset registry. It invokes
|
|
`internal/modules/generic/register`,
|
|
`internal/modules/seriatim/register`, and `internal/modules/dnd/register` in
|
|
that order, then exposes the matching catalog for resolution. The generic and
|
|
Seriatim registrars own their production leaf registrations. The D&D registrar
|
|
owns D&D leaf registrations, the spell default-validator chain, and D&D
|
|
prompt/schema asset collection.
|
|
|
|
Concrete implementation packages do not import generic implementation
|
|
packages directly. A concrete family's `register` package is its composition
|
|
point for specializing reusable generic implementations, while the generic
|
|
registrar composes only generic children.
|
|
|
|
Core and framework production packages do not import production extensions.
|
|
CLI production code is the sole application composition root for extensions
|
|
and imports only exact family registrar packages. Other production packages,
|
|
including commands and newly introduced package trees, do not import module
|
|
packages directly. Compatibility tests in the CLI, core, and framework trees
|
|
may import roots and implementation leaves directly. Other non-module tests do
|
|
not receive that exemption. White-box tests within module families retain the
|
|
production family boundaries. `internal/modules/integration` is test
|
|
infrastructure: its black-box tests may compose multiple families, but it is
|
|
not a production module family or production dependency target.
|
|
|
|
## Adding An Extension
|
|
|
|
When adding a production module or validator:
|
|
|
|
1. implement the stage or validator contract and package-local key;
|
|
2. expose and test its spec, constructor, and registration function;
|
|
3. keep format or domain parsing inside the concrete package;
|
|
4. add package-owned prompt/schema assets when the extension is LLM-backed;
|
|
5. register it through its package-family registrar and add a default chain
|
|
there only when production policy requires one;
|
|
6. add resolution and composition coverage for capabilities, options,
|
|
references, and validation behavior;
|
|
7. update the selectable-key catalog in [Configuration](../config.md), the
|
|
relevant external contract, this inventory, and maintained examples when
|
|
user-visible behavior changes.
|
|
|
|
Do not add the extension to `docs/development.md`; that file routes by task and
|
|
does not inventory implementations.
|
|
|
|
## Tests To Inspect
|
|
|
|
- Package-local `*_test.go` files under the module or validator being changed.
|
|
- `internal/framework/pipeline/typed_resolution_test.go`: typed registry, spec,
|
|
and heterogeneous artifact composition.
|
|
- `internal/framework/pipeline/profile_test.go`: framework binding defaults and
|
|
profile resolution.
|
|
- `internal/cli/production_contract_test.go`: production catalog, config
|
|
resolution, and composition smoke coverage.
|
|
- `internal/cli/example_contract_test.go`: maintained example ownership.
|
|
- `internal/framework/promptfs/*_test.go` and
|
|
`internal/modules/dnd/shared/*_test.go`: shared prompt and reference assembly.
|
|
- `internal/modules/integration/*_test.go`: black-box composition across
|
|
production extension domains.
|