Compare commits

..

29 Commits

Author SHA1 Message Date
88a0eaacf5 Record completion of the Notarius role upgrade 2026-09-15 20:05:28 +00:00
1806bfaf7f Prepare the D&D Notarius integration sprint 2026-09-15 19:55:48 +00:00
f91871ba0f Complete the shared pipeline filesystem feature 2026-09-15 15:02:05 +00:00
69961180a2 Record shared pipeline implementation validation 2026-09-15 01:11:43 +00:00
f605fa0c1a Mark shared pipeline execution documentation complete 2026-09-15 00:47:14 +00:00
1e0d4d0788 Mark cross-identity pipeline access testing complete 2026-09-15 00:39:04 +00:00
dcc1103358 Mark shared pipeline ACL management complete 2026-09-15 00:14:49 +00:00
daa08e6156 Mark shared configuration ownership complete 2026-09-15 00:05:36 +00:00
fa348e9376 Clear the shared pipeline dependency blocker 2026-09-14 23:49:08 +00:00
7d92867ba7 Record the remaining shared filesystem work 2026-09-14 23:47:28 +00:00
398562a2ca Record shared pipeline dependency publication blocker 2026-09-14 14:05:50 +00:00
efc7905798 Mark Narratio configuration ownership complete 2026-09-14 14:05:06 +00:00
8143732741 Mark Scriptorium configuration ownership complete 2026-09-14 14:00:13 +00:00
cb90d63a2b Mark Notarius configuration ownership complete 2026-09-14 13:57:06 +00:00
52fa8ac918 Mark Audita configuration ownership complete 2026-09-14 13:54:01 +00:00
f6b6c7196b Prepare the shared pipeline filesystem sprint 2026-09-14 13:45:55 +00:00
a7d718970f Document shared pipeline filesystem policy 2026-09-14 13:02:12 +00:00
e63b334887 Complete the D&D processing configuration feature 2026-09-11 04:40:48 +00:00
562eb540b8 Mark processing configuration documentation complete 2026-09-11 02:45:26 +00:00
870fc7b739 Mark processing configuration tests complete 2026-09-11 02:38:30 +00:00
9f0d11d897 Mark Narratio processing configuration complete 2026-09-11 02:23:42 +00:00
663dce1a9c Mark Audita policy complete 2026-09-11 02:10:28 +00:00
b83b778751 Prepare the D&D processing configuration sprint 2026-09-11 02:03:17 +00:00
daab85ae7e Complete D&D asset deployment 2026-09-10 17:20:20 +00:00
fb3c95d462 Mark asset integration coverage complete 2026-09-10 15:48:22 +00:00
ca0380b208 Mark asset deployment complete 2026-09-10 15:43:53 +00:00
3b2c47d236 Mark prompt asset corrections complete 2026-09-10 15:42:02 +00:00
4765586004 Mark campaign alignment complete 2026-09-10 15:41:17 +00:00
5fdd92b297 Plan D&D asset deployment 2026-09-10 15:37:00 +00:00
15 changed files with 2882 additions and 131 deletions

View File

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

View File

@@ -0,0 +1,160 @@
workspace:
root: /var/lib/narratio
cleanup_after_publish: true
secrets:
env_dir: /usr/local/etc/narratio/secrets
campaigns:
root: /usr/local/etc/narratio/campaigns
default_campaign_id: dilfs
storage:
backend: s3
s3:
endpoint: "https://s3.us-east-005.backblazeb2.com"
bucket: "rakestraw-assets"
root_prefix: "dnd"
region: "us-east-1"
force_path_style: True
access_key_id_env: OBJECT_STORAGE_KEY_ID
secret_access_key_env: OBJECT_STORAGE_KEY
whisperx:
transcribe_url: https://transcription.ai.rakestrawhome.com/transcribe
publish:
enabled: true
upload_run: true
outputs:
- source: narratio.transcript.final
required: true
- source: narratio.transcript.final_trimmed
required: true
- source: narratio.transcript.final_markdown
required: true
- source: narratio.transcript.final_trimmed_markdown
required: true
- source: narratio.artifact.session_recap
dest: artifacts/session_recap.md
required: true
- source: narratio.artifact.hostile_rumors
dest: artifacts/hostile_rumors.md
required: true
- source: narratio.artifact.deranged_rumors
dest: artifacts/deranged_rumors.md
required: false
scriptorium:
binary: scriptorium
config_path: /usr/local/etc/scriptorium/config.yml
timeout: 10m
render_debug: false
artifacts:
session_recap:
enabled: true
prompt_id: dnd.session_recap
profile_id: claude-fable-latest
output_path: artifacts/session_recap.md
timeout: 10m
inputs:
transcript:
source: narratio.transcript.final_trimmed
required: true
players:
source: narratio.input.players
required: true
party:
source: narratio.input.party
required: true
# recap:
# source: narratio.previous_session.artifact.session_recap
# required: false
scene_map:
enabled: false
prompt_id: dnd.scene_map
profile_id: claude-haiku-latest
output_path: artifacts/scene_map.json
timeout: 10m
inputs:
transcript:
source: narratio.transcript.final_trimmed
required: true
players:
source: narratio.input.players
required: true
party:
source: narratio.input.party
required: true
character_meta_analysis_alan:
enabled: false
prompt_id: dnd.character_meta_analysis
profile_id: claude-fable-latest
output_path: artifacts/character_meta_analysis_alan.md
timeout: 10m
inputs:
transcript:
source: narratio.transcript.final_trimmed
required: true
players:
source: narratio.input.players
required: true
party:
source: narratio.input.party
required: true
recap:
source: narratio.previous_session.artifact.session_recap
required: false
vars:
character_name: "Alan"
character_class: "Druid"
character_meta_analysis_hrank:
enabled: false
prompt_id: dnd.character_meta_analysis
profile_id: claude-fable-latest
output_path: artifacts/character_meta_analysis_hrank.md
timeout: 10m
inputs:
transcript:
source: narratio.transcript.final_trimmed
required: true
players:
source: narratio.input.players
required: true
party:
source: narratio.input.party
required: true
recap:
source: narratio.previous_session.artifact.session_recap
required: false
vars:
character_name: "Hrank"
character_class: "Cleric"
hostile_rumors:
enabled: true
prompt_id: dnd.hostile_rumors
output_path: artifacts/hostile_rumors.md
timeout: 10m
depends_on:
- session_recap
inputs:
recap:
source: narratio.artifact.session_recap
required: true
deranged_rumors:
enabled: true
prompt_id: dnd.deranged_rumors
output_path: artifacts/deranged_rumors.md
timeout: 10m
depends_on:
- session_recap
inputs:
recap:
source: narratio.artifact.session_recap
required: true

View File

@@ -0,0 +1,154 @@
version: 4
output:
directory: /var/lib/notarius/output
debug:
directory: /var/lib/notarius/debug
cache:
chunk_plans:
mode: auto
directory: /var/lib/notarius/cache/chunk_plans
checkpoints:
enabled: true
directory: /var/lib/notarius/cache/checkpoints
pipelines:
dnd-session:
llm_profile: dnd-extraction
# llm_profile: rakestrawhome-gemma-4-31b
input: seriatim
# Stable campaign context is shared by every module that accepts these slots.
references:
party: /usr/local/etc/notarius/campaigns/centaurs/party.yml
glossary: /usr/local/etc/notarius/campaigns/centaurs/glossary.yml
chunk:
module: dnd/scenes
retries: 2
output:
module: json
options:
include_chunk_map: true
evidence_context:
enabled: true
window_units: 3
lanes:
- item-occurrences
- item-registry
- location-registry
- location-occurrences
- npc-registry
- spells
- combat-turns
- npc-occurrences
- enemy-events
steps:
# Establish session-wide reference artifacts before their consumers.
- id: describe-session
artifacts:
item-registry:
extract:
module: dnd/item-registry
retries: 2
merge: appendorder
normalize: dnd/item-registry
npc-registry:
extract:
module: dnd/npc-registry
retries: 2
merge: appendorder
normalize:
module: dnd/npc-registry
retries: 2
location-registry:
extract:
module: dnd/location-registry
retries: 2
merge: appendorder
normalize:
module: dnd/location-registry
retries: 2
scene-descriptions:
extract:
module: dnd/scene-descriptions
retries: 2
merge: appendorder
normalize: dnd/scene-descriptions
- id: extract-events
# Accepted registry artifacts and scene-description eligibility artifacts
# are supplied in memory to their compatible consumers in this step.
references:
location_registry:
artifact:
step: describe-session
lane: location-registry
npc_registry:
artifact:
step: describe-session
lane: npc-registry
scene_descriptions:
artifact:
step: describe-session
lane: scene-descriptions
item_registry:
artifact:
step: describe-session
lane: item-registry
artifacts:
item-occurrences:
extract:
module: dnd/item-occurrences
retries: 2
merge: appendorder
normalize: dnd/item-occurrences
spells:
extract:
module: dnd/spells
retries: 2
merge: appendorder
normalize:
module: dnd/spells
combat-turns:
extract:
module: dnd/combat-turns
retries: 2
merge: appendorder
normalize: dnd/combat-turns
npc-occurrences:
extract:
module: dnd/npc-occurrences
retries: 2
merge: appendorder
normalize: dnd/npc-occurrences
location-occurrences:
extract:
module: dnd/location-occurrences
retries: 2
merge: appendorder
normalize: dnd/location-occurrences
- id: track-enemies
references:
npc_registry:
artifact:
step: describe-session
lane: npc-registry
scene_descriptions:
artifact:
step: describe-session
lane: scene-descriptions
combat_turns:
artifact:
step: extract-events
lane: combat-turns
npc_occurrences:
artifact:
step: extract-events
lane: npc-occurrences
artifacts:
enemy-events:
extract:
module: dnd/enemy-events
retries: 2
merge: appendorder
normalize: dnd/enemy-events

View File

@@ -0,0 +1,5 @@
# Ansible managed
prompt_dir: /usr/local/etc/scriptorium/library/prompts
profile_dir: /usr/local/etc/scriptorium/library/profiles
schema_dir: /usr/local/etc/scriptorium/library/schemas

View File

@@ -0,0 +1,70 @@
# Decision 0002: Shared, Readable Pipeline Filesystem Policy
Status: accepted
Date: 2026-09-14
## Context
The D&D pipeline may be invoked either by its dedicated `narratio` service
account or by a human operator who is already a member of the `narratio`
group. Both identities need a consistent view of application configuration and
shared writable state. Notarius versions before v0.7.0 imposed private cache
modes that prevented this deployment model, but v0.7.0 delegates cache access
policy to deployment provisioning.
The pipeline processes D&D campaign material. This deployment does not treat
configuration, transcripts, caches, generated artifacts, logs, or other
pipeline content as secret. API keys and similar credentials are the sole
confidential category and must remain isolated from ordinary content.
## Decision
The suite uses `narratio` as both its service identity and shared operator
group. A human account that is already a member of that group is a supported
pipeline invocation identity. Selecting operators and managing their group
membership remain separate deployment concerns.
Application configuration directories and files are owned by
`narratio:narratio` and are world-readable. Directories normally use `0755`
and files use `0644`. They remain Ansible-managed even though the service
account owns them; operators do not edit managed configuration in place.
Standalone application roles expose generic owner, group, and mode variables
and retain independently useful defaults. The opinionated pipeline role
selects the suite ownership policy through those interfaces.
Shared writable roots use `narratio:narratio` ownership and mode `2775`.
Setgid preserves the shared group, while managed default ACLs preserve owner
and group write access and world read/traverse access for newly created
content regardless of an invoking account's ordinary umask. Ordinary files
are expected to converge to the corresponding non-executable mode `0664`.
Application source trees and installed binaries remain root-owned and
world-readable or executable as appropriate.
Credential material belongs only beneath the suite's eventual `secrets/`
directory. That directory is not world-accessible; its expected directory and
file modes are `0750` and `0640`, respectively, with
`narratio:narratio` ownership so both supported invocation identities can read
shared credentials. Configuration may contain credential reference names but
never raw credential values.
Version-controlled campaign and prompt assets may remain root-managed because
Git is authoritative, but they are world-readable. The suite does not add
confidentiality controls to non-secret D&D content.
## Consequences
The pipeline can run under the service account or an existing human member of
the shared group without maintaining separate configuration or cache trees.
The deployment must provision setgid and default ACL behavior on shared
writable roots; directory modes alone do not guarantee group write access for
content created under an arbitrary user umask.
The broad readability of transcript-derived content is intentional. Hosts
requiring confidential campaign data need a different deployment policy and
are outside this MVP contract. Secret delivery remains future work and must
honor the separate restricted subtree rather than tightening unrelated files.
Existing content with incompatible ownership or ACLs is not recursively
migrated unless a feature expressly selects that behavior. Fresh convergence
and newly created content follow this policy.

View File

@@ -6,3 +6,8 @@ change. Number records sequentially, for example
`0001-application-and-suite-role-boundaries.md`.
Do not create a decision record for routine implementation choices.
## Records
- [0001: Minimal, Module-Driven Ansible](0001-minimal-module-driven-ansible.md)
- [0002: Shared, Readable Pipeline Filesystem Policy](0002-shared-readable-pipeline-filesystem-policy.md)

View File

@@ -14,6 +14,9 @@ Repositories inside this directory:
role.
- `assets/narratio-prompts`: PromptKit-compatible prompts and schemas deployed
for Scriptorium by the pipeline role.
- `assets/configs`: snapshots of application configuration from a test machine;
treat them as non-authoritative operational references that may use obsolete
syntax or installation-specific values.
- `rakestraw-ansible`: working deployment repository containing the
`pipeline_dnd` proof of concept; treat it as read-only reference unless the
task explicitly includes it.
@@ -49,4 +52,7 @@ machine-readable inventory of paths and remotes.
contracts.
- Asset repositories: authoritative campaign and prompt-library content and
layout.
- Reference configurations under `assets/configs`: evidence of prior
operational choices, never an application contract or a source to copy
verbatim.
- Individual Ansible repositories: implementation and repository-local tests.

View File

@@ -0,0 +1,353 @@
# Feature 0007: D&D Asset Deployment and Scriptorium Integration
Status: done
## Summary
Extend the standalone D&D pipeline role to deploy the authoritative campaign
registry and Narratio prompt library, then connect those assets to Narratio
and Scriptorium through the application roles' existing public interfaces.
The result is an assembled suite in which Narratio can resolve a deployed
campaign and Scriptorium can discover the deployed D&D prompts and schemas.
## Problem or Opportunity
Feature 0006 composes and configures all five applications, but intentionally
leaves the suite's content roots empty. A consumer still has to deploy the
`campaigns` and `narratio-prompts` repositories separately and override
application configuration before the installed tools can find that content.
Both authoritative content repositories are now present in the workspace.
Their layouts make the required integration concrete: the campaign repository
is already organized as Narratio's campaign registry, while the prompt
repository contains top-level `prompts/` and `schemas/` trees. The prompt
repository does not contain execution profiles, so this feature must not
invent or configure a profile directory on its behalf.
Inspection also found four stale references in the current prompt content.
The character-analysis and session-recap definitions name a shared Markdown
file that does not exist under that name, and the two JSON-schema prompts name
schema paths that do not match the repository's `schemas/` layout. Deploying
those definitions without correcting their source would leave known-broken
suite content.
Both campaign definitions also retain an `inputs.players_file` field that
Narratio 2.0 rejects, and both `party.yml` documents use Narratio's legacy
list format. Narratio's canonical party model now obtains player identity from
a versioned `party_file`; the obsolete field must be removed and the party
documents migrated before either deployed campaign can pass native
configuration validation.
## Governing Policies
- [The Ansible house style](../../ansible.md) governs the role interface,
direct desired-state tasks, privilege escalation, and downstream role
configuration.
- [The testing house style](../../testing.md) governs focused native outcome
coverage and clean repeated convergence.
- [The MVP roadmap](../mvp.md) assigns campaign and prompt deployment to the
pipeline role, fixes the campaign registry location, and requires the
prompt library to track upstream until it publishes releases.
- [Decision 0001](../../decisions/0001-minimal-module-driven-ansible.md)
requires module-owned convergence without supplemental state or redundant
verification.
## Scope
- Add suite-owned repository URL, revision, and installation-root variables
for campaign and prompt content.
- Default both repositories to their authoritative Gitea origins and the
`main` branch, while allowing a caller to select another branch, tag,
commit, origin, or local Git fixture.
- Check out the campaign repository directly at
`/usr/local/share/narratio/campaigns` by default.
- Check out the prompt repository directly at
`/usr/local/share/narratio/prompt-library` by default.
- Treat both Git checkouts as root-managed, remotely authoritative content
that is updated during ordinary role convergence.
- Pass the selected campaign root to the Narratio role.
- Pass `<prompt-library-root>/prompts` and
`<prompt-library-root>/schemas` to the Scriptorium role as its native prompt
and schema directories.
- Leave Scriptorium's profile directory unset; the prompt repository does not
provide profiles.
- Remove the obsolete `inputs.players_file` declaration from both campaign
definitions while retaining their `party_file` inputs.
- Migrate both legacy party lists to the `narratio.party.v1` document shape,
preserving their supported character, player, class, and level data.
- Correct the two invalid shared-content references and the two invalid schema
paths in the authoritative `narratio-prompts` repository.
- Align pipeline-role defaults, argument specifications, dependency metadata,
README documentation, and focused integration coverage with the expanded
suite contract.
## Non-goals
- Defining Scriptorium execution profiles, model backends, API endpoints, or
credentials.
- Selecting the final D&D prompt/profile combinations used by Narratio stages
and artifacts.
- Defining the broader opinionated Audita, Narratio, Notarius, Seriatim, or
Scriptorium processing policy; that remains a later pipeline feature.
- Enabling Notarius or defining its D&D pipelines.
- Managing human operators or their group membership.
- Delivering secrets or environment files.
- Supporting non-Git asset sources, archive downloads, local overlay trees,
per-campaign selection, or merges of multiple campaign repositories.
- Making managed-host edits coexist with the authoritative repositories.
- Purging untracked files, maintaining asset manifests, recording deployed
commits in sidecar state, or adding independent drift/integrity checks.
- Adding an asset-specific release mechanism before either content repository
publishes releases.
- Running a real LLM request, WhisperX request, or end-to-end transcript.
- Re-testing the standalone roles' installation and configuration matrices.
- Incorporating the pipeline role into `rakestraw.dnd` or publishing a role or
collection release.
## Target End State
Applying `rakestraw.dnd_pipeline` on a supported host installs the application
suite and converges two root-managed Git working trees. The campaign checkout
itself is Narratio's campaign registry, so its top-level campaign directories
are immediately addressable by campaign ID. The prompt-library checkout
contains its native `prompts/` and `schemas/` subdirectories without copied or
rearranged content.
Narratio's managed pipeline configuration uses the same suite-selected
campaign root that the pipeline role populates. Scriptorium's managed
configuration points its `prompt_dir` and `schema_dir` fields to the
corresponding subdirectories of the suite-selected prompt root. Its
`profile_dir` remains omitted unless a caller or later suite-policy feature
provides one.
By default, each convergence fetches and reconciles the `main` branch of both
content repositories. A caller that needs reproducibility can select an
immutable commit through the corresponding revision variable. Ordinary Git
module change detection reports content updates, and an immediate repeat with
unchanged upstream state reports no changes.
The corrected prompt repository is internally consistent with its installed
layout: shared content files named by prompt definitions exist relative to the
definitions, and schema paths resolve relative to Scriptorium's configured
schema root. No compatibility links or installation-time content rewrites are
needed.
## Repository Ownership
- `ansible-role-dnd-pipeline` owns the suite asset variables, Git checkout
tasks, application-role variable wiring, documentation, and integration
coverage. It is the primary implementation repository.
- `assets/narratio-prompts` owns prompt definitions and their internal content
and schema references. It changes only to correct the four discovered stale
references; the pipeline role does not patch content at deployment time.
- `assets/campaigns` owns the campaign registry content and layout. It changes
only to remove the obsolete `players_file` fields and migrate the two party
documents to Narratio's current native schema; the pipeline role does not
rewrite campaign content at deployment time.
- `ansible-role-narratio` and `ansible-role-scriptorium` remain unchanged and
are read-only authorities for their public configuration variables.
- `../narratio` and `../scriptorium` remain read-only authorities for native
content discovery and validation behavior.
- `rakestraw-ansible` is a read-only historical reference. Its older
`/usr/local/etc` asset layout and monolithic deployment tasks are not copied.
- `ansible-workspace-dnd` owns this roadmap, the later staged implementation
plan, the settled MVP decisions, and aggregate status.
- `ansible-collection-dnd` remains unchanged until collection assembly is
selected.
## Constraints and Settled Decisions
- The public additions are:
| Variable | Default | Purpose |
| --- | --- | --- |
| `dnd_pipeline_campaigns_repository_url` | `https://gitea.maximumdirect.net/eric/campaigns.git` | Authoritative campaign Git origin |
| `dnd_pipeline_campaigns_revision` | `main` | Campaign branch, tag, or commit |
| `dnd_pipeline_campaigns_root` | `/usr/local/share/narratio/campaigns` | Campaign checkout and Narratio registry root |
| `dnd_pipeline_prompt_library_repository_url` | `https://gitea.maximumdirect.net/eric/narratio-prompts.git` | Authoritative prompt-library Git origin |
| `dnd_pipeline_prompt_library_revision` | `main` | Prompt-library branch, tag, or commit |
| `dnd_pipeline_prompt_library_root` | `/usr/local/share/narratio/prompt-library` | Prompt-library checkout root |
- Both repositories currently have no release tags. Tracking `main` is the
deliberate suite default; callers can opt into commit pinning without a
separate update switch.
- `ansible.builtin.git` owns checkout creation, fetch/update behavior, tracked
content convergence, and change reporting. The role does not run Git
commands, compare commits, or persist revision state separately.
- `update: true` and `force: true` express that the configured remote revision
owns tracked content. The role does not separately remove untracked files.
- The role performs the privileged content operations with task-level
`become: true`.
- The Narratio dependency creates the campaign root as `root:narratio` mode
`0755`. The pipeline role reuses that root rather than duplicating its
directory task.
- The pipeline role creates the prompt-library root as `root:narratio` mode
`0755` before checkout. Repository files retain their Git modes and remain
operator-readable; no recursive permission normalization is required.
- The pipeline role passes `dnd_pipeline_campaigns_root` as
`narratio_campaigns_root`,
`dnd_pipeline_prompt_library_root ~ '/prompts'` as
`scriptorium_prompt_dir`, and
`dnd_pipeline_prompt_library_root ~ '/schemas'` as
`scriptorium_schema_dir` through ordinary dependency metadata.
- `scriptorium_profile_dir` is not set by this feature. The default profile IDs
named by prompt definitions do not create profile definitions, and selecting
usable suite profiles belongs with the later D&D application-policy work.
- The prompt source corrections use the paths actually present in the
repository: `../common/previous_recap.user.md`,
`analyze/scene_map.schema.json`, and `trim/bounds.schema.json`.
- The campaign source corrections remove `inputs.players_file` from
`centaurs/campaign.yml` and `dilfs/campaign.yml`. The existing
`inputs.party_file` field remains the canonical party source.
- Each party document uses `schema_version: narratio.party.v1` and a
`characters` map. Stable character IDs are the lowercase underscore forms
of their names: `krek`, `rick_oathbreaker`, `tlann`,
`torvass_oathbreaker`, `hrank_greenfield`, `alan_hohey`, `svend_balderk`,
and `popov`.
- Each character retains its player name, display name, class, and level in
the corresponding native nested fields. Legacy `category: pc` is implicit
in membership in the canonical character map. Legacy free-form notes are
retained as adjacent YAML comments because `narratio.party.v1` has no note
field. Popov's evident `pladin` typo is corrected to `paladin` during the
otherwise mechanical migration.
- The now-unused `players.yml` files are not deleted or otherwise repurposed
by this feature.
- The existing dependency-management switch is not expanded. With
`dnd_pipeline_manage_build_dependencies: true`, the composed application
roles install Git before pipeline tasks execute. A caller that disables
dependency management remains responsible for providing Git as well as Go.
- Repository URLs and revisions are data, not secrets. No credentials are
added to role defaults or tests.
## Simplest Viable Implementation
The production change should remain a small extension of the composition
role:
1. Remove the obsolete `players_file` field from both campaign definitions
and migrate both party documents to `narratio.party.v1`.
2. Correct the four stale paths in the prompt source repository.
3. Add and type the six asset variables.
4. Map the campaign root and prompt/schema directories into the existing
Narratio and Scriptorium dependency variables.
5. Declare the prompt-library root with `ansible.builtin.file`.
6. Converge the campaign and prompt repositories with two
`ansible.builtin.git` tasks.
7. Update consumer documentation and extend the existing integration driver
with the asset-specific native outcomes and clean repeat.
No preliminary `stat`, remote revision query, registered-result conditional,
handler, checksum, manifest, or post-checkout permission sweep is required.
The file and Git modules already own the selected desired states.
## Rationale and Alternatives
Checking each repository out directly at its installed root preserves the
upstream layout and makes updates a single module-owned operation. Copying
files from a separate checkout would add a second synchronization boundary,
and installing compatibility links for stale prompt references would encode
source defects into deployment logic. Correcting those paths at their source
is smaller and makes the asset repository useful outside this role as well.
The dedicated `/usr/local/share/narratio/prompt-library` root makes the
relationship clear without producing a confusing `prompts/prompts` path.
Its `prompts/` and `schemas/` children map directly to Scriptorium's native
configuration fields. `/usr/local/share` is appropriate for host-wide,
root-managed, architecture-independent application data and is consistent
with the already selected campaign location.
One suite root variable per content repository keeps the Git destination and
application configuration coupled. Hard-coding each path independently would
permit accidental divergence, while exposing separate checkout and installed
paths would add flexibility for which no consumer requirement exists.
Tracking `main` matches the prompt-library policy already selected for the MVP
and is also the practical campaign default while that repository has no
releases. A single revision variable still permits immutable deployments.
Adding an update boolean would create overlapping modes without improving that
choice: selecting a commit already fixes content, and selecting a branch
expresses the intent to follow it.
## Acceptance Criteria
### Required Asset Behavior
- Applying the pipeline role checks out the configured campaign repository at
`dnd_pipeline_campaigns_root` and the configured prompt repository at
`dnd_pipeline_prompt_library_root`.
- The default origins, revisions, and roots match the fixed public interface.
- A caller can replace either origin, revision, or root through its suite
variable without editing role tasks or dependency metadata.
- Narratio's managed configuration names the exact campaign root populated by
the pipeline role.
- Scriptorium's managed configuration names the deployed `prompts/` and
`schemas/` directories and does not acquire a profile directory from this
feature.
- Both deployed campaign definitions and their versioned party documents
conform to Narratio 2.0's canonical party-input contract and pass native
validation by campaign ID.
- The two prompt definitions that use previous-recap content load the existing
`previous_recap.user.md` file, and both JSON-schema definitions resolve
paths beneath the configured schema directory.
- The managed content roots are root-owned and operator-readable. Runtime and
operator accounts do not receive write access through this feature.
- Upstream changes to a selected branch are applied by a later role run;
selecting an immutable commit produces stable content.
- An immediate repeated role application with unchanged inputs and upstream
state reports no changes.
- The role contains no content copies, deployment-time prompt rewrites,
redundant state probes, revision sidecars, checksums, or production
self-validation.
- Only `ansible-role-dnd-pipeline`, `assets/campaigns`,
`assets/narratio-prompts`, and workspace planning/status documentation
change.
### Required Validation
- YAML syntax checking and production-profile ansible-lint pass for the role
and its test playbooks.
- The integration driver uses explicit repository URL and revision inputs for
controlled local Git fixtures rather than depending on mutable network
state.
- Narratio natively validates its managed pipeline configuration with a
campaign selected by ID from the deployed registry.
- Scriptorium natively inspects a deployed prompt through its managed
configuration, including a representative definition that uses the repaired
shared-content path.
- A representative JSON-schema prompt has a schema path that resolves beneath
the configured deployed schema directory.
- The asset-enabled baseline is followed immediately by a convergence that
reports no changes.
- Existing suite version-forwarding coverage remains intact; the feature does
not repeat standalone application installation matrices.
- Tests do not assert current default revisions as immutable facts, enumerate
every asset as a snapshot, inspect Git internals, trace task execution, or
re-test `ansible.builtin.file` and `ansible.builtin.git` behavior.
## Dependencies and Follow-up Work
Feature 0006 and all five standalone roles are complete. The managed host must
be able to reach the selected content repositories unless callers provide
local origins. The narrow campaign and prompt source corrections must be
committed before an integration test pins or checks out their resulting
revisions.
The next suite-policy feature should select actual Scriptorium profiles and
backends together with Narratio prompt IDs, artifacts, and other opinionated
D&D application settings. Operator access, secret delivery, end-to-end
processing validation, and collection assembly also remain separate work.
Before a suite or collection release, both asset repositories need an explicit
release policy. If they begin publishing immutable releases, the suite should
replace its branch defaults with compatible released revisions.
Feature 0007 was completed by campaign commit `d1193e8`, prompt-library commit
`c7e1845`, pipeline-role commits `a6ce224` and `cbfd601`, and final test-quality
remediation commit `7572fa3`. The complete integration suite and post-remediation
review passed with no remaining findings.
## Potential Future Hardening
- Verify signed asset releases when the repositories publish them.
- Protect managed checkouts against hostile repository ownership changes.
- Provide a controlled offline mirror or packaged asset artifact.

View File

@@ -0,0 +1,475 @@
# Feature 0008: Opinionated D&D Processing Configuration
Status: done
## 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](../../ansible.md) governs the suite-owned public
interface, templates, direct desired-state tasks, and omission of
unselected application defaults.
- [The testing house style](../../testing.md) governs native behavioral
validation, explicit testing inputs, and clean repeated convergence.
- [The MVP roadmap](../mvp.md) assigns opinionated cross-application and D&D
policy to the pipeline role while keeping standalone application roles
generic.
- [Decision 0001](../../decisions/0001-minimal-module-driven-ansible.md)
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:
```text
/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 0010 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 after Feature 0009 establishes shared filesystem and
execution policy. Later features should address storage/publishing and secret
delivery together, optional operator selection and membership management,
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.

View File

@@ -0,0 +1,266 @@
# Feature 0009: Shared Pipeline Filesystem and Execution
Status: done
## Summary
Establish one coherent filesystem and invocation policy for the D&D suite.
Standalone application roles will expose sensible generic configuration
ownership and mode controls, while the pipeline role will use those controls
to make configuration service-owned and world-readable and to make writable
state safely shareable by the service account and existing human members of
its group.
## Problem or Opportunity
The current standalone roles hard-code their configuration ownership and
modes. Those defaults are reasonable in isolation, but the pipeline cannot
select its intended `narratio:narratio` ownership without adding a second
convergence pass that would fight the dependency roles and report changes on
every run.
Narratio's writable roots already use setgid mode `2775`, but directory mode
alone does not preserve group write access when different invocation identities
have different umasks. Notarius v0.7.0 has removed its application-enforced
private cache modes, so deployment provisioning can now establish a consistent
shared policy before Notarius integration begins.
## Governing Policies
- [The Ansible house style](../../ansible.md) governs the generic role
interfaces, direct module-driven convergence, and suite overrides.
- [The testing house style](../../testing.md) governs behavioral access tests
and clean repeated convergence.
- [The MVP roadmap](../mvp.md) assigns operator access and cross-application
policy to the pipeline role while keeping standalone roles independently
useful.
- [Decision 0001](../../decisions/0001-minimal-module-driven-ansible.md)
requires direct idempotent modules without preliminary state inspection.
- [Decision 0002](../../decisions/0002-shared-readable-pipeline-filesystem-policy.md)
defines the service ownership, shared writable state, world-readable content,
and restricted credential boundary implemented by this feature.
## Scope
- Add configuration owner, group, directory-mode, and file-mode variables to
the Audita, Notarius, Narratio, and Scriptorium roles.
- Preserve standalone defaults appropriate to each application rather than
embedding D&D suite policy in those roles.
- Add suite-level runtime identity and configuration-mode variables to the
pipeline role and pass them explicitly to all four configuration-bearing
dependencies.
- Run the Narratio dependency before the other application dependencies so it
creates the selected service account and group before they write
service-owned configuration.
- Converge suite application configuration as `narratio:narratio`, with
directory mode `0755` and file mode `0644` by default.
- Keep `/var/lib/narratio`, `/var/spool/narratio`, and
`/var/cache/narratio` as `narratio:narratio` mode `2775` shared writable
roots.
- Install the Ubuntu `acl` package, declare a pinned `ansible.posix`
collection dependency, and manage access and default ACL entries that retain
owner/group write and world read/traverse access beneath shared roots.
- Support invocation as either the service account or an existing human
member of the selected runtime group.
- Document the standalone defaults, pipeline overrides, expected group
membership, world-readable non-secret boundary, and reserved restricted
`secrets/` policy.
- Add focused integration coverage for public configuration-mode overrides,
cross-identity access, and immediate clean repeated convergence.
## Non-goals
- Upgrading Notarius, adding its ConfigKit import interface, deploying its
D&D pipeline, creating `/var/cache/notarius`, or enabling Narratio's
extraction stage; those belong to Feature 0010.
- Changing any application's native configuration fields or runtime behavior.
- Selecting human operators or changing their group membership.
- Creating or populating a `secrets/` directory, delivering credentials, or
defining secret injection.
- Making application configuration group-writable or supporting manual edits
to Ansible-managed configuration.
- Changing ownership of root-managed source checkouts, installed binaries,
campaign assets, or prompt assets.
- Recursively migrating pre-existing runtime content with incompatible modes
or ACLs.
- Running transcript processing, calling external services, or adding
scheduling and service management.
## Target End State
Each standalone role exposes the same four concepts using its application
prefix. Its defaults remain appropriate for an independent installation:
| Role | Configuration owner | Configuration group | Directory mode | File mode |
| --- | --- | --- | --- | --- |
| Audita | `root` | `root` | `0755` | `0644` |
| Notarius | `root` | `root` | `0755` | `0644` |
| Scriptorium | `root` | `root` | `0755` | `0644` |
| Narratio | `root` | `narratio` | `0750` | `0640` |
For example, the Notarius variables are
`notarius_config_owner`, `notarius_config_group`,
`notarius_config_directory_mode`, and `notarius_config_file_mode`; the other
roles use their corresponding prefixes. Each role uses these variables in the
ordinary directory and template tasks that already own its configuration. No
role adds a follow-up permission-repair task or preliminary inspection.
The pipeline role defines `dnd_pipeline_runtime_user` and
`dnd_pipeline_runtime_group`, both defaulting to `narratio`, plus
`dnd_pipeline_config_directory_mode: "0755"` and
`dnd_pipeline_config_file_mode: "0644"`. It passes those values as the four
roles' configuration owner, group, and mode inputs. Narratio executes first in
dependency order and creates the selected identity before another dependency
references it.
The resulting application configuration beneath
`/usr/local/etc/{audita,notarius,narratio,scriptorium}` is owned by
`narratio:narratio` and is world-readable. It remains under Ansible control;
neither the service account nor human operators are expected to edit managed
files in place.
The three existing Narratio writable roots are `narratio:narratio` mode
`2775`. Their access and default ACLs are equivalent to `u::rwx`, `g::rwx`,
`o::r-x`, and `m::rwx`. Inherited permissions remain subject to the mode
requested for each new file type, so ordinary files are non-executable while
remaining group-writable and world-readable. A later feature applies the same
policy when it introduces another shared root such as
`/var/cache/notarius`.
A human account already belonging to `narratio` can use the same configuration
and writable roots as the service account. This feature does not choose that
account. Credential files are absent; the reserved future
`/usr/local/etc/narratio/secrets` subtree uses the distinct `0750` directory
and `0640` file policy when a credential-delivery feature creates it.
## Repository Ownership
- `ansible-role-audita`, `ansible-role-notarius`, and
`ansible-role-scriptorium` own their generic configuration ownership and
mode variables, standalone defaults, documentation, and focused integration
coverage.
- `ansible-role-narratio` owns the equivalent generic controls while retaining
its existing standalone relationship to the service group it creates.
- `ansible-role-dnd-pipeline` owns dependency ordering, the suite runtime
identity and configuration-mode defaults, explicit dependency overrides,
the `acl` package and `ansible.posix` dependency, shared-root ACL
convergence, consumer documentation, and cross-identity integration
coverage.
- `ansible-workspace-dnd` owns this roadmap, Decision 0002, the later staged
implementation plan, and aggregate status.
- The five application source repositories are unchanged; their runtime
contracts are not needed to implement configuration-file ownership.
## Constraints and Settled Decisions
- Standalone application roles remain independently usable. Their defaults do
not assume that a `narratio` account exists unless the role itself creates
it.
- The pipeline role selects suite policy by passing public role variables; it
does not reapply ownership after dependencies have completed.
- Configuration owner and group variables are strings, while mode variables
use the quoted four-digit strings expected by Ansible file-management
modules.
- The pipeline's selected runtime user and group are the configuration owner
and group. Supporting different configuration and runtime identities would
require a concrete later use case.
- Application configuration is world-readable but not group-writable. Shared
writable roots and their ordinary content are group-writable and
world-readable.
- The role uses `ansible.builtin.apt` for the `acl` package and
`ansible.posix.acl` for access/default ACL state. The collection dependency
is pinned in the pipeline role's manifest and installed by its integration
driver.
- ACL management covers only the three existing writable roots and their
inheritance policy. It does not recursively rewrite existing descendants.
- A `secrets/` subtree is a documented future boundary, not state created by
this feature.
- Tests exercise the public operating contract and one representative
cross-identity workflow. They do not enumerate every path or restate every
module argument.
## Simplest Viable Implementation
1. Add four defaults, four argument-specification entries, and direct task
substitutions to each configuration-bearing standalone role; update its
README and focused integration inputs without adding new task flow.
2. Reorder the pipeline dependencies so Narratio creates the service identity
first, add four suite policy variables, and pass them directly to each
configuration-bearing role.
3. Add the pinned `ansible.posix` requirement, install `acl`, and apply the
selected access/default ACL entries to the three existing writable roots
with ordinary state-management modules.
4. Update pipeline consumer documentation and extend its integration driver
with one representative human group member, native configuration
inspection, shared-write behavior, and a clean repeat.
No task gathers preliminary filesystem or account state. Existing `file`,
`template`, `apt`, and `acl` modules own convergence and change reporting.
## Rationale and Alternatives
Public ownership and mode variables let each standalone role express its own
sensible installation while allowing a composing role to select different
policy through normal Ansible precedence. A corrective pipeline task would
fight the dependency templates and make every otherwise unchanged run report
changes.
Setgid alone preserves group identity but does not guarantee group-write bits
for files created under an arbitrary human user's umask. A managed default ACL
expresses the required inherited state directly. A wrapper command that sets a
umask would add another invocation path and would not protect direct use of the
installed applications.
Mode `2775`, rather than `2770`, is deliberate: D&D transcript content is not
treated as secret in this deployment. Only API keys and similar credentials
belong in the separately restricted future subtree.
## Acceptance Criteria
- Each configuration-bearing standalone role exposes and documents owner,
group, directory-mode, and file-mode variables with the standalone defaults
listed above.
- Each role applies those inputs through the tasks that already create its
configuration directory and file, without a second convergence pass.
- The pipeline role runs Narratio first and explicitly selects
`narratio:narratio`, `0755` directories, and `0644` files for all application
configuration.
- The deployed configuration for Audita, Notarius, Narratio, and Scriptorium
is owned by `narratio:narratio`, is readable by other local users, and
contains no credential values.
- The three existing Narratio writable roots are `narratio:narratio` mode
`2775` and have access/default ACLs that preserve group write and world
read/traverse access for new content.
- The pipeline role declares a pinned `ansible.posix` dependency and installs
the required Ubuntu `acl` package.
- The service account and a representative existing human member of the
`narratio` group can use the same configuration and exchange ordinary
writable-state content.
- The role does not create users other than the established service account,
alter human group membership, create a secrets directory, or migrate
existing descendants recursively.
- Syntax checking and production-profile lint pass in every changed role.
- Focused standalone-role integration checks and the complete pipeline
integration entry point pass.
- An immediate repeated application in every changed role reports no changes.
- Tests observe the shared operating contract without snapshotting defaults,
enumerating implementation steps, or testing trusted module behavior.
## Dependencies and Follow-up Work
Features 0001 through 0008 and the standalone-role test-suite simplification
are complete. Notarius v0.7.0's deployment-owned cache permissions remove the
application blocker that previously prevented this policy, but Feature 0009
does not otherwise depend on or modify the Notarius application.
Feature 0010 applies this policy to `/var/cache/notarius` while adding the D&D
extraction integration. Later work may add optional operator-selection and
group-membership variables or deliver credentials beneath the restricted
`secrets/` subtree.
## Potential Future Hardening
- Offer a non-world-readable deployment profile if a concrete environment
later treats campaign material as confidential.
- Select a recursive migration policy if supported upgrades must normalize
pre-existing descendants rather than only managed roots and new content.

View File

@@ -0,0 +1,544 @@
# Feature 0010: D&D Notarius Extraction Integration
Status: ready
## Summary
Enable Narratio's Notarius stage with the maintained ten-lane D&D extraction
pipeline. The pipeline role will supply the opinionated Notarius pipeline,
bind campaign-owned inputs through Narratio's invocation boundary, and declare
the exact lane contracts Narratio may accept as extraction sources. It uses
the service ownership and shared-access foundation established by Feature
0009.
## Problem or Opportunity
Features 0006 through 0008 install and configure the five applications,
deploy the D&D content, and define the transcript-processing and Scriptorium
workflow. Narratio still leaves its Notarius stage disabled, and Notarius's
managed configuration contains no pipeline. A run can therefore produce a
cleaned and trimmed transcript but cannot yet extract the structured D&D
registries and events implemented by Notarius.
The uploaded test-machine configuration demonstrates the intended multi-step
pipeline, but it embeds campaign-specific filesystem paths and explicit
runtime roots. The current Notarius v0.7.0 complete example and Narratio 2.0
integration boundary provide the maintained replacement. Narratio 2.0 names
Notarius v0.6.0 as its subprocess baseline, while Notarius v0.7.0 expressly
preserves that subprocess receipt and extraction-artifact contract. The
Notarius upgrade therefore changes deployment configuration without requiring
a Narratio adapter change. Narratio must prepare invocation-local campaign
references and own the run-specific output staging directory; generated
registry and event handoffs remain internal to Notarius. Notarius v0.7.0 also
replaces configuration version 4 with a strict, ConfigKit-backed version 5
contract and makes cache access policy a deployment responsibility.
## Governing Policies
- [The Ansible house style](../../ansible.md) governs the suite-owned public
interface, direct desired-state configuration, and reliance on the
standalone roles' native templates.
- [The testing house style](../../testing.md) governs focused native contract
validation and immediate clean repeated convergence.
- [The MVP roadmap](../mvp.md) assigns opinionated D&D policy and
cross-application coordination to the pipeline role while keeping the
standalone application roles generic.
- [Decision 0001](../../decisions/0001-minimal-module-driven-ansible.md)
requires module-owned convergence without redundant inspection or
supplemental state.
- [Decision 0002](../../decisions/0002-shared-readable-pipeline-filesystem-policy.md)
defines the service ownership, shared operator access, world-readable
content, and restricted credential boundary.
- [Feature 0008](0008-opinionated-dnd-processing-configuration.md) establishes
the trimmed transcript, ConfigKit layout, and `testing` overlay into which
this feature integrates.
- [Feature 0009](0009-shared-pipeline-filesystem-and-execution.md) establishes
the runtime identity, configuration ownership interfaces, and inherited
shared-access policy extended by this feature.
## Scope
- Update the standalone Notarius role for Notarius v0.7.0 and configuration
version 5 while preserving its generic, independently usable interface.
- Advance the pipeline role's selected Notarius application version to v0.7.0
and pin its Notarius role dependency to the reviewed revision that provides
the version 5 interface.
- Expose Notarius's native `configkit.imports` field through one optional
`notarius_configkit_imports` role variable; the role continues to own only
its root configuration and does not manage caller-selected fragments.
- Supply one complete `dnd-session` Notarius pipeline as deliberate D&D suite
policy in a suite-managed imported fragment at
`/usr/local/etc/notarius/pipelines/dnd-session.yml`.
- Adapt the maintained Notarius v0.7.0 complete D&D pipeline using canonical
version 5 module-binding objects, including:
- the embedded `dnd-extraction` PromptKit workload profile;
- Seriatim input and scene-based chunking;
- the ordered `describe-session`, `extract-events`, and `track-enemies`
steps;
- all ten maintained D&D artifact lanes and their generated handoffs; and
- JSON output with the chunk map and selected evidence context.
- Remove every campaign-specific filesystem reference from the Notarius
pipeline definition.
- Enable Narratio's Notarius stage and select `dnd-session`.
- Bind `party`, `players`, and `glossary` to Narratio's prepared campaign
sources at invocation time.
- Define Narratio acceptance descriptors for all ten maintained lane outputs.
- Make the pipeline map, Narratio reference map, and Narratio output map
ordinary suite variables so callers can compose or replace native mappings
through inventory precedence.
- Make the selected pipeline ID an ordinary suite variable and keep it
coordinated with the default pipeline map.
- Enable Notarius caching to the maximum currently available extent: use
`auto` chunk-plan caching and enable checkpoint recording. Narratio does not
yet request checkpoint reuse with Notarius's `--resume` flag.
- Provision `/var/cache/notarius` as a shared FHS cache root owned by
`narratio:narratio` with mode `2775`, and configure Notarius to create its
chunk-plan and checkpoint stores beneath that root.
- Apply Feature 0009's established access and default ACL policy to the new
cache root so content created by either supported invocation identity remains
group-writable and world-readable.
- Keep Notarius enabled under the existing `testing` overlay. Testing and
production select the same Notarius pipeline and workload profile until the
suite chooses a distinct testing profile strategy.
- Document the reference boundary, lane-to-source mapping, runtime-state
policy, production/testing behavior, and supported caller customization.
- Extend focused integration coverage for native Notarius validation,
Narratio base/testing resolution, representative reference and output
wiring, and immediate clean repeated convergence.
## Non-goals
- Changing any application's native configuration fields or duplicating a
standalone role's root configuration template in the pipeline role.
- Making the standalone Notarius role manage imported fragments; fragment
deployment remains the responsibility of the caller that selects an
import.
- Copying the uploaded test-machine configuration verbatim.
- Installing a filesystem PromptKit profile for Notarius. Notarius v0.7.0
already embeds the selected production `dnd-extraction` fallback profile.
- Defining a second Notarius pipeline solely to select an inexpensive testing
model, or otherwise adding profile inheritance that Notarius does not
natively provide.
- Binding a spell catalog before the campaign registry declares one.
- Publishing, rendering, or otherwise consuming the new extraction sources in
Scriptorium artifacts.
- Selecting a default campaign.
- Delivering API keys, provider credentials, environment files, or a general
secret-management mechanism.
- Running Notarius extraction, making model calls, or processing a complete
transcript during integration tests.
- Managing output retention, cache cleanup, or debug retention.
- Adding checkpoint-resume control to Narratio or changing Narratio's
subprocess invocation to pass `--resume` or `--config-profile`.
- Installing a systemd service, timer, scheduler, or other unattended
invocation mechanism.
- Selecting human operator accounts or changing their membership in the
`narratio` group.
- Revising the general configuration ownership, dependency ordering, ACL
dependency, or existing shared roots established by Feature 0009.
- Delivering or populating the future restricted `secrets/` directory.
- Modifying upstream application source, embedded Notarius prompts, schemas,
modules, codecs, or validators.
- Collection assembly, role releases, storage/publishing, upgrade/removal
behavior, or end-to-end production validation.
## Target End State
The standalone Notarius role continues to own the version 5 root document at
`/usr/local/etc/notarius/config.yml`. Its public interface exposes the native
`configkit.imports` list, and the pipeline role selects the explicit relative
import `pipelines/dnd-session.yml`. The pipeline role owns that fragment and
renders the complete `dnd_pipeline_notarius_pipelines` map into it, producing
one native `dnd-session` definition by default. The definition follows the
Notarius v0.7.0 maintained complete D&D topology:
```text
Seriatim transcript
-> dnd/scenes chunking
-> describe-session
item-registry
npc-registry
location-registry
scene-descriptions
-> extract-events
item-occurrences
spells
combat-turns
npc-occurrences
location-occurrences
-> track-enemies
enemy-events
-> JSON bundle, chunk map, and evidence context
```
Feature 0009 already makes application configuration service-owned and
world-readable. The Notarius root document and new suite fragment retain that
`narratio:narratio`, `0755` directory, and `0644` file policy through the
standalone role's established ownership and mode interface.
The `extract-events` step consumes the four generated outputs from
`describe-session` under their declared internal reference slots. The
`track-enemies` step consumes the generated NPC registry and scene
descriptions from `describe-session` and the generated combat turns and NPC
occurrences from `extract-events`. Those handoffs are part of the Notarius
pipeline and never appear in Narratio's CLI reference map.
Narratio's effective base configuration enables Notarius, selects the managed
configuration and `dnd-session`, and supplies three campaign-owned references:
| Notarius selector | Prepared Narratio source |
| --- | --- |
| `party` | `narratio.input.party` |
| `players` | `narratio.input.players` |
| `glossary` | `narratio.input.glossary` |
Narratio snapshots those inputs for each invocation and passes their absolute
paths with `--reference`. No campaign path appears in Notarius configuration.
The optional `spell_catalog` binding is absent because neither deployed
campaign currently declares `inputs.spell_catalog_file`. A caller that adds
that campaign input can extend the suite reference map with
`spell_catalog: narratio.input.spell_catalog` without changing either
application role.
Narratio accepts all ten configured lanes using these exact v1 contracts and
registers each accepted payload as `narratio.extraction.<output-key>`:
| Narratio output key | Lane ID | Schema ID | Module key |
| --- | --- | --- | --- |
| `item_registry` | `item-registry` | `notarius.dnd.item_registry` | `dnd/item-registry` |
| `npc_registry` | `npc-registry` | `notarius.dnd.npc_registry` | `dnd/npc-registry` |
| `location_registry` | `location-registry` | `notarius.dnd.location_registry` | `dnd/location-registry` |
| `scene_descriptions` | `scene-descriptions` | `notarius.dnd.scene_descriptions` | `dnd/scene-descriptions` |
| `item_occurrences` | `item-occurrences` | `notarius.dnd.item_occurrences` | `dnd/item-occurrences` |
| `spells` | `spells` | `notarius.dnd.spells` | `dnd/spells` |
| `combat_turns` | `combat-turns` | `notarius.dnd.combat_turns` | `dnd/combat-turns` |
| `npc_occurrences` | `npc-occurrences` | `notarius.dnd.npc_occurrences` | `dnd/npc-occurrences` |
| `location_occurrences` | `location-occurrences` | `notarius.dnd.location_occurrences` | `dnd/location-occurrences` |
| `enemy_events` | `enemy-events` | `notarius.dnd.enemy_events` | `dnd/enemy-events` |
Every entry requires `media_type: application/json` and
`schema_version: v1`. Narratio validates the received descriptor before
registering the source; it does not infer contracts from filenames.
Narratio supplies its run-specific staging root through Notarius's
`--output-dir` override, so the suite does not set Notarius's global
`output.directory`. Reconstructible Notarius state uses the FHS cache layout:
```text
/var/cache/notarius/
├── chunk-plans/
└── checkpoints/
```
The pipeline role creates the root as `narratio:narratio` mode `2775`, sets
chunk-plan mode to `auto`, enables checkpoint recording, and configures both
child paths. Notarius creates cache entries with conventional maximum creation
modes and leaves their effective modes to deployment provisioning, process
umask, setgid inheritance, and default ACLs. The suite applies a default ACL
that retains owner and group write access and world read/traverse access for
new cache content. Narratio and its Notarius subprocess may run as the
dedicated `narratio` account or as a human member of the `narratio` group.
Chunk plans are reused automatically; checkpoints are recorded but are not
reused because Narratio does not pass `--resume`. The debug root remains
unset. The selected Notarius process working directory is
`/usr/local/etc/notarius`, matching the managed configuration location; no
relative profile or reference paths depend on it.
The cache root receives the same setgid and default-ACL policy that Feature
0009 applies to Narratio's existing shared roots. Non-secret content created
beneath it remains writable by the shared group and readable by other local
users. The suite does not create or populate a `secrets/` directory.
The base Narratio configuration and the `testing` ConfigKit overlay both run
the extraction stage using Notarius's embedded `dnd-extraction` profile. The
testing overlay continues to override only the Scriptorium profile selections;
it does not disable or restate Notarius. A later feature may select a distinct
inexpensive Notarius testing profile without changing the pipeline topology.
## Repository Ownership
- `ansible-role-dnd-pipeline` owns the D&D pipeline map and imported fragment,
Narratio integration mappings, Notarius dependency-variable wiring, the new
cache root and its inherited shared-access policy, testing-overlay choice,
consumer documentation, and suite integration coverage.
- `ansible-role-notarius` owns the generic Notarius v0.7.0 installation,
version 5 root configuration, optional ConfigKit import interface, focused
role documentation, and role-local integration coverage. It does not own or
render the suite's imported D&D fragment.
- `ansible-role-audita`, `ansible-role-narratio`, and
`ansible-role-scriptorium` remain unchanged. The Narratio role owns its generic
Notarius adapter fields and ConfigKit-aware root configuration.
- `../notarius` is the read-only authority for configuration version 5, the
maintained D&D pipeline, embedded profile, module handoffs, and lane
contracts.
- `../narratio` is the read-only authority for prepared campaign sources,
subprocess invocation, output acceptance, and profile overlay behavior.
- `assets/configs/notarius/config.yml` is an operational reference only. Its
useful topology is adapted, while its campaign paths and runtime roots are
not copied.
- `assets/campaigns` remains unchanged and continues to own the campaign
registry inputs that Narratio prepares.
- `ansible-workspace-dnd` owns this roadmap, the later implementation plan,
settled MVP decisions, and aggregate status.
## Constraints and Settled Decisions
- This feature advances the standalone role default and pipeline application
selection from Notarius v0.6.0 to v0.7.0. Narratio remains at v2.0.0.
- Narratio v2.0.0 documents Notarius v0.6.0 as its invocation baseline, but
Notarius v0.7.0 preserves the subprocess receipt and extraction-artifact
contracts. Version 5 configuration migration is confined to the Notarius
role and the suite-owned Notarius fragment.
- The pipeline dependency manifest must pin the reviewed standalone Notarius
role revision that implements this v0.7.0/configuration-version-5 contract.
- Feature 0009 has already established the runtime identity, dependency order,
standalone ownership interfaces, configuration modes, `acl` package, and
pinned `ansible.posix` dependency used here.
- The pipeline role relies on the standalone roles for application
installation and both root configuration documents. It manages only the
suite-owned Notarius and Narratio fragments selected through those public
interfaces.
- The standalone Notarius role defaults to configuration version 5 and exposes
`notarius_configkit_imports` as the complete native import list. A null value
omits the `configkit` section and leaves composition with Notarius.
- The pipeline role passes the fixed import
`pipelines/dnd-session.yml` to the standalone role and manages that imported
file as suite-owned configuration. It does not pass the pipeline map into
the standalone role's root-level `notarius_pipelines` field.
- `/var/cache/notarius` uses the Feature 0009 runtime identity, mode `2775`,
and access/default ACL entries equivalent to `u::rwx`, `g::rwx`, `o::r-x`,
and `m::rwx`.
- `dnd_pipeline_notarius_pipelines` is a complete native map whose default
contains `dnd-session`. Callers may replace it or compose additional
pipeline definitions with Jinja's `combine` filter in inventory.
- `dnd_pipeline_narratio_notarius_pipeline_id` defaults to `dnd-session`.
Callers that replace that key are responsible for selecting a matching ID.
- `dnd_pipeline_narratio_notarius_references` is the complete native Narratio
reference map. It defaults to `party`, `players`, and `glossary`; its values
are prepared source IDs, never filesystem paths.
- `dnd_pipeline_narratio_notarius_outputs` is the complete native Narratio
output map. It defaults to all ten lanes because the suite claims to consume
the complete maintained D&D extraction workflow.
- `dnd_pipeline_notarius_cache_root` defaults to `/var/cache/notarius`,
`dnd_pipeline_notarius_cache_chunk_plans_mode` defaults to `auto`, and
`dnd_pipeline_notarius_cache_checkpoints_enabled` defaults to `true`. They
are intentional, inventory-overridable suite policy. The two application
cache directories derive from that root rather than becoming independent
suite variables.
- The pipeline defaults to `llm_profile: dnd-extraction` and relies on
Notarius's embedded fallback. It does not set `promptkit.profile_file`,
`promptkit.profile_dir`, a local backend, or credentials.
- The pipeline uses the version 5 `input: {module: seriatim}` binding,
`dnd/scenes` chunking with two retries, and the three ordered steps documented
above. Extract, merge, and normalize bindings use canonical objects with
`module:`; retries and generated reference handoffs match the maintained
Notarius complete example.
- JSON output enables `include_chunk_map` and evidence context with a
three-unit window. Evidence context includes item occurrences, item
registry, location registry, location occurrences, NPC registry, spells,
combat turns, NPC occurrences, and enemy events, matching the maintained
example.
- Notarius pipeline YAML contains no external file references. Narratio owns
all campaign input materialization for the orchestrated path.
- Narratio's Notarius binary and configuration paths remain the established
`/usr/local/bin/notarius` and `/usr/local/etc/notarius/config.yml`.
- The suite uses the runtime user and group selected by Feature 0009 for the
Notarius cache and configuration fragment.
- Narratio's Notarius working directory is explicitly
`/usr/local/etc/notarius`; the timeout inherits Narratio's native three-hour
default because the suite has selected no different policy.
- Narratio owns per-run Notarius output staging. The suite provisions
`/var/cache/notarius` for the shared `narratio` identity, and Notarius owns
its child cache stores. The role does not create `/var/lib/notarius`, set a
global output root, or provision a debug root.
- Checkpoint enablement records reusable state but does not cause Narratio to
reuse it. Resume remains an explicit Notarius invocation action and requires
a later Narratio integration decision.
- The production configuration enables Notarius. The existing `testing`
overlay inherits that enabled stage and the same `dnd-extraction` profile;
it does not override Notarius merely to avoid model calls.
- All maps use native application shapes and remain replaceable through normal
inventory precedence. The suite does not create field-by-field aliases for
every nested lane or module option.
- Directory and ACL tasks declare only the shared roots required by the
applications, using ordinary state-management modules with task-level
privilege escalation. No `stat`, command, handler, checksum, manifest, or
production validation task accompanies them.
## Simplest Viable Implementation
The production changes remain direct configuration management:
1. Update the standalone Notarius role's version and configuration-version
defaults and add the nullable native ConfigKit import field to defaults,
argument specification, root template, and documentation. Cover that public
behavior with focused native validation and a clean repeat.
2. Advance the pipeline's Notarius application selection and standalone-role
dependency pin, then add the selected Notarius pipeline map, shared FHS
cache policy, and three suite-level Narratio integration mappings to
pipeline-role defaults and the argument specification.
3. Pass the fixed import and cache choices to `rakestraw.notarius`, and pass
Notarius enablement, selected ID, working directory, references, and outputs
to `rakestraw.narratio`.
4. Create the Notarius pipeline-fragment directory and cache root with ordinary
`ansible.builtin.file` tasks, render the suite-owned pipeline map into one
imported fragment, and extend Feature 0009's access/default ACL task to the
new root.
5. Update both role READMEs and extend focused integration coverage with native
configuration validation, effective-configuration inspection, inspection
as a supported group member, and clean repeats.
The standalone roles' template operations continue to own both root
configuration files. The pipeline role adds one Notarius pipeline-fragment
template but does not duplicate the root document or change the existing
Narratio testing-overlay template for this feature.
## Rationale and Alternatives
Using Notarius's maintained complete example preserves the upstream module
topology and contract while keeping suite policy explicit. Maintaining a
smaller custom pipeline would make the role responsible for deciding which
D&D artifacts no longer matter. Copying the uploaded file would instead
preserve obsolete host paths and bypass Narratio's verified reference
boundary.
Rendering one native map into a ConfigKit-imported fragment keeps configuration
ownership clear and preserves the inventory-composition workflow already
selected for Notarius. It also follows Notarius v0.7.0's maintained composition
shape without making the generic role own D&D content. Field-specific variables
for every lane, step, and retry would create a large parallel schema with little
consumer value. One complete map is easier to replace, combine, validate, and
compare with Notarius documentation.
`/var/cache/notarius` follows the filesystem hierarchy's intended location for
reconstructible application state and is preferable to the uploaded
`/var/lib/notarius/cache` layout. Assigning the root to the dedicated
`narratio` account and group gives unattended and human-initiated runs one
reusable cache. Mode `2775` preserves the shared group, and the default ACL
prevents an invoking account's umask from accidentally removing group write or
world read access from new content. Notarius v0.7.0 respects this deployment
policy rather than replacing it with application-owned private modes.
Narratio's staging root remains separate because output bundles are run
results, not cache data.
The `testing` overlay cannot natively replace a nested Notarius pipeline's
`llm_profile`; that configuration lives in a separate application file.
Duplicating the full pipeline or managing a second Notarius root configuration
would add substantial configuration drift for one model choice. Testing
therefore inherits production extraction for now; a distinct testing strategy
can be selected later if it becomes a concrete need.
## Acceptance Criteria
### Required Configuration Behavior
- The pipeline role installs a Notarius configuration that natively validates
the `dnd-session` pipeline without provider credentials or a model call.
- The pipeline role selects Notarius v0.7.0 and its dependency manifest pins
the reviewed standalone-role revision that supplies the version 5 interface.
- The standalone Notarius role supports an explicitly selected v0.7.0,
emits configuration version 5 with its compatible defaults, and can render
a caller-supplied native ConfigKit import list.
- The root Notarius configuration imports the suite-owned
`pipelines/dnd-session.yml` fragment, and that fragment contains the complete
pipeline map selected through inventory.
- The pipeline contains the maintained Seriatim input, D&D scene chunker,
three ordered steps, ten lanes, generated handoffs, JSON chunk map, and
selected evidence-context policy.
- The Notarius configuration contains no campaign-specific reference paths,
PromptKit operator-profile path, fixed output root, or debug root.
- The Notarius configuration selects `auto` chunk-plan caching, enables
checkpoints, and uses `/var/cache/notarius/chunk-plans` and
`/var/cache/notarius/checkpoints` respectively.
- The deployed cache root is `narratio:narratio` mode `2775`; its access and
default ACLs preserve group write and world read/traverse access without
depending on Notarius to enforce entry modes. Checkpoints are recorded; the
roadmap does not claim Narratio reuses them.
- The Notarius root configuration and suite-owned imported fragment retain
Feature 0009's `narratio:narratio`, `0755` directory, and `0644` file policy.
No secret value appears in either file.
- Narratio's effective base configuration enables Notarius, selects
`dnd-session`, and uses the installed binary, configuration, and working
directory.
- Narratio maps `party`, `players`, and `glossary` to the three documented
prepared campaign sources and contains no default `spell_catalog` binding.
- Narratio declares all ten documented output entries with exact lane, media,
schema, version, and module identities.
- Narratio natively validates the effective base configuration for either
deployed campaign without a model call.
- `narratio config show` or the equivalent native inspection surface exposes
the enabled stage, selected pipeline, representative reference, and
representative output contract.
- The effective `testing` profile keeps Notarius enabled with the same pipeline
and profile while retaining the existing Scriptorium testing overrides.
- A caller can compose an additional Notarius pipeline into
`dnd_pipeline_notarius_pipelines` and select it through the corresponding
Narratio pipeline-ID variable without changing the role.
- A caller can add the optional spell-catalog source by extending the native
Narratio reference map after providing that campaign input.
- An immediate repeated role application with unchanged inputs reports no
changes.
- The production role contains no new configuration probes, validation
commands, runtime state beyond the required cache root, state bookkeeping,
duplicated root templates, secrets, extraction invocation, storage, or
publishing behavior.
### Required Validation
- YAML syntax checking and production-profile ansible-lint pass for the role
and test playbooks.
- The standalone-role integration suite explicitly selects Notarius v0.7.0,
validates a representative imported version 5 configuration through the
native CLI, and retains immediate clean repeated convergence without
asserting that v0.7.0 remains the default forever.
- The complete existing pipeline integration entry point continues to install
the pinned role combination and validate both deployed campaigns.
- A representative human account in the `narratio` group can execute native
Notarius configuration inspection through the same files used by the service
account.
- Notarius natively validates the role-managed `dnd-session` configuration.
- Notarius `config effective` exposes the composed imported pipeline and a
representative cache override without parsing managed YAML directly.
- Narratio natively validates both base and `testing` configurations with an
explicitly selected deployed campaign.
- Focused native inspection observes a representative generated Notarius
handoff and representative Narratio reference and output mappings rather
than reproducing the full application validators in shell assertions.
- A test explicitly supplies a small additional or replacement Notarius
pipeline mapping and observes that selected behavior; it does not assert
that `dnd-session` remains the role's current default forever.
- A representative test explicitly overrides one cache choice and observes
the effective Notarius configuration; it does not freeze all current cache
defaults or test Notarius's cache implementation.
- The immediate repeat reports `changed=0` and `failed=0`.
- Tests do not execute extraction, call an LLM, snapshot complete rendered
files, enumerate every nested option as an implementation lock, inspect
template task results, test filesystem metadata, or reproduce Ansible,
Notarius, Narratio, ConfigKit, or PromptKit behavior.
## Dependencies and Follow-up Work
Features 0001 through 0009 and the standalone-role test-suite simplification
are complete, so the shared filesystem and execution prerequisite is
satisfied. Implementation depends on the current Notarius v0.7.0 maintained
D&D configuration and ConfigKit contract, the compatible Narratio v2.0.0
subprocess boundary, campaign sources deployed by Feature 0007, and trimmed
transcript policy defined by Feature 0008.
The next suite feature should select which extraction sources feed new or
existing Scriptorium artifacts, or address pipeline-wide credential delivery
if real end-to-end execution requires it first. Later work should cover
storage and publishing, optional operator selection and membership management,
collection assembly, release pinning, and an end-to-end workflow using actual
external services. A separate feature may add inexpensive Notarius testing
extraction if a concrete workflow justifies a second operator profile or
application configuration.
## Potential Future Hardening
- Add explicit cache and debug retention policy once operational use provides
concrete retention requirements.
- Define credential delivery beneath the restricted `secrets/` subtree. No
further Notarius cache-permission feature is required for shared invocation.
- Pin content repositories to immutable releases when their upstream projects
begin publishing them.

View File

@@ -1,14 +1,613 @@
# Implementation Plan
# Implementation Plan 0010: D&D Notarius Extraction Integration
Status: pending
Status: ready
No implementation plan is currently active. Feature 0006 was implemented in
`ansible-role-dnd-pipeline` commits `b515968` and `61869d1`, independently
reviewed, and finalized by remediation commit `4ea4358`.
Target executor: GPT-5.6-Terra
Its durable scope and rationale remain in
[the Feature 0006 roadmap](features/0006-pipeline-role-composition-foundation.md),
and its final review record remains in [the remediation record](remediation.md).
Feature roadmap:
`docs/roadmap/features/0010-dnd-notarius-extraction-integration.md`
Select and approve the next unit of work before replacing this notice with a
new staged implementation plan.
Active plan location: `docs/roadmap/implementation.md`
## Objective
Upgrade the generic Notarius role to the v0.7.0 configuration contract, then
have the D&D pipeline role deploy the maintained ten-lane extraction pipeline,
enable it through Narratio, bind prepared campaign references, accept all ten
lane contracts, and provision the shared FHS cache policy established by
Feature 0009.
The feature roadmap remains authoritative for scope, rationale, target end
state, and acceptance criteria. Decisions 0001 and 0002 remain authoritative
for direct Ansible convergence and the shared-readable filesystem boundary.
## Execution Rules
- Execute stages in numeric order.
- Before each stage, confirm its preconditions and the working-tree state of
its owning repository.
- Before each stage, reread every document listed in that stage's Required
Policy Review. Do not rely on policy recalled from an earlier stage.
- Preserve unrelated and pre-existing changes. Stop if an owning repository is
unexpectedly dirty at a stage boundary.
- Keep `ansible-role-notarius` generic. ConfigKit import support is a native
application interface; the D&D pipeline, campaign bindings, cache policy,
and Narratio coordination belong only to `ansible-role-dnd-pipeline`.
- Use the Notarius v0.7.0 maintained complete pipeline as the topology and
contract authority. Remove external path references, but retain generated
artifact handoffs and canonical version 5 binding objects.
- Trust the existing application-role templates and Ansible modules. Do not
add production validation commands, preliminary probes, manual comparisons,
handlers, checksums, manifests, state files, or corrective permission tasks.
- Create only the shared Notarius cache root. Notarius owns creation of its
configured `chunk-plans` and `checkpoints` children during actual use.
- Keep the existing Narratio `testing` overlay unchanged so it inherits the
enabled Notarius stage and `dnd-extraction` workload profile.
- Do not add credentials, a PromptKit profile file, campaign paths, a global
Notarius output or debug root, checkpoint resume, extraction execution,
model calls, storage, publishing, services, schedules, or user-membership
management.
- Test public behavior through the installed applications' native inspection
and validation interfaces. Do not snapshot complete configuration files,
parse production task results, inspect filesystem metadata, or reproduce
application and Ansible validators in assertions.
- Run every stage's validation before committing it. Commit each completed
stage when it leaves the owning repository valid, using the plain-English
commit intent specified by that stage.
- Do not begin a dependent stage after an earlier stage fails validation.
- The pipeline integration suite installs role dependencies from their
canonical Git origins. The Stage 1 Notarius-role commit must therefore be
reachable from its canonical origin before Stage 2 begins. If it is not,
stop after Stage 1 and report the commit hash for publication; do not use a
branch, local path, or weakened dependency test as a substitute.
## Starting State and Preconditions
- The workspace control repository contains the reviewed Feature 0010 roadmap
and this implementation plan on `main` in a clean planning commit descended
from `f91871ba0f90da19592eb56824f5abb9e7868285`.
- Features 0001 through 0009 and the standalone-role test-suite simplification
are complete.
- The implementation repositories are clean on `main` at these reviewed
starting commits:
| Repository | Starting commit |
| --- | --- |
| `ansible-role-notarius` | `e9ae2dc34023e1e8462bf0991de62b97d8c0e0ee` |
| `ansible-role-dnd-pipeline` | `b15fe8dcf57a53784bc3b0b8bf04aa97d39edb3f` |
- The Notarius-role starting commit matches `origin/main`. The pipeline role
is intentionally ahead of its canonical origin and must not be reset or
replaced.
- `../notarius` is clean at the immutable `v0.7.0` tag,
`4e77725b24cb62bd1f96ee31b4d17b4a2ed68ba7`.
- `../narratio` is clean at the immutable `v2.0.0` tag,
`ed4623bc415901134c765fe9cf06d59aa7891500`.
- Notarius v0.7.0 preserves the subprocess receipt and extraction-artifact
contracts consumed by Narratio v2.0.0 while requiring Notarius
configuration version 5.
- The workspace `.venv` provides Ansible Core 2.21.3 and ansible-lint 26.8.0.
- The local integration environment remains an accepted proxy for Ubuntu
26.04, supports task-level privilege escalation, and provides ordinary POSIX
ACL behavior.
## Repository Scope
Repositories that change:
- `ansible-role-notarius`: v0.7.0 selection, configuration version 5,
nullable native ConfigKit imports, generic documentation, and focused
integration coverage.
- `ansible-role-dnd-pipeline`: compatible Notarius role and application pins,
opinionated D&D pipeline configuration, Narratio integration, shared cache
root, documentation, and focused integration coverage.
- `ansible-workspace-dnd`: implementation progress and review handoff only
after the role stages are complete.
Repositories that may be inspected but must remain unchanged:
- `../notarius` and `../narratio`, which are read-only application authorities.
- `ansible-role-narratio`, whose generic Notarius adapter already exposes all
fields required by this feature.
- `ansible-role-audita`, `ansible-role-seriatim`,
`ansible-role-scriptorium`, and `ansible-collection-dnd`.
- `assets/campaigns`, `assets/narratio-prompts`, and `assets/configs`.
- `rakestraw-ansible` and every other repository in `workspace.yml`.
## Stage 1: Upgrade the Generic Notarius Role
Status: complete (`14a38e04e35ef524d6a97fa7fb5a04981a0a2161`)
### Objective
Make the standalone role install Notarius v0.7.0, render configuration version
5, and expose the application's native ConfigKit import list without adding
D&D-specific policy.
### Required Policy Review
Before beginning this stage, read:
- `AGENTS.md`
- `docs/orientation.md`
- `docs/conventions.md`
- `docs/ansible.md`
- `docs/testing.md`
- `docs/roadmap/features/0010-dnd-notarius-extraction-integration.md`
- `docs/decisions/0001-minimal-module-driven-ansible.md`
- `../notarius/docs/releases/v0.7.0.md`
- `../notarius/docs/config.md`
- `../notarius/docs/cli.md`
- `../notarius/examples/dnd-complete.config.yml`
- `../notarius/examples/pipelines/dnd-session.yml`
- `ansible-role-notarius/defaults/main.yml`
- `ansible-role-notarius/meta/argument_specs.yml`
- `ansible-role-notarius/templates/config.yml.j2`
- `ansible-role-notarius/tests/integration`
- `ansible-role-notarius/tests/verify-config.yml`
- `ansible-role-notarius/README.md`
### Preconditions
- `ansible-role-notarius` is clean at its stated starting commit.
- The repository's existing `tests/integration` entry point passes before
modification.
- The v0.7.0 upstream files listed above remain at the reviewed immutable tag.
### Owning Repository
`ansible-role-notarius`
### Required Changes
1. Advance `notarius_version` from `v0.6.0` to `v0.7.0` and
`notarius_config_version` from `4` to `5`. Do not change the established
source-build task flow or other generic defaults.
2. Add `notarius_configkit_imports: null` as one optional public variable and
add a matching argument-specification entry using a list of native mapping
objects. Do not create field aliases for import entries or add role-owned
merge behavior.
3. Render a top-level `configkit.imports` section only when
`notarius_configkit_imports is not none`. Serialize the supplied list with
an established Ansible/Jinja data filter; do not manually construct YAML or
alter `notarius_pipelines`.
4. Keep every other optional field governed by its current null-omission
behavior. The role manages only its root configuration and must not create
any caller-selected imported fragment.
5. Update the README's version, configuration version, variable list, and
configuration discussion. Explain that ConfigKit imports are caller-owned
native composition inputs and that relative imports resolve from the
managed root configuration directory. Do not mention the D&D suite's fixed
fragment or cache policy as a standalone default.
6. Migrate the integration fixture from configuration version 4 shorthand to
canonical version 5 module-binding objects. Use a test-owned imported
fragment to exercise `notarius_configkit_imports`; fixture creation is test
setup and must not become a production role task.
7. Exercise an explicitly selected `notarius_version: v0.7.0`, caller-side
composition of two small pipeline maps, an intentional falsey cache value,
a representative cache override, and the existing caller-supplied Go
executable/missing-binary recovery behavior. Use v0.7.0 for cases that need
a configuration-compatible executable.
8. Validate the representative imported pipeline with
`notarius config validate --pipeline <id>` and observe composition and the
cache override through `notarius config effective` or another native
inspection command. Remove direct managed-file assertions from
`tests/verify-config.yml`; delete that playbook if it has no remaining
behavioral purpose.
9. Retain an immediate identical repeat that reports `changed=0` and
`failed=0`. Do not assert that v0.7.0 remains the role default, test
ConfigKit itself, or add production validation and state inspection.
### Validation
Run from `ansible-role-notarius`:
```text
tests/integration
git diff --check
git status --short
```
Expected result: syntax and production-profile lint pass; the explicitly
selected v0.7.0 binary reports its selected version; native Notarius commands
validate and inspect the representative composed version 5 configuration;
missing-binary recovery still works with the caller's Go executable; all
immediate repeats report `changed=0` and `failed=0`; and only intended role,
test, and README files are modified.
### Completion Criteria
- Defaults, argument specification, template, README, and tests expose one
coherent generic ConfigKit import interface.
- The root document is version 5 and no D&D pipeline or caller-owned fragment
is embedded in the standalone role.
- Tests observe native application behavior and do not snapshot defaults or
re-test Ansible module guarantees.
- The repository is valid and the stage is committed.
### Commit
Commit intent: `Upgrade the Notarius role to version 0.7.0`
## Stage 2: Implement the Suite Notarius Integration
### Objective
Add the pipeline role's complete D&D Notarius configuration, Narratio wiring,
and shared cache convergence using the reviewed standalone-role interface.
### Required Policy Review
Before beginning this stage, read:
- `AGENTS.md`
- `docs/orientation.md`
- `docs/conventions.md`
- `docs/ansible.md`
- `docs/testing.md`
- `docs/roadmap/features/0010-dnd-notarius-extraction-integration.md`
- `docs/decisions/0001-minimal-module-driven-ansible.md`
- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md`
- the committed Stage 1 changes in `ansible-role-notarius`
- `../notarius/docs/releases/v0.7.0.md`
- `../notarius/docs/config.md`
- `../notarius/docs/consumers/dnd-pipeline.md`
- `../notarius/examples/dnd-complete.config.yml`
- `../notarius/examples/pipelines/dnd-session.yml`
- `../narratio/docs/integrations/notarius.md`
- `../narratio/examples/pipeline.full.annotated.yml`
- `ansible-role-dnd-pipeline/defaults/main.yml`
- `ansible-role-dnd-pipeline/meta/argument_specs.yml`
- `ansible-role-dnd-pipeline/meta/main.yml`
- `ansible-role-dnd-pipeline/requirements.yml`
- `ansible-role-dnd-pipeline/tasks/main.yml`
- `ansible-role-dnd-pipeline/templates/testing.yml.j2`
- `ansible-role-dnd-pipeline/tests/integration`
### Preconditions
- Stage 1 is committed, validated, and clean.
- The Stage 1 commit is reachable from the canonical
`ansible-role-notarius` Git origin. Stop and report the hash if a fresh Git
or Galaxy fetch cannot resolve it.
- `ansible-role-dnd-pipeline` is clean at its stated starting commit or an
expected reviewed descendant.
- Its existing `tests/integration` entry point passes before modification.
### Owning Repository
`ansible-role-dnd-pipeline`
### Required Changes
1. Set `dnd_pipeline_notarius_version: v0.7.0` and pin the
`rakestraw.notarius` entry in `requirements.yml` to the exact Stage 1
commit. Retain the canonical Git URL and every unrelated dependency pin.
2. Add these required, defaulted suite variables and matching argument
specifications:
`dnd_pipeline_notarius_pipelines` as a complete native map,
`dnd_pipeline_notarius_cache_root` as a path,
`dnd_pipeline_notarius_cache_chunk_plans_mode` as a string,
`dnd_pipeline_notarius_cache_checkpoints_enabled` as a boolean,
`dnd_pipeline_narratio_notarius_pipeline_id` as a string,
`dnd_pipeline_narratio_notarius_references` as a complete native map, and
`dnd_pipeline_narratio_notarius_outputs` as a complete native map.
3. Default the pipeline map to one `dnd-session` entry adapted from the
Notarius v0.7.0 maintained fragment. Preserve its embedded
`dnd-extraction` profile ID, Seriatim input, `dnd/scenes` chunker with two
retries, three ordered steps, ten lanes, canonical object bindings,
generated artifact handoffs, JSON chunk map, and nine-lane evidence-context
selection with a three-unit window.
4. Remove every external `path` reference from the adapted pipeline: omit the
example's `party`, `glossary`, and binding-local `spell_catalog` paths.
Retain only generated `artifact` references between steps. Do not install a
PromptKit profile file or set global output/debug roots.
5. Default the selected pipeline ID to `dnd-session`. Default the Narratio
reference map to `party: narratio.input.party`,
`players: narratio.input.players`, and
`glossary: narratio.input.glossary`; do not add `spell_catalog` until a
deployed campaign supplies that optional input.
6. Default the Narratio output map to all ten exact lane, media type, schema
ID, schema version, and module-key descriptors recorded in the feature
roadmap and Narratio's maintained example. Keep both maps replaceable as
whole native values through normal inventory precedence.
7. Default the cache root to `/var/cache/notarius`, chunk-plan mode to `auto`,
and checkpoint recording to `true`. Derive
`/var/cache/notarius/chunk-plans` and
`/var/cache/notarius/checkpoints` in dependency wiring rather than adding
independent suite variables.
8. Pass the fixed relative import `pipelines/dnd-session.yml`, selected cache
settings, and derived child paths to `rakestraw.notarius`. Leave its
root-level `notarius_pipelines` unset so the standalone role continues to
own only the root document.
9. Pass `narratio_notarius_enabled: true`, the selected pipeline ID,
`/usr/local/etc/notarius` working directory, and the reference/output maps
to `rakestraw.narratio`. Retain the established binary and configuration
paths, leave its native three-hour timeout in control, and do not change the
Narratio role or testing-overlay template.
10. Create `/var/cache/notarius` directly as the selected runtime user and
group with mode `2775` before ACL convergence. Add that root to both
existing access and default ACL loops; do not create its child stores or
add a second ACL implementation.
11. Create `/usr/local/etc/notarius/pipelines` directly with the suite
configuration owner, group, and directory mode. Add one template that
serializes only `pipelines: dnd_pipeline_notarius_pipelines` to
`dnd-session.yml` with the suite file metadata. Do not duplicate the
standalone root template or manually render every nested map field.
12. Keep production convergence limited to the existing role dependencies,
one cache-root file operation, the existing ACL loops, one configuration
directory operation, and one template operation. Do not add commands,
`stat`, handlers, validation tasks, state bookkeeping, secrets, extraction,
or retention behavior.
### Validation
Run from `ansible-role-dnd-pipeline`:
```text
tests/integration
git diff --check
git status --short
```
Expected result: isolated dependency installation resolves the exact Stage 1
commit; syntax and production-profile lint pass; the five applications install
successfully; Notarius natively validates the imported `dnd-session` pipeline;
Narratio validates the assembled base and testing configurations; the baseline
repeat reports `changed=0` and `failed=0`; and only intended pipeline-role
files are modified.
### Completion Criteria
- The suite installs Notarius v0.7.0 through the exact reviewed role revision.
- The complete path-free D&D pipeline is owned by one suite fragment and is
imported through the standalone role's public interface.
- Narratio enables and selects the pipeline with the three prepared campaign
references and all ten exact accepted outputs.
- The FHS cache root and inherited access policy use direct module-owned
convergence; child stores remain application-owned.
- The unchanged testing overlay inherits Notarius enablement and pipeline
selection.
- The repository is valid and the stage is committed.
### Commit
Commit intent: `Integrate Notarius extraction into the D&D pipeline`
## Stage 3: Document and Exercise the Integration Contract
### Objective
Document the suite's Notarius policy and add the smallest behavioral coverage
that proves native composition, Narratio coordination, shared access,
customization, and immediate idempotence.
### Required Policy Review
Before beginning this stage, read:
- `AGENTS.md`
- `docs/orientation.md`
- `docs/conventions.md`
- `docs/ansible.md`
- `docs/testing.md`
- `docs/roadmap/features/0010-dnd-notarius-extraction-integration.md`
- `docs/decisions/0002-shared-readable-pipeline-filesystem-policy.md`
- the committed Stage 1 and Stage 2 changes
- `../notarius/docs/cli.md`
- `../notarius/docs/consumers/dnd-pipeline.md`
- `../narratio/docs/cli.md`
- `../narratio/docs/integrations/notarius.md`
- `ansible-role-dnd-pipeline/README.md`
- `ansible-role-dnd-pipeline/tests/integration`
- `ansible-role-dnd-pipeline/tests/converge.yml`
### Preconditions
- Stages 1 and 2 are committed, validated, and clean.
- The pipeline's isolated dependency installation resolves the Stage 1 commit.
- The deployed baseline can be restored through the existing integration
driver's cleanup path.
### Owning Repository
`ansible-role-dnd-pipeline`
### Required Changes
1. Update the README's compatible-version table to Notarius v0.7.0 and replace
the statement that Notarius remains disabled with the implemented
extraction behavior.
2. Document the seven new suite variables, the fixed root import and fragment
path, caller-side map replacement/composition with Jinja `combine`, the
prepared-reference boundary, all ten accepted output sources, and the
optional future `spell_catalog` extension. Distinguish native maps from
field-specific scalar controls.
3. Document `/var/cache/notarius`, `auto` chunk plans, recorded-but-not-resumed
checkpoints, derived child paths, `2775` setgid/default-ACL policy, and use
by either the service account or an existing member of the runtime group.
Retain the world-readable non-secret policy and the deferred restricted
credential boundary.
4. Document that base and `testing` configurations use the same
`dnd-extraction` profile and pipeline. Do not claim that testing avoids
Notarius model calls during a real run; integration tests perform only
offline configuration inspection.
5. Extend the baseline integration path to run
`notarius config validate --pipeline dnd-session` and inspect
`notarius config effective`. Observe one generated artifact handoff and one
cache setting from the native effective output without reading the managed
YAML file or enumerating every pipeline option.
6. Use Narratio's native `config validate` for both `centaurs` and `dilfs` in
the base configuration and at least one campaign under `testing`. Use
`config show` or another native inspection surface to observe Notarius
enablement, the selected pipeline, one prepared reference, and one output
descriptor. Keep the existing check that the testing overlay changes only
its intended Scriptorium profile selections.
7. As the existing uniquely named operator fixture in the runtime group, run
one native Notarius validation or inspection command against the same root
and imported fragment used by the service account. Add one actual
service/operator read-write exchange beneath `/var/cache/notarius`, or move
the existing representative exchange there, to exercise the new shared
root without parsing ACLs or mode bits. Do not add an exhaustive root or
identity matrix.
8. Add one alternate convergence case that supplies two small version 5
pipeline maps and composes them into
`dnd_pipeline_notarius_pipelines` with Jinja `combine`, selects a matching
alternate pipeline ID, and overrides one cache choice. Observe the two
pipeline IDs and effective cache choice through native Notarius inspection,
then require one immediate identical repeat with `changed=0` and
`failed=0`.
9. Retain the baseline clean repeat, immutable local asset inputs, isolated
dependency installation, cleanup safety, and existing representative
application checks. Restore the default deployment during cleanup.
10. Do not run extraction, contact an LLM or WhisperX endpoint, snapshot a
complete rendered document, assert every nested pipeline field, test
filesystem metadata, or reproduce Notarius, Narratio, ConfigKit, PromptKit,
or Ansible behavior.
### Validation
Run from `ansible-role-dnd-pipeline`:
```text
tests/integration
git diff --check
git status --short
```
Expected result: isolated role and collection installation, syntax checking,
and production-profile lint pass; native Notarius validation and effective
inspection prove composition and representative policy; Narratio validates
both campaigns and the testing profile; a supported group member can inspect
the same Notarius configuration and exchange representative cache content;
the combined-map/cache override is observable; all immediate repeats report
`changed=0` and `failed=0`; and documentation matches the public interface.
### Completion Criteria
- Documentation describes the implemented suite policy, public customization
boundary, shared cache, testing behavior, and deliberate exclusions.
- Tests protect role-owned integration behavior without freezing complete
defaults or testing module internals.
- Both deployed campaigns validate, and the base and testing configurations
retain the enabled Notarius stage.
- Baseline and representative override applications converge cleanly on their
immediate repeats.
- The repository is valid and the stage is committed.
### Commit
Commit intent: `Document and test the D&D Notarius integration`
## Stage 4: Record the Implementation for Review
### Objective
Record the completed implementation and validation evidence in the workspace
without declaring the feature complete before independent review.
### Required Policy Review
Before beginning this stage, read:
- `AGENTS.md`
- `docs/orientation.md`
- `docs/conventions.md`
- `docs/planning.md`
- `docs/roadmap/features/0010-dnd-notarius-extraction-integration.md`
- `docs/roadmap/implementation.md`
- `docs/status.md`
### Preconditions
- Stages 1 through 3 are committed and their owning repositories are clean.
- Both complete integration entry points pass at the committed revisions.
- The workspace control repository is clean at the planning commit.
### Owning Repository
`ansible-workspace-dnd`
### Required Changes
1. Update this plan's Progress Notes with the three implementation commit
hashes and concise validation results.
2. Update `docs/status.md` so Feature 0010 is `in_progress`, its evidence names
the implementation commits, and the current focus is independent review of
the completed implementation.
3. Keep the feature roadmap `ready`; do not mark Feature 0010 `done`, clean the
durable roadmap, or create `docs/roadmap/remediation.md`. Those actions
belong to the independent review and closeout workflow.
4. Do not change implementation repositories or unrelated workspace policy in
this stage.
### Validation
Run from the workspace root:
```text
git diff --check
./scripts/status
git status --short
```
Expected result: the status report identifies only the intended workspace
tracking edits before commit; both implementation repositories are clean; and
the dashboard and progress notes point to the exact completed stage commits.
### Completion Criteria
- The implementation and validation evidence is traceable across repositories.
- Feature 0010 remains awaiting independent review rather than being marked
complete.
- The workspace control repository is valid and the stage is committed.
### Commit
Commit intent: `Record the D&D Notarius integration implementation`
## Final Validation and Handoff
After Stage 4, rerun both owning repositories' complete integration entry
points:
```text
cd ansible-role-notarius && tests/integration
cd ../ansible-role-dnd-pipeline && tests/integration
```
Then, from the workspace root, run:
```text
git diff --check
./scripts/status
```
The final handoff must:
- identify the Stage 1 through Stage 4 commit hashes and confirm each changed
repository has a clean working tree;
- confirm syntax and production-profile lint pass in both changed roles;
- confirm the standalone role installs an explicitly selected Notarius v0.7.0,
validates and inspects composed version 5 configuration natively, and
immediately converges cleanly;
- confirm the pipeline installs the exact immutable Notarius-role commit,
validates the complete D&D pipeline and both Narratio campaign resolutions,
preserves Notarius under `testing`, supports the representative shared-user
path, and immediately converges cleanly;
- confirm no upstream application, asset, collection, unrelated standalone
role, secret, external service, or real human account was modified;
- summarize any deviation, blocker, or deferred work, including any pause
required to publish the Stage 1 dependency commit;
- report any production complexity beyond the planned public variables,
dependency wiring, one imported fragment, one cache-root task, and extension
of the existing ACL loops, together with the acceptance criterion that
required it; and
- leave Feature 0010 `in_progress` for independent review rather than marking
it `done`.
## Progress Notes
No implementation stages have begun. Record only concise stage commit hashes,
validation results, and blockers here during execution; preserve detailed
evidence in the implementation commits and final handoff.

View File

@@ -14,9 +14,11 @@ Build independently usable Ansible roles for the five Narratio applications
and compose them through a suite-level role developed in its own repository.
The `rakestraw.dnd` collection exposes that role as `rakestraw.dnd.pipeline`.
The suite-level role installs and configures the complete D&D transcript
processing pipeline on a single supported host. Human operators invoke
Narratio commands directly to process D&D session recordings and produce
transcripts and related artifacts.
processing pipeline on a single supported host. Operators or unattended
automation invoke Narratio commands either under the dedicated `narratio`
runtime identity or under a human account that belongs to the `narratio`
group, processing D&D session recordings into transcripts and related
artifacts.
## Locked Decisions
@@ -186,38 +188,78 @@ application-role releases in one source repository.
- The pipeline role installs Narratio's PromptKit-compatible prompt library
from the `narratio-prompts` Git repository. The Scriptorium role owns its
native prompt, profile, and schema directory configuration, while the
pipeline role owns populating those locations with suite integration
content.
native prompt and schema directory configuration, while the pipeline role
owns populating those locations with suite integration content.
- The upstream repository is
`https://gitea.maximumdirect.net/eric/narratio-prompts`.
- For the MVP, the pipeline role tracks and pulls the latest upstream commit.
`https://gitea.maximumdirect.net/eric/narratio-prompts.git`.
- The repository is checked out at
`/usr/local/share/narratio/prompt-library` by default. Scriptorium's prompt
and schema directories are the checkout's `prompts/` and `schemas/`
subdirectories.
- The repository does not currently contain execution profiles. The pipeline
role does not set Scriptorium's profile directory until a later suite-policy
feature selects and deploys profiles.
- For the MVP, the pipeline role tracks and pulls the repository's `main`
branch. The origin, revision, and checkout root are configurable, and a
caller may select an immutable commit when required.
- Pinning the prompt library to a version or release is deferred until the
upstream repository provides versioned releases.
### Campaign registry content
- The pipeline role checks out the `campaigns` Git repository directly into
Narratio's campaign registry root. The upstream repository is
`https://gitea.maximumdirect.net/eric/campaigns.git`.
- The default campaign root remains
`/usr/local/share/narratio/campaigns`, and the pipeline role passes that same
value to the Narratio application role.
- For the MVP, the pipeline role tracks and pulls the repository's `main`
branch. The origin, revision, and campaign root are configurable, and a
caller may select an immutable commit when required.
- Both asset checkouts are root-managed and remotely authoritative. Operators
may read the content but do not edit it on the managed host. Ordinary Git
module convergence owns tracked-content updates; the role does not maintain
separate revision state or purge untracked files.
### Accounts, ownership, and operator access
- The standalone Narratio role creates a dedicated system `narratio` user and
`narratio` group. The account uses `/var/lib/narratio` as its default home
and has a non-login shell.
- The `narratio` account owns Narratio's writable runtime directories.
- The `narratio` account owns the suite's application configuration and
writable runtime directories; `narratio` is also the shared operator group.
- Application source trees and installed binaries are owned by `root` and are
not writable by operators or the runtime account.
- Ordinary human users run `narratio run` and other Narratio commands directly.
- Those operators receive the required access by membership in the `narratio`
group.
- Narratio's configuration directory is owned by `root:narratio` with mode
`0750`, and its pipeline file is owned by `root:narratio` with mode `0640`.
Configuration remains under Ansible control rather than being routinely
edited by operators on the host.
- The Narratio workspace, spool, and cache roots are owned by
`narratio:narratio` with mode `2775`, preserving the group on created content
and granting the shared write access needed for direct operator invocations.
- The supported operational model runs `narratio run` and other processing
commands either as the dedicated `narratio` account or as a human account
that is already a member of the `narratio` group. The suite does not yet
select those human accounts or manage their membership.
- Application configuration directories and files are owned by
`narratio:narratio`, use modes `0755` and `0644`, respectively, and are
world-readable. Configuration remains under Ansible control rather than
being routinely edited by operators on the host.
- Workspace, spool, and cache roots are owned by `narratio:narratio` with mode
`2775`. Setgid and managed default ACLs preserve shared group write access
and world read/traverse access for newly created directories and files even
when invocation identities have different ordinary umasks.
- The pipeline role installs the host `acl` package and uses the declared,
pinned `ansible.posix` collection to manage access and default ACL entries on
those shared writable roots.
- The campaign registry root is owned by `root:narratio` with mode `0755`.
Its content is readable by operators but is populated by the suite role and
is not edited directly on the managed host.
- The standalone role does not select human operators. The suite role owns the
operator list and adds those accounts to the `narratio` group.
Its content is world-readable but is populated by the suite role and is not
edited directly on the managed host.
- Configuration, transcripts, caches, generated artifacts, logs, campaign
data, and prompt assets are deliberately non-secret D&D content and remain
world-readable. API keys and similar credentials are the sole confidential
category.
- Debug output is not enabled by the MVP. Any later debug feature must either
produce world-readable non-secret D&D diagnostics or identify and justify a
narrower application contract before deployment.
- Credential material will live beneath a restricted `secrets/` subdirectory
owned by `narratio:narratio`, with directories mode `0750` and files mode
`0640`. Ordinary configuration contains only credential reference names.
- [Decision 0002](../decisions/0002-shared-readable-pipeline-filesystem-policy.md)
records the complete rationale and boundary for this policy.
### Narratio configuration
@@ -239,6 +281,44 @@ application-role releases in one source repository.
them owns their deployment.
- Credential fields contain environment-variable names, never secret values.
Secret delivery remains suite-level policy.
- The standalone Narratio role owns the root pipeline document. The pipeline
role owns its D&D-specific imported processing, artifact, and artifact-family
fragments under `/usr/local/etc/narratio` and selects them through an
explicit ordered `configkit.imports` list.
- Each ordinary artifact and artifact family is defined in a separate managed
file. Explicit imports are preferred to directory globs so removed or stale
files do not remain active implicitly.
- The pipeline role manages a native `profiles/testing.yml` overlay for
inexpensive development and asset iteration. Production retains its
frontier-oriented model/profile policy; callers select the testing overlay
explicitly with Narratio's `--profile testing` interface.
- Base fragments and the testing overlay contain configuration and
environment-variable or secret-reference names only. They never contain raw
credentials.
- The D&D suite deliberately supplies Audita's complete reviewed processing
policy, including the current module sequence and tuning, `audita-v1`
output, the `https://inference.ai.rakestrawhome.com/v1` endpoint, and
`google/gemma-4-31b-it` for proposal and validation. Those values remain
inventory-overrideable and are suite policy rather than copies of upstream
defaults.
- The Narratio `testing` profile selects `gemini-flash-latest` for its
Scriptorium artifacts and families. Audita initially uses the same endpoint
and models in production and testing; identical values are inherited rather
than duplicated in the overlay.
- The D&D suite enables Notarius's `auto` chunk-plan cache and checkpoint
cache beneath `/var/cache/notarius`. That FHS cache root is owned by the
`narratio` account and group with mode `2775` and the suite's shared default
ACL policy. Notarius v0.7.0 leaves cache-entry access to that deployment
policy. Chunk plans are reused automatically; checkpoints are recorded but
Narratio does not yet request their reuse.
- The standalone Notarius role exposes Notarius v0.7.0's native ConfigKit
import list while remaining independent of D&D content. The pipeline role
owns an imported `pipelines/dnd-session.yml` fragment containing its
opinionated, inventory-composable D&D pipeline map; the standalone role
continues to own only the version 5 root document.
- The Narratio `testing` profile keeps the Notarius stage enabled and inherits
the same D&D pipeline and extraction profile as production until a distinct
testing extraction policy is selected.
### Execution model
@@ -255,19 +335,26 @@ later design decision changes them:
- `/usr/local/etc/narratio` for Narratio configuration
- `/usr/local/etc/audita/config.yml` for Audita configuration
- `/usr/local/etc/notarius/config.yml` for Notarius configuration
- `/usr/local/etc/notarius/pipelines` for suite-owned imported Notarius
pipeline definitions
- `/usr/local/etc/scriptorium/config.yml` for Scriptorium configuration
- `/usr/local/etc/narratio/secrets` for future restricted credential material
- `/usr/local/share/narratio/campaigns` for version-controlled campaign data
- `/usr/local/share/narratio/prompt-library` for version-controlled prompts
and schemas
- `/usr/local/src/<app>` for root-owned application source checkouts
- `/usr/local/bin/<app>` for root-owned application binaries
- `/var/lib/narratio` for durable workspace and session state
- `/var/spool/narratio` for spool data
- `/var/cache/narratio` for cached data
- `/var/cache/notarius` for suite-provisioned Notarius chunk-plan and
checkpoint caches
The Narratio role creates and configures the campaign root; the pipeline role
populates it from the selected campaign source. `/usr/local/share` assumes Git
is authoritative and operators do not edit campaign content directly on the
managed host. The exact prompt-library checkout and installed-content paths
remain to be designed.
managed host. The prompt-library checkout retains its upstream `prompts/` and
`schemas/` layout at the fixed root above.
## Deferred Beyond the MVP
@@ -276,6 +363,7 @@ remain to be designed.
- Installation from prebuilt application release artifacts
- Deploying or managing WhisperX
- Versioned Narratio prompt-library releases and pinning
- Versioned campaign-content releases and default release pinning
- A role-managed scheduler or persistent Narratio service
- Cryptographic artifact verification, supply-chain hardening, and protection
against adversarial source or dependency infrastructure
@@ -290,10 +378,8 @@ The following areas require investigation and decisions before implementation:
- The mechanism used to incorporate the independently developed pipeline role
into collection releases
- The prompt-library destination and its integration with Scriptorium
- The campaign repository's checkout revision and deployment/update policy
- Secret injection and storage
- Suite-level operator-selection variables
- Optional suite-level operator-selection and group-membership management
- Upgrade, downgrade, and removal behavior
- Collection bootstrap and end-to-end validation details beyond the locked
dependency and testing policies above

View File

@@ -1,119 +1,90 @@
# Feature 0006 Remediation Review
# Feature 0009 Remediation Review
Status: resolved
Reviewed implementation commits:
- `b515968 Compose the D&D pipeline roles`
- `61869d1 Add focused pipeline composition coverage`
- `66ebea9 Make Audita configuration ownership configurable`
- `e9ae2dc Make Notarius configuration ownership configurable`
- `8b4c86e Make Scriptorium configuration ownership configurable`
- `eeb1105 Make Narratio configuration ownership configurable`
- `901ae35 Apply shared configuration ownership to the D&D pipeline`
- `dddc5ee Manage shared pipeline access with ACLs`
- `f53da82 Test shared pipeline access across users`
- `608d5be Document the shared pipeline execution model`
Remediation commit:
## Review Summary
- `4ea4358 Clean up pipeline composition review findings`
The production architecture and behavioral coverage implement Feature 0009 as
planned. The four standalone roles expose generic configuration ownership and
mode controls, and the pipeline selects its opinionated service-owned,
world-readable policy through those interfaces. Narratio establishes the
runtime identity first. The pipeline then installs ACL support and directly
converges access and default ACLs on the three existing shared roots. Focused
integration coverage exercises actual cross-identity configuration access and
bidirectional writes under a restrictive umask while preserving immediate clean
convergence.
The production architecture matches Feature 0006: the role contains only its
public defaults and argument specification, five pinned role dependencies,
the approved variable forwarding, and fixed Narratio path wiring. Its task
file is empty, and it does not duplicate downstream tasks, templates, state
inspection, or validation. The complete integration entry point passes.
No production code or test-suite remediation is required. One small consumer
documentation inconsistency remains.
The review identified two repository-quality findings.
## Finding 1: Remove the Misleading Placeholder README Sentence
## Finding 1: Operator Support Is Documented Inconsistently
Severity: low
`ansible-role-dnd-pipeline/README.md` still ends with the original placeholder
sentence claiming that the role installs the full production pipeline “plus
supporting assets.” Feature 0006 expressly defers campaign and prompt assets,
operator policy, secrets, and the opinionated D&D configuration layer. The
sentence is both redundant with the rewritten introduction and inaccurate for
the implemented foundation.
`ansible-role-dnd-pipeline/README.md:201-217` first lists "operator access" as
deferred, then correctly states that invocation by an existing member of the
selected runtime group is supported. The likely deferred concern is operator
selection and group-membership management, not operator access itself.
The supported-platform summary also names Ubuntu 26.04 without recording the
roadmap's `amd64` and `arm64` boundary.
The adjacent YAML fragment defines an otherwise unexplained
`operator_group_members` variable but shows no consumer task or role that uses
it. As written, copying the example does not manage any membership and may lead
a reader to believe that the pipeline role consumes that variable.
### Required Remediation
- Remove the retained placeholder sentence.
- State the supported `amd64` and `arm64` architectures in the rewritten
platform summary.
- Make no broader README expansion; the existing dependency, interface,
deferral, and validation documentation is otherwise aligned.
- Replace "operator access" in the deferred list with the precise deferred
behavior: operator selection and group-membership management.
- Replace the inert variable fragment with a concise, complete consumer-side
example that actually adds a selected account to the runtime group, or omit
the example and state the prerequisite directly.
- Keep human account and membership management outside the production pipeline
role.
### Resolution
## Resolution
The retained sentence was removed, and the introduction now records the
supported `amd64` and `arm64` architectures without expanding the role's
claimed scope.
Resolved in pipeline-role commit `b15fe8d`. The deferred-work summary now
names operator selection and group-membership management rather than operator
access. The shared-filesystem section retains existing-group-member invocation
as supported behavior and provides a complete consumer-owned
`ansible.builtin.user` example that adds a selected account to the runtime
group. No production role behavior changed.
## Finding 2: Give the Isolated Dependency Path Resolution Priority
## Required Validation
Severity: low
`ansible-role-dnd-pipeline/tests/integration` installs the five pinned Git
roles into `$test_tmp/roles`, but sets `ANSIBLE_ROLES_PATH` with the workspace
parent before that isolated directory:
```sh
export ANSIBLE_ROLES_PATH="$(dirname "$repository_root"):$test_tmp/roles"
```
No conflicting canonical role directories currently exist in the workspace,
so the reviewed run used the installed dependencies and passed. Nevertheless,
the ordering does not preserve the test's stated invariant if a
`rakestraw.<application>` directory is later present in the parent path:
Ansible would resolve that checkout before the exact version installed from
`requirements.yml`. Feature 0006 requires the integration suite to exercise
the same pinned dependency combination delivered to consumers.
### Required Remediation
Put the fresh dependency path first while retaining the workspace parent only
as the fallback that resolves the pipeline role under test:
```sh
export ANSIBLE_ROLES_PATH="$test_tmp/roles:$(dirname "$repository_root")"
```
Do not add dependency-content comparisons, source-revision assertions, or
other verification machinery. Ordinary Ansible role lookup with the correct
path precedence is sufficient.
### Resolution
The integration driver now places its private dependency directory first and
uses the workspace parent only as the fallback for the pipeline role under
test. No additional dependency verification was added.
## Final Validation
From `ansible-role-dnd-pipeline`, run:
After the documentation correction, run:
```text
tests/integration
cd ansible-role-dnd-pipeline && tests/integration
git diff --check
git status --short --branch
```
Expected result: dependency bootstrap, syntax checking, production lint,
baseline native checks, Narratio configuration validation, both immediate
clean repeats, the explicit Seriatim `v1.4.0` outcome, and baseline cleanup all
pass. The role repository contains only the intended remediation changes.
The expected result remains successful native configuration checks,
representative cross-identity access, and immediate repeats with `changed=0`
and `failed=0`.
## Review Validation Evidence
During review, `tests/integration` completed successfully. It installed
`community.general` 13.3.0 and all five exact Git role revisions into private
temporary paths, passed syntax checking and production-profile ansible-lint,
validated the assembled applications through their native interfaces, and
reported `changed=0` and `failed=0` on both required immediate repeats. The
cleanup trap restored the baseline Seriatim `v1.5.0` deployment. `git diff
--check` also passed before this review record was written.
The independent review inspected the complete diffs for all eight stage
commits and confirmed that every dependency pin resolves to the intended
standalone-role commit. `git diff --check` passed across all five changed role
repositories. The complete pipeline `tests/integration` entry point passed its
isolated dependency installation, syntax check, production-profile lint,
native application checks, cross-identity access exercise, configurable
profile and version cases, and immediate clean repeats. All repositories were
clean before this review document was revised.
After remediation, `bash -n tests/integration`, `git diff --check`, and the
complete `tests/integration` entry point passed again. The rerun installed the
exact pinned dependencies into fresh private paths, passed syntax and
production-profile lint, completed all native checks, reported `changed=0` and
`failed=0` on both required repeats, and restored the baseline suite. No
Feature 0006 findings remain.
After remediation, the complete pipeline integration entry point and
`git diff --check` passed again. The test fixture was removed and the baseline
Seriatim version and pipeline configuration were restored during cleanup.

View File

@@ -1,10 +1,11 @@
# Workspace Status
Last updated: 2026-09-10
Last updated: 2026-09-15
Current milestone: M1-03 suite-level pipeline role
Current focus: Select the next suite-level pipeline role feature.
Current focus: Publish the completed Notarius role revision required to resume
Feature 0010.
| ID | Deliverable | Owner | State | Evidence or next step |
| --- | --- | --- | --- | --- |
@@ -15,7 +16,7 @@ Current focus: Select the next suite-level pipeline role feature.
| M0-05 | Suite-level role repository | ansible-role-dnd-pipeline | done | Repository created and added to `workspace.yml` |
| M1-01 | Remaining MVP design decisions | workspace | done | Feature 0003 roadmap fixes the Notarius configuration interface |
| M1-02 | Standalone application roles | role repositories | done | All five standalone roles implemented and independently reviewed |
| M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | in_progress | Composition foundation complete; select the next suite-policy feature |
| M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | blocked | Publish the completed Notarius role revision, then resume Feature 0010 |
| M1-04 | Collection assembly | ansible-collection-dnd | proposed | Select and implement the pipeline-role incorporation mechanism |
| F0001 | Install Seriatim from pinned source | ansible-role-seriatim | done | Implementation, integration coverage, and final remediation completed through `fb8dc41` |
| F0002 | Install and configure Audita | ansible-role-audita | done | Field-specific configuration completed in `e61f02f` and `847c4c3`; full suite passed |
@@ -23,6 +24,10 @@ Current focus: Select the next suite-level pipeline role feature.
| F0004 | Install and configure Scriptorium | ansible-role-scriptorium | done | Implemented and validated through remediation commit `8f47aa8` |
| F0005 | Install and configure Narratio | ansible-role-narratio | done | Implemented and validated through remediation commit `7feff47` |
| F0006 | Establish pipeline-role composition | ansible-role-dnd-pipeline | done | Implemented and validated through remediation commit `4ea4358` |
| F0007 | Deploy D&D campaigns and prompt assets | ansible-role-dnd-pipeline, campaigns, and narratio-prompts | done | Implemented and validated through remediation commit `7572fa3` |
| F0008 | Define opinionated D&D processing configuration | ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `3e253d7` |
| F0009 | Establish shared pipeline filesystem and execution | configuration-bearing application roles and ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `b15fe8d` |
| F0010 | Integrate D&D Notarius extraction | ansible-role-notarius and ansible-role-dnd-pipeline | blocked | Stage 1 completed in Notarius role commit `14a38e04e35ef524d6a97fa7fb5a04981a0a2161`; publish it to the canonical origin before Stage 2 |
| A0001 | Audit completed standalone-role test suites | workspace and standalone roles | done | Findings recorded in `docs/roadmap/test-suite-audit-findings.md` |
| R0001 | Simplify completed standalone-role test suites | workspace and standalone roles | done | Role commits `e08c63c`, `d2d0b9d`, and `cfecf37` passed implementation and independent review |