Files
ansible-workspace-dnd/docs/roadmap/features/0008-opinionated-dnd-processing-configuration.md

26 KiB

Feature 0008: Opinionated D&D Processing Configuration

Status: ready

Summary

Turn the installed application suite and deployed D&D assets into a coherent processing configuration. The pipeline role will supply deliberately opinionated Audita and Narratio policy, split Narratio's suite-owned processing and artifact definitions into explicit ConfigKit fragments, and provide a named testing profile for inexpensive prompt and model iteration without changing production policy.

Problem or Opportunity

Features 0006 and 0007 install the five applications, connect their standard paths, and deploy valid campaigns, prompts, and schemas. The assembled role still leaves most optional application policy unset. Narratio can validate its minimal root document and discover content, but it does not yet describe the D&D trimming, rendering, recap, rumor, scene-map, or per-character analysis workflow.

A current test-machine configuration provides useful evidence of the intended workflow, but it cannot be copied. It includes pre-Narratio-2.0 syntax, installation-specific storage and inference settings, obsolete paths, campaign-specific character entries, and redundant artifact dependencies. The current application repositories remain authoritative for supported configuration.

Narratio 2.0 also provides two useful composition mechanisms that the suite has not yet adopted: additive root imports for independently owned base fragments and a fixed profiles/testing.yml overlay. Using both will make the production policy reviewable and make inexpensive development runs easy to select without editing the production configuration.

Governing Policies

  • The Ansible house style governs the suite-owned public interface, templates, direct desired-state tasks, and omission of unselected application defaults.
  • The testing house style governs native behavioral validation, explicit testing inputs, and clean repeated convergence.
  • The MVP roadmap assigns opinionated cross-application and D&D policy to the pipeline role while keeping standalone application roles generic.
  • Decision 0001 requires direct module-owned convergence without supplemental state or redundant verification.

Scope

  • Supply the complete reviewed Audita configuration as deliberate D&D suite policy, including its context, schema, module sequence, endpoint, models, credential environment-variable names, timeouts, retries, concurrency, chunking, normalization, thresholds, and diagnostics settings.
  • Configure Narratio's normalization, trimming, and Markdown rendering stages through its current public contract, explicitly pinning only the schemas, identifiers, enablement choices, and paths that form the D&D suite's cross-stage contract.
  • Use the deployed dnd.session_bounds prompt for transcript-bound detection.
  • Define each ordinary Narratio Scriptorium artifact in its own managed YAML fragment:
    • session recap;
    • hostile rumors;
    • deranged rumors; and
    • scene map.
  • Define per-character gameplay analysis as one Narratio artifact-family fragment over party.characters, not as campaign-specific artifact entries.
  • Supply only the inputs declared by each current prompt definition.
  • Let each production prompt select its own declared Promptkit default profile unless the roadmap records a concrete reason for a suite override.
  • Manage a valid profiles/testing.yml Narratio overlay that selects an inexpensive Scriptorium profile while leaving the base production policy and inherited Audita configuration unchanged.
  • Expose the suite-owned testing-profile choice through normal Ansible inventory precedence.
  • Compose the base fragments through an explicit ordered narratio_configkit_imports list in the standalone Narratio role's root configuration.
  • Create and manage the required conf.d, artifacts, artifact-families, and profiles directories and their suite-owned files under /usr/local/etc/narratio.
  • Document production and testing invocations, the imported layout, public variables, and the boundary with later pipeline features.
  • Extend focused integration coverage for both base and testing resolution, representative artifact relationships, party-driven family expansion, and immediate clean repeated convergence.

Non-goals

  • Enabling Narratio's Notarius stage or installing the uploaded Notarius pipeline. Its multi-stage D&D extraction, campaign reference bindings, output descriptors, and runtime directories remain a separate feature.
  • Configuring S3 or other remote storage, publishing outputs, upload behavior, or cleanup-after-publish.
  • Selecting a default campaign. Campaign choice remains an inventory or invocation decision.
  • Delivering API keys, object-storage credentials, environment files, or a general secret-management mechanism.
  • Selecting human operators or managing their Narratio group membership.
  • Adding a scheduler, service, or automated invocation.
  • Running WhisperX, Audita model calls, Scriptorium model calls, Notarius, or a complete transcript during integration tests.
  • Copying the test-machine configuration verbatim or preserving its obsolete Narratio, campaign, Scriptorium, or credential paths.
  • Duplicating prompt content, prompt schemas, built-in Promptkit profiles, or application validation rules in the pipeline role.
  • Modifying the standalone application roles or upstream application source.
  • Collection assembly, role releases, asset release policy, upgrade/removal behavior, or end-to-end production validation.

Target End State

The standalone Narratio role continues to own /usr/local/etc/narratio/pipeline.yml. That root document contains the installation paths already supplied by the pipeline role and an explicit list of suite-owned relative imports. The pipeline role owns the imported files:

/usr/local/etc/narratio/
├── pipeline.yml
├── conf.d/
│   └── processing.yml
├── artifacts/
│   ├── session-recap.yml
│   ├── hostile-rumors.yml
│   ├── deranged-rumors.yml
│   └── scene-map.yml
├── artifact-families/
│   └── character-meta-analysis.yml
└── profiles/
    └── testing.yml

Each base artifact or family key is declared by exactly one fragment. The root uses explicit path imports rather than globs; Narratio therefore loads only the files selected by current suite policy, even if an obsolete file is left on a previously managed host. Imported maps remain additive and no two base sources claim the same leaf.

The production configuration uses the deployed prompt definitions and their frontier-oriented default profiles. Audita uses the selected https://inference.ai.rakestrawhome.com/v1 endpoint and google/gemma-4-31b-it proposal and validation model. Narratio's canonical processing paths and schemas are suite-owned contracts rather than incidental copies of application defaults. Session recap consumes the final trimmed transcript and may consume the previous session's recap. Hostile and deranged rumors consume the current recap, allowing Narratio to infer their dependency without a duplicate depends_on declaration. Scene map is configured as an available, normally disabled artifact. Character analysis is an available party-driven family whose generated members receive character.name and character.class_summary through family member variables.

The installed testing profile is a valid overlay selected with --profile testing. It selects gemini-flash-latest for each Scriptorium artifact and artifact family while inheriting the base topology, paths, prompts, inputs, outputs, and enabled state. Audita inherits the same endpoint and model in both modes for now, so the overlay does not restate its base configuration. The testing profile neither imports files nor contains credentials. Operators can validate, inspect, or run the same session under base or testing policy without modifying an Ansible-managed file.

Repository Ownership

  • ansible-role-dnd-pipeline owns the suite variables, Narratio fragment and testing-profile templates, direct directory/file convergence, dependency variable wiring, consumer documentation, and integration coverage. It is the only implementation repository expected to change.
  • ansible-role-narratio remains unchanged. It owns the root pipeline template and the public narratio_configkit_imports and stage variables through which the suite composes it.
  • ansible-role-audita remains unchanged. It owns Audita's field-specific configuration interface; the pipeline role selects only intentional D&D policy through that interface.
  • ansible-role-scriptorium, assets/narratio-prompts, and ../promptkit remain unchanged authorities for source-directory configuration, prompt contracts, and built-in production/testing profile choices.
  • ../audita and ../narratio remain unchanged authorities for current application configuration and native inspection behavior.
  • ansible-role-notarius and ../notarius are read-only inputs for the later D&D extraction feature.
  • rakestraw-ansible and the uploaded test-machine configurations are historical and operational references, not application contracts.
  • ansible-workspace-dnd owns this roadmap, the later implementation plan, settled MVP decisions, and aggregate status.

Constraints and Settled Decisions

  • Standalone application roles remain generic. Every concrete value added by this feature must represent policy deliberately owned by the D&D suite.
  • Application defaults observed in documentation or the uploaded files are not copied merely to restate them. An explicit suite value must preserve a chosen outcome across upstream default changes.
  • The pipeline explicitly owns a value when another stage, artifact, prompt, or future publishing rule relies on its schema, identifier, enabled state, or path. Behavior confined to Narratio inherits Narratio's application default unless the suite has independently selected that behavior as policy.
  • The pipeline role does not duplicate Narratio's root template. It acts as a caller: the standalone role renders the root and the pipeline role deploys the suite-owned fragments named by that root.
  • Every ordinary artifact and every artifact family has its own source and installed file. General stage policy may share conf.d/processing.yml.
  • Imports are explicit relative path entries. Globs are not used because the role does not need directory discovery and must not activate stale files accidentally.
  • The imported files cannot contain configkit, nested imports, or profile directives. The testing overlay cannot import or stack other profiles.
  • Suite-managed configuration directories are root:narratio mode 0750; files are root:narratio mode 0640, matching the established Narratio configuration boundary.
  • The role declares directory and template state directly. It does not inspect files first, validate production configuration during convergence, keep manifests, or track fragment digests.
  • The base artifact definitions omit profile_id when the deployed prompt's declared default is the selected production policy.
  • Artifact inputs must match the current prompt contracts:
    • session recap: required transcript, optional recap;
    • hostile and deranged rumors: required recap;
    • scene map: required transcript; and
    • character analysis family: required transcript, optional recap, plus member variables for character_name and character_class.
  • A narratio.artifact.session_recap input already creates the rumor dependency. The base fragments do not repeat that edge with depends_on.
  • Scene map and character analysis are configured but disabled by default; Narratio's explicit artifact selection may still run their concrete entries.
  • The character family uses for_each: party.characters, an output path with exactly one {character_id} token, and member selectors character.name and character.class_summary. It contains no hard-coded campaign character names.
  • Production and testing policy never embeds secret values. Credential delivery remains a later feature.
  • The testing profile is a single valid overlay at the native fixed location. It overrides each Scriptorium artifact and family profile_id with the suite's gemini-flash-latest testing-profile variable rather than duplicating complete definitions. Audita deliberately uses the same base endpoint and models under both configurations.
  • Each fixed artifact or family fragment has one complete native-mapping variable: dnd_pipeline_narratio_session_recap_artifact, dnd_pipeline_narratio_hostile_rumors_artifact, dnd_pipeline_narratio_deranged_rumors_artifact, dnd_pipeline_narratio_scene_map_artifact, and dnd_pipeline_narratio_character_analysis_family. The file names, imports, and top-level source keys remain fixed suite topology; callers customize the mapping and disable an available source with enabled: false rather than removing its managed fragment or import.

Selected Narratio Coordination Policy

The pipeline role pins the following effective Narratio fields because they connect processing stages, prompt contracts, or stable suite outputs. A value that currently equals an application default is still intentional suite policy when an upstream change would otherwise break that connection.

Native Narratio field D&D suite default Coordination purpose
pipeline.seriatim.output_schema seriatim-intermediate Establishes the merge-stage transcript contract.
pipeline.audita.output_schema audita-v1 Matches the Audita configuration and adapter output contract.
pipeline.normalize.output_path transcripts/final.json Provides the canonical normalized transcript source.
pipeline.normalize.output_schema seriatim-intermediate Provides the canonical schema consumed by later stages.
pipeline.trim.enabled true Makes the trimmed transcript part of the selected D&D workflow.
pipeline.trim.output_path transcripts/final.trimmed.json Provides the canonical transcript consumed by D&D artifacts.
pipeline.trim.bounds.prompt_id dnd.session_bounds Selects the deployed D&D bounds prompt.
pipeline.trim.bounds.transcript_input_name transcript Matches that prompt's declared input contract.
pipeline.trim.bounds.output_path artifacts/session_bounds.json Provides a stable bounds artifact location.
pipeline.render.enabled true Selects rendered transcripts as a suite outcome.
pipeline.render.format markdown Selects the suite's rendered transcript format.

The fixed artifact mappings own these output paths:

Source D&D suite output
session_recap artifacts/session_recap.md
hostile_rumors artifacts/hostile_rumors.md
deranged_rumors artifacts/deranged_rumors.md
scene_map artifacts/scene_map.json
character_meta_analysis family artifacts/character_meta_analysis/{character_id}.md

The processing fragment omits Narratio-local choices such as reports, timeouts, debug rendering, work-directory retention, render title, timestamp, segment-ID, and metadata presentation, and the bounds prompt profile. Narratio continues to supply those defaults. Likewise, the Narratio Audita adapter does not repeat Audita's endpoint, models, module sequence, tuning, or diagnostic settings: it uses the pipeline-managed Audita configuration file. The Audita output schema is the deliberate exception because it spans that application boundary, and one suite value must feed both configurations.

Audita does not choose a fixed final transcript path in this integration. Narratio supplies the run-specific --output path when invoking Audita and then normalizes the result to the canonical path above. The role therefore does not invent a separate Audita output-path setting.

Selected Audita and Testing Policy

The pipeline role deliberately owns all of the following Audita values. They are suite defaults, not assertions about Audita's upstream defaults, and each remains replaceable through the corresponding suite-prefixed role variable.

Native Audita field D&D suite default
pipeline.modules [glossary, homophones, glossary, spoken_word, grammar]
output.schema audita-v1
llm.proposal.base_url https://inference.ai.rakestrawhome.com/v1
llm.proposal.model google/gemma-4-31b-it
llm.proposal.api_key_env AUDITA_LLM_API_KEY
llm.proposal.timeout 900s
llm.proposal.max_retries 3
llm.validation.base_url https://inference.ai.rakestrawhome.com/v1
llm.validation.model google/gemma-4-31b-it
llm.validation.api_key_env AUDITA_VALIDATION_LLM_API_KEY
llm.validation.timeout 900s
llm.validation.max_retries 3
concurrency.total_llm 4
concurrency.proposal_llm 4
concurrency.validation_llm 4
chunking.target_sections 8
chunking.max_section_tokens 6144
chunking.min_section_tokens 2048
normalization.max_segment_gap 3s
normalization.ellipsis_gap 3s
normalization.max_segment_duration 240s
normalization.max_segment_tokens 2048
thresholds.glossary 0.8
thresholds.homophones 0.8
thresholds.spoken_word 0.8
thresholds.grammar 0.8
context.description The following transcript was recorded during a Dungeons & Dragons game session. It may contain some unrelated pre-session or post-session banter, in addition to actual D&D gameplay.
diagnostics.work_dir /tmp/audita
diagnostics.retention auto

The repeated glossary entry is intentional and preserves the selected multi-pass module sequence. Environment-variable names are configuration, not secret values; the later secret-delivery feature will provide their contents.

The testing overlay uses one suite variable whose default is gemini-flash-latest for every Scriptorium artifact and artifact family. Callers may replace that profile normally. Audita uses the production endpoint and models in testing until the suite deliberately selects alternatives; the overlay omits identical Audita fields rather than writing them twice. These model choices are expected to evolve rapidly and can be updated as ordinary suite policy without changing the fragment architecture.

Simplest Viable Implementation

The production change should remain a small configuration extension:

  1. Add only the suite variables required by the selected Audita policy, selected Narratio coordination policy, fragment mappings, and testing-profile override; align the argument specification.
  2. Pass the Audita choices and explicit Narratio import list through the existing dependency interfaces.
  3. Create the four Narratio configuration subdirectories with one ansible.builtin.file loop.
  4. Render the processing fragment, four artifact fragments, one family fragment, and testing overlay with one ansible.builtin.template loop.
  5. Update the README and extend the existing integration driver with native base/testing validation and a clean repeat.

No preliminary stat, configuration assembly fact, handler, validation command, checksum, manifest, or fragment cleanup task is required. Explicit imports make an obsolete unreferenced file inert without destructive directory reconciliation.

Rationale and Alternatives

ConfigKit fragments preserve the application's native composition model and give each artifact a focused review boundary. Rendering one monolithic Narratio mapping through the standalone root variable would produce a valid file but would discard that operational and editorial advantage. Reimplementing the entire root template in the pipeline role would duplicate the standalone role and create competing configuration ownership.

Explicit imports are preferred to globs because the suite already knows every managed fragment. A glob would add discovery behavior and could keep a removed artifact active through a stale file. Deleting and recreating the directory on every run would harm idempotence and caller safety merely to compensate for that avoidable ambiguity.

One testing overlay is preferable to a second complete configuration tree. Profiles replace only selected leaves after base composition, so topology and paths cannot drift between production and development. The selected gemini-flash-latest default provides immediate value while remaining one ordinary role-default change when model economics evolve.

The uploaded Notarius pipeline is concrete and valid, but adding it here would combine a ten-lane extraction contract, campaign-reference mapping, output descriptor mapping, runtime directories, and model policy with an already coherent Narratio/Scriptorium feature. Keeping it separate makes both reviews smaller and preserves a clear acceptance boundary.

Acceptance Criteria

Required Configuration Behavior

  • The pipeline role produces the documented imported configuration layout with one file per artifact and artifact family.
  • The root pipeline document contains the exact explicit relative imports and no glob imports.
  • Base Narratio configuration validates natively for either deployed campaign.
  • The effective base configuration uses the selected Seriatim, Audita, normalization, trimming, bounds, and rendering contracts and the canonical artifact output paths documented above.
  • narratio config artifacts reports a valid recap-to-rumor graph and expands the character-analysis family for the selected campaign.
  • The recap, rumor, scene-map, and character-family definitions use only inputs and variables supported by their deployed prompt definitions and Narratio's current source vocabulary.
  • The two rumor dependencies are inferred from their recap input sources and are not duplicated as explicit ordering edges.
  • Scene map and the character-analysis family are available but disabled by default; recap and both rumor artifacts are enabled.
  • Production artifacts inherit their selected profiles from the prompt definitions unless an expressly agreed suite override is documented.
  • Audita's managed configuration contains the selected D&D policy and remains valid through Audita's native validator.
  • The same suite-owned audita-v1 schema is supplied to Audita's managed configuration and Narratio's Audita adapter; Narratio supplies Audita's run-specific output path rather than relying on a second fixed path.
  • profiles/testing.yml is a valid, independently selectable Narratio profile that selects the configured inexpensive Scriptorium profile for every artifact and family and inherits base workflow structure.
  • The testing profile does not repeat Audita configuration while production and testing deliberately share the same Audita endpoint and models.
  • Base and testing configuration can be compared with narratio config diff default testing without requiring a model call.
  • All suite-managed configuration remains readable by the narratio group and is not made writable by runtime or human operator accounts.
  • An immediate repeated role application with unchanged inputs reports no changes.
  • The role contains no configuration probes, production self-validation, fragment manifests, duplicate root template, secrets, Notarius integration, storage, or publishing behavior.

Required Validation

  • YAML syntax checking and production-profile ansible-lint pass for the role and test playbooks.
  • The complete existing pipeline integration entry point continues to install the pinned role combination and validate asset discovery.
  • Audita natively validates the role-managed D&D configuration.
  • Narratio natively validates both base and testing configuration with an explicitly selected deployed campaign.
  • Narratio's native artifact inspection demonstrates one enabled ordinary artifact, one inferred dependency, and representative family expansion.
  • A test explicitly supplies a representative testing Scriptorium profile and observes its effective selection; it does not assert that the same value remains the role's current default.
  • Scriptorium can resolve the representative production and testing profiles through its native inspection interface without making a provider request.
  • The immediate repeat reports changed=0 and failed=0.
  • Tests do not snapshot full rendered files, enumerate every character or artifact, inspect template/file task results, test filesystem metadata, or reproduce ConfigKit, Narratio, Audita, Scriptorium, or Promptkit validation.

Dependencies and Follow-up Work

Features 0001 through 0007 and the standalone-role test-suite simplification are complete. Feature 0008 depends on the current Narratio 2.0 ConfigKit contract, the canonical party files deployed by Feature 0007, and prompt definitions whose production default profiles are available from Promptkit.

Feature 0009 should adapt the validated D&D Notarius pipeline, remove its hard-coded campaign references in favor of Narratio invocation bindings, declare its runtime-directory policy, map its accepted outputs into Narratio, and enable extraction. Later features should address storage/publishing and secret delivery together, operator access, collection assembly, and an end-to-end workflow that can use actual external services.

Potential Future Hardening

  • Use ConfigKit source inspection in operational diagnostics to show which managed fragment supplied an effective value.
  • Add a controlled cleanup policy for obsolete suite fragments if accumulated inert files become an operational problem.