11 KiB
Chunk Module Implementation Plan
This plan implements the accepted target state in Chunk Module Roadmap. It is written for an LLM coding agent that will implement each stage in order.
Before beginning any stage, review:
docs/policy/architecture.mddocs/policy/development.mddocs/policy/documentation.mddocs/roadmap/chunk.md
Do not move planned behavior into non-roadmap docs until the corresponding code is implemented. Do not revert unrelated user changes.
Stage 1: Framework Chunk Contract
Goal: make LLM-backed chunking first-class and enforce generic chunk result invariants without adding any D&D-specific framework behavior.
Code changes:
- Add
LLMClient contracts.StructuredLLMClienttocontracts.ChunkRequestininternal/framework/contracts/contracts.go. - Update
internal/framework/pipeline/runner.goso the runner passesinput.LLMClientto the chunker incontracts.ChunkRequest. - Add framework-level chunk result validation after
chunker.Chunkreturns and before lanes execute. - Keep validation source-generic. The validator should reject:
- empty chunk ID;
- duplicate chunk ID;
- chunk
SourceIDthat does not match the source document ID; - chunk
Indexthat does not match returned order; - empty chunk units;
- repeated source unit inside one chunk;
- source unit not found in the source document;
- chunk units that do not appear in source-document order.
- The validator must not require complete coverage and must not reject overlap between different chunks.
- Preserve existing warning behavior: append chunker warnings before returning chunk errors, as the runner does today.
Documentation changes:
- Update implemented internal docs under
docs/internal/to define the chunk module API and validation invariants once the code exists. - Keep examples and user docs unchanged in this stage unless an existing doc becomes inaccurate.
Tests:
- Update contract tests for the new
ChunkRequest.LLMClientfield where useful. - Add focused pipeline runner tests for each invalid chunk result case listed above.
- Add runner tests proving partial coverage and overlapping chunks remain accepted.
- Run:
go test ./internal/framework/contracts ./internal/framework/pipeline
Stage completion criteria:
- Existing generic chunking still works.
- A fake chunker can receive the structured LLM client through
ChunkRequest. - Framework tests prove the accepted generic chunk invariants.
Stage 2: D&D Scene Assets And Module Skeleton
Goal: revise the draft D&D scene prompt and schema into module-owned assets and add load/render plumbing without registering production behavior.
Asset decisions:
- Rename
internal/modules/chunk/dnd/scenes/assets/schemas/scene_map.schema.jsontointernal/modules/chunk/dnd/scenes/assets/schemas/dnd_scenes.v1.json. - Use these schema constants unless a code-local naming conflict requires a
mechanical adjustment:
- prompt ID:
dnd.scenes - response schema key:
dnd_scenes - response schema ID:
notarius.dnd.scenes - response schema version:
v1 - response schema name:
notarius_dnd_scenes_v1
- prompt ID:
- Use this structured response shape:
{
"scenes": [
{
"start_unit_id": "seg-001",
"end_unit_id": "seg-010",
"short_title": "Ambush at the gate",
"primary_mode": "Combat",
"main_participants": ["Aria", "Bandit mage"],
"summary": "The party fights the bandit mage at the gate.",
"boundary_note": "The scene begins when combat starts and ends when the immediate threat is resolved.",
"boundary_confidence": "High"
}
],
"boundary_caveats": []
}
- Required top-level fields:
scenes,boundary_caveats. - Required scene fields:
start_unit_id,end_unit_id,short_title,primary_mode,main_participants,summary,boundary_note,boundary_confidence. - Boundary fields are source-unit ID strings, not integers.
primary_modeenum:Recap,Discussion,Combat,Narrative.boundary_confidenceenum:High,Medium,Low.- Keep
additionalProperties: falsethroughout the schema. - Do not include model-authored final chunk IDs or chunk indexes in the schema. The Go module assigns deterministic chunk IDs and indexes.
Prompt decisions:
- Keep D&D-specific scene guidance in the D&D scene module.
- Make the user prompt a Go template similar to the spell extractor prompt.
- Include source document ID and ordered source units.
- Include selected source-unit metadata when present:
speaker,start, andend. - Align prompt terms exactly with schema field names and enum values.
- Keep
dnd/scenesmodule policy explicit in the prompt: full coverage, sequential scenes, no gaps, no overlap, exact source-unit IDs.
Code changes:
- Add
assets.gowith anembed.FSfor prompts and schemas. - Add
schema.gowith the constants and aloadResponseSchemafunction usingllm.LoadResponseSchema, following the pattern ininternal/modules/extract/dnd/spells/schema.go. - Add prompt rendering code using
framework/prompt.Bundle, following the pattern ininternal/modules/extract/dnd/spells/prompt.go. - Add internal response structs for the schema shape.
- Do not register the module in
internal/cli/catalog.goin this stage.
Tests:
- Add tests that the schema loads, is valid JSON, has the expected metadata, and rejects the old integer-boundary assumption through Go-side type expectations.
- Add prompt rendering tests that source unit IDs and selected metadata appear in the rendered user prompt.
- Run:
go test ./internal/modules/chunk/dnd/scenes
Stage completion criteria:
- The scene schema and prompts are loadable embedded assets.
- The prompt/schema terminology is internally consistent.
- No production catalog behavior changes yet.
Stage 3: D&D Scene Chunker Implementation
Goal: implement dnd/scenes as a contract-compliant chunk module with strict
module-owned validation.
Module decisions:
- Package path:
internal/modules/chunk/dnd/scenes. - Package name:
scenes. - Module key:
dnd/scenes. ModuleSpec:Stage:pipeline.StageChunkRequires:source.transcriptProvides:chunks,chunks.scenes
- Constructor:
New() *Chunker. - Registration function:
Register(registry *pipeline.ChunkerRegistry) error. - No module options initially. Reject non-empty options with an actionable module-prefixed error unless a clear option is implemented in the same stage.
Chunking behavior:
- Validate
context.Context, source document, non-empty source units, and non-nilLLMClient. - Render the scene prompt over the full source document.
- Call
LLMClient.CompleteStructuredwith:StageName:dnd/scenes- response schema name and schema JSON from the module schema loader.
- Validate the decoded response before producing chunks:
scenesmust be present and non-empty;- every boundary ID must exist in the source document;
- each scene start must be at or before its end;
- the first scene starts at the first source unit;
- the final scene ends at the final source unit;
- scenes are contiguous in source order;
- scenes do not overlap;
- required metadata fields are non-empty after trimming;
main_participantsentries are trimmed and empty entries rejected.
- Assign deterministic chunk fields:
ID:scene-000001,scene-000002, and so on;SourceID: source document ID;Index: zero-based returned order;Units: defensive copies of the source units in the scene range.
- Store per-scene metadata on each chunk:
scene_titleprimary_modemain_participantssummaryboundary_noteboundary_confidencestart_unit_idend_unit_idunit_count
- Convert each
boundary_caveatsentry into acontracts.Warningwith:Scope:dnd/scenesReasonCode:scene_boundary_caveatMessage: the caveat text.
- Fail explicitly for malformed model output. Do not fall back to
generic. - Implement
contracts.ManifestMetadataProviderand include prompt and response-schema provenance without raw prompts, raw schemas, source text, or secrets.
Tests:
- Registration and
ModuleSpec. - Successful chunking from a fake LLM response.
- Prompt request uses the expected schema name and schema JSON.
- Caveats become warnings.
- Defensive copy behavior for source units and metadata.
- Errors for nil context, nil source, invalid source, nil LLM client, empty model scenes, unknown boundary ID, out-of-order boundaries, gaps, overlap, incomplete coverage, empty metadata fields, and non-empty unsupported options.
- Manifest metadata contains prompt/schema provenance.
- Run:
go test ./internal/modules/chunk/dnd/scenes
go test ./internal/framework/pipeline
Stage completion criteria:
dnd/scenesworks in focused tests with fake LLM clients.- It is still not production-registered unless Stage 4 is completed.
Stage 4: Production Registration And Implemented Docs
Goal: make dnd/scenes available in production configuration and document only
the behavior that now exists.
Code changes:
- Register
dnd/scenesininternal/cli/catalog.go. - Add or update catalog/default module tests so the production catalog exposes the new chunk module.
- Add CLI/config validation tests proving a pipeline can select
chunk: dnd/scenes. - Do not change the existing maintained example config unless the related CLI fixture tests are updated to keep it loadable and useful.
Documentation changes:
- Update
docs/config.mdimplemented production module tables and chunk module notes. - Update
docs/cli.mdimplemented production module list. - Update
docs/internal/modules.mdwithdnd/scenesbehavior, capabilities, metadata, and failure policy. - Update or add internal chunk-module documentation if Stage 1 did not already create a clear API reference.
- Update
docs/troubleshooting.mdfor common scene chunker failures: malformed model output, invalid boundaries, incomplete coverage, and provider failures during chunking. - Keep roadmap docs for any deferred options or future prompt tuning.
Tests:
go test ./internal/cli
go test ./internal/core/config
go test ./internal/framework/pipeline
go test ./internal/modules/chunk/dnd/scenes
Stage completion criteria:
- Config resolution can bind
dnd/scenes. - User and internal docs describe the implemented module accurately.
- Existing examples and CLI docs remain truthful.
Stage 5: Full Verification
Goal: verify the complete feature across contracts, production wiring, docs, and the command entry point.
Run:
go test ./...
go vet ./...
go build ./cmd/notarius
Inspect diagnostics-sensitive output manually in tests or fixtures where relevant:
- no raw prompts, source text, provider payloads, API keys, or secrets in manifest metadata;
- errors name the module and operation;
- warnings are preserved in
RunOutput.Warnings; - run manifests record the
dnd/sceneschunker when selected.
Stage completion criteria:
- Full validation commands pass.
- The feature is documented as implemented only where code supports it.
docs/roadmap/chunk.mdretains target-state context and does not duplicate current-behavior reference material.