Compare commits

..

122 Commits

Author SHA1 Message Date
31c01f0fce Close out the Scriptorium credential update 2026-09-29 20:04:11 +00:00
7f957e14bc Record the Scriptorium credential update handoff 2026-09-29 18:47:03 +00:00
ed91180899 Record local consumer credential revision 2026-09-29 18:46:27 +00:00
827c734fdd Record public D&D collection credential revision 2026-09-29 18:44:25 +00:00
62f5f5e93f Record public D&D pipeline credential revision 2026-09-29 18:40:30 +00:00
2d2f67f66e Record public Narratio credential role revision 2026-09-29 18:19:04 +00:00
e1aa245054 Plan the Narratio Scriptorium credential update 2026-09-29 18:10:17 +00:00
43ecdebcc5 Close out the coordinated suite upgrade 2026-09-29 15:17:31 +00:00
6829439807 Record resolution of the suite upgrade review findings 2026-09-29 15:10:17 +00:00
fec2f89b48 Record coordinated suite upgrade validation 2026-09-29 14:58:35 +00:00
1f41045830 Record consumer upgrade preparation 2026-09-29 14:55:59 +00:00
f964b24f7e Record validated collection assembly revision 2026-09-29 14:51:58 +00:00
8b8c232043 Record validated pipeline assembly revision 2026-09-29 14:46:31 +00:00
1b1382fe6e Record suite configuration migration completion 2026-09-29 14:32:20 +00:00
c0a0dae794 Record the coordinated suite upgrade in progress 2026-09-29 14:16:57 +00:00
82e672b888 Record Gitea publication blocker 2026-09-29 14:11:02 +00:00
f084988c80 Prepare the coordinated suite upgrade sprint 2026-09-29 14:08:18 +00:00
005a1c8ad5 Close out the standalone Narratio upgrade 2026-09-29 13:16:41 +00:00
ced9e66382 Record Narratio upgrade validation 2026-09-28 14:55:53 +00:00
0dc7e5b965 Record Narratio selector validation 2026-09-28 14:54:06 +00:00
2477189047 Record the Narratio upgrade in progress 2026-09-28 14:50:08 +00:00
8c689ea113 Prepare the Narratio upgrade implementation sprint 2026-09-28 14:43:11 +00:00
e93ebea771 Close out the standalone Notarius upgrade 2026-09-28 14:36:06 +00:00
a0414244bb Record Notarius upgrade validation 2026-09-28 14:14:58 +00:00
ae8d93f71a Record Notarius retry validation 2026-09-28 14:13:33 +00:00
bcaf48155e Record the Notarius upgrade in progress 2026-09-28 14:09:01 +00:00
760a172b34 Prepare the Notarius upgrade implementation sprint 2026-09-28 14:06:57 +00:00
8111f66de5 Close out the standalone Audita upgrade 2026-09-28 13:52:04 +00:00
f58c960b56 Record the standalone Audita upgrade for review 2026-09-28 13:48:14 +00:00
5301dac921 Record completion of Audita configuration coverage 2026-09-28 13:45:52 +00:00
c0582faa24 Record completion of Audita version 2 role migration 2026-09-28 13:42:24 +00:00
e0153d938b Plan the standalone Audita version 2 upgrade 2026-09-28 13:33:47 +00:00
86836879eb Close out the standalone Scriptorium upgrade 2026-09-28 13:16:30 +00:00
e7f5e4753a Record the standalone Scriptorium upgrade for review 2026-09-28 03:52:37 +00:00
98abc1b905 Record completion of Scriptorium configuration interface 2026-09-28 03:50:16 +00:00
aa9338b135 Record completion of Scriptorium version adoption 2026-09-28 03:44:53 +00:00
5a8e3fccc9 Plan the standalone Scriptorium upgrade 2026-09-28 03:40:04 +00:00
3bc042ea22 Close out the Notarius testing overlay feature 2026-09-22 19:25:35 +00:00
47129b213d Record the Notarius testing overlay implementation for review 2026-09-22 19:01:09 +00:00
8cd642ffa6 Record the testing overlay collection snapshot 2026-09-22 18:57:31 +00:00
ad739671f6 Record the Notarius testing overlay implementation 2026-09-22 18:52:52 +00:00
0b2a45a327 Record the Notarius v0.7.1 role update 2026-09-22 18:36:23 +00:00
59b472d0a1 Record the Narratio profile selector implementation 2026-09-22 18:33:46 +00:00
38dfb0422c Plan the Notarius testing overlay implementation 2026-09-22 18:23:20 +00:00
58738e4efc Close out the D&D deployment playbook feature 2026-09-21 14:19:47 +00:00
a231b57294 Record D&D playbook preparation for review 2026-09-21 05:16:25 +00:00
1d1f34fc8b Limit the D&D feature to playbook preparation 2026-09-21 05:14:06 +00:00
f9901f17d1 Remove unnecessary deployment gates and record preparation 2026-09-21 05:04:47 +00:00
f8fe8dd0c6 Record role documentation compatibility blocker 2026-09-21 04:52:36 +00:00
e482ea4b01 Close storage review and begin host deployment 2026-09-21 04:48:54 +00:00
bbb7acc315 Separate local preparation from deployment prerequisites 2026-09-21 04:46:49 +00:00
d0c776b47e Record D&D deployment blockers 2026-09-21 04:37:52 +00:00
45599bb020 Prepare the D&D host deployment sprint 2026-09-21 04:31:36 +00:00
bb0f8cf84b Mark implementation handoff complete 2026-09-21 03:41:02 +00:00
76c10f79f5 Record D&D storage and publishing implementation 2026-09-21 03:40:52 +00:00
f399be34cd Mark pipeline collection import complete 2026-09-21 03:39:52 +00:00
2feb622937 Mark collection credential fixture complete 2026-09-21 03:36:37 +00:00
974b57e33e Mark D&D storage policy complete 2026-09-21 03:35:45 +00:00
a95a0ea280 Resume D&D storage and publishing plan 2026-09-21 03:20:03 +00:00
e262b61292 Plan D&D S3 storage and publishing 2026-09-21 02:20:57 +00:00
ec69f5a03b Mark operator enrollment handoff complete 2026-09-18 13:01:20 +00:00
bf81461de6 Record pipeline operator enrollment implementation 2026-09-18 13:01:07 +00:00
839b63a61e Mark collection operator enrollment import complete 2026-09-18 13:00:28 +00:00
3233bf6b9b Mark pipeline operator enrollment complete 2026-09-18 12:56:32 +00:00
a5bc701f60 Plan pipeline operator enrollment 2026-09-18 12:44:26 +00:00
eda361fa5d Complete the first suite release 2026-09-17 23:52:46 +00:00
06e1b35f25 Mark first suite release handoff complete 2026-09-17 20:08:24 +00:00
539c75cb18 Record the first suite release implementation 2026-09-17 20:08:09 +00:00
fc8f5709b0 Mark public release validation complete 2026-09-17 20:07:08 +00:00
0e0034ef02 Mark collection release published 2026-09-17 20:03:11 +00:00
40ca08a352 Mark collection release candidate complete 2026-09-17 19:20:26 +00:00
956c50cc2f Mark pipeline role release published 2026-09-17 19:16:27 +00:00
e24e8d0d05 Mark application role tags published 2026-09-17 18:57:34 +00:00
943ece7a65 Mark application role release validation complete 2026-09-17 18:56:42 +00:00
b98fb5783f Plan the first coordinated suite release 2026-09-17 18:44:56 +00:00
253d283234 Complete the D&D collection assembly 2026-09-17 14:24:03 +00:00
8f57e1bcf5 Mark Feature 0012 handoff complete 2026-09-17 03:46:56 +00:00
b359eee321 Record the Feature 0012 implementation 2026-09-17 03:46:47 +00:00
2b1448ab91 Mark collection integration testing complete 2026-09-17 03:46:10 +00:00
ec3c0b9706 Mark pipeline subtree import complete 2026-09-17 03:32:19 +00:00
1a81db660e Mark collection foundation stage complete 2026-09-17 03:30:14 +00:00
bc1cf31f0e Mark collection usage documentation complete 2026-09-17 03:28:59 +00:00
9a86cdb57e Plan the D&D collection assembly 2026-09-17 03:26:04 +00:00
54a2362c02 Close Feature 0011 after remediation 2026-09-16 21:37:17 +00:00
d2bd48cc99 Record the pipeline credential implementation 2026-09-16 20:06:35 +00:00
731a799873 Mark pipeline credential documentation stage complete 2026-09-16 20:06:05 +00:00
bbc8d25d64 Mark pipeline credential delivery stage complete 2026-09-16 19:51:05 +00:00
9b0949f2ac Mark Narratio upgrade stage complete 2026-09-16 19:24:46 +00:00
358051af98 Prepare the managed credential implementation sprint 2026-09-16 19:12:42 +00:00
6d9b4b87f8 Complete the D&D Notarius integration feature 2026-09-15 22:19:28 +00:00
7ac9220e87 Record the D&D Notarius integration implementation 2026-09-15 21:01:19 +00:00
7f8ce88b43 Record documentation and testing completion 2026-09-15 21:00:45 +00:00
5b2effd68a Record completion of the D&D pipeline integration 2026-09-15 20:49:10 +00:00
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
29 changed files with 5776 additions and 138 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,77 @@
# 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.
Narratio's general operational guidance recommends `0700` directories and
`0600` files for a single-user credential store. The suite deliberately grants
group read/traverse access instead: membership in the selected `narratio`
runtime group authorizes both pipeline execution and use of its shared provider
credentials. Deployments that do not trust every group member require a
different per-user credential policy and are outside this decision.
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,88 @@
# Application Upgrade Sequence
Decision agreed: 2026-09-28
## Purpose and Order
Adopt the newly released applications through focused, individually reviewed
features in this order:
**Scriptorium → Audita → Notarius → Narratio → suite integration.**
This document tracks the cross-feature direction, not implementation steps.
Each feature roadmap owns its scope and decisions. Only one staged plan is
active at a time, at [implementation.md](implementation.md).
## Version Baseline
These are the suite pins at the start of this upgrade, not assertions about
what is installed on an operational host. Targets are the releases reviewed
on the decision date; later releases require deliberate review.
| Application | Starting suite version | Adoption target |
| --- | --- | --- |
| Scriptorium | v0.13.0 | v0.15.0 |
| Audita | v0.9.1 | v2.0.1 |
| Notarius | v0.7.1 | v0.8.1 |
| Narratio | v2.2.0 | v3.0.0 |
Seriatim is unchanged by this sequence.
## Progress and Feature Links
Release-summary and migration-guidance triage is complete. Standalone
Scriptorium, Audita, Notarius, and Narratio adoption are complete after independent
review. Coordinated suite integration and its three review remediations are
complete. This upgrade sequence was closed on 2026-09-29; operational deployment
and a new tagged release remain separate activities.
- [x] [Feature 0018: Scriptorium adoption](features/0018-scriptorium-v0-15-adoption.md) — complete through role `b174c8c`; independent review found no remediation issues.
- [x] [Feature 0019: Audita adoption](features/0019-audita-v2-adoption.md) — complete through role `c3dd59f`; independent review found no remediation issues.
- [x] [Feature 0020: Notarius adoption](features/0020-notarius-v0-8-adoption.md) — complete through role `6aef48b`; independent review found no remediation issues; suite unchanged.
- [x] [Feature 0021: Narratio adoption](features/0021-narratio-v3-adoption.md) — complete through role `3c0700b`; independent review found no remediation issues; suite unchanged.
- [x] [Feature 0022: Coordinated suite integration](features/0022-coordinated-suite-upgrade.md) — complete with three review findings resolved at public pipeline `37b1cf6`, public collection `b3bc045`, and local consumer `15f0f4e`.
## Adoption Boundaries
Completing a standalone-role update does **not** advance the suite's application
or role dependency pins, collection snapshot, or deployment-repository pins.
Keep that existing compatibility set until the final integration feature
assembles and validates the coordinated configuration.
Standalone features own generic application interfaces. The integration feature
owns D&D defaults, cross-application configuration, testing overlays, credential
references, compatible dependency pins, and consumer upgrade guidance. Each
feature follows roadmap → staged plan → implementation → review → closeout.
No operational deployment is authorized merely by this sequencing decision.
## Compatibility Constraints to Carry Forward
- **Scriptorium is not a documentation-only upgrade from our baseline.** The
intervening v0.14.0 introduces ConfigKit and changes configuration acceptance,
selection, and retry behavior. Review those changes as well as v0.15.0's
licensing and dependency updates.
- **Audita and Narratio need a coordinated suite cutover.** Audita v2 requires
migrated configuration; Narratio v3 expects that interface and no longer owns
the retired downstream settings or generated Audita configuration.
- **Overlay terminology changes on both sides of the Notarius boundary.**
Narratio's selector and the suite-managed downstream files must migrate
together. Preserve explicit selection and independent application ownership.
- **Existing Narratio manifests need operator migration guidance.** Carry the
upstream provenance-field migration into final integration planning. Preserve
session progress; do not infer a requirement to delete checkpoints, force all
stages, edit immutable remote snapshots, or automate the migration.
- **Review retry and timeout semantics explicitly.** New transport retry and
repair behavior is not necessarily equivalent to the previous settings.
Preserve user intent without copying old values mechanically or inventing
new suite policy.
The upstream documentation remains authoritative for exact fields and migration
procedures:
- [Scriptorium v0.14.0](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.14.0/docs/releases/v0.14.0.md)
and [v0.15.0](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.15.0/docs/releases/v0.15.0.md).
- [Audita v2 migration](https://gitea.maximumdirect.net/eric/audita/src/tag/v2.0.1/docs/migrations/v2.md).
- [Notarius v0.8.0](https://gitea.maximumdirect.net/eric/notarius/src/tag/v0.8.0/docs/releases/v0.8.0.md)
and [v0.8.1](https://gitea.maximumdirect.net/eric/notarius/src/tag/v0.8.1/docs/releases/v0.8.1.md).
- [Narratio v3.0.0](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/releases/v3.0.0.md)
and [migration procedures](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/operations.md#migrating-manifest-overlay-provenance).

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: done
## 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

@@ -0,0 +1,389 @@
# Feature 0011: Managed Pipeline Credentials and Notarius Reuse
Status: done
## Summary
Upgrade the generic Narratio role and D&D pipeline to Narratio v2.1.0, manage
provider credentials through Narratio's conventional ConfigKit secrets
directory, and use the release's typed Notarius credential and checkpoint-reuse
controls. Credential values remain outside ordinary application YAML and are
readable only by the selected runtime user and group. Ordinary pipeline runs
reuse compatible Notarius checkpoints, while forced extraction retains
Narratio's native refresh behavior.
## Problem or Opportunity
The pipeline role currently writes credential reference names but manages no
credential values. A caller must prepare the invoking environment through an
external mechanism before a real run can reach the selected model providers.
The installed Narratio v2.0.0 release also cannot forward a selected provider
credential to Notarius. Its Notarius child receives a restricted environment,
and the v2.0 configuration contract exposes no typed credential field. The
pipeline records Notarius checkpoints but cannot ask Notarius to reuse them.
Narratio v2.1.0, immutable tag `v2.1.0` at `c45e042`, resolves both application
contract gaps. It adds optional `notarius.llm_api_key`, `notarius.resume`, and
`notarius.chunk_cache` fields without requiring migration of existing v2
configuration. The credential field resolves through the existing process
environment or secrets-directory bootstrap, forwards only the exact selected
name and value, and participates in the application's existing redaction
boundary. Ordinary extraction may request checkpoint reuse; forced extraction
omits resume and refreshes the active chunk plan.
The suite separately configures Audita proposal and validation with different
environment names even though both use the same endpoint and model. Narratio's
Audita boundary accepts one typed credential. This feature therefore
coordinates both suite-default Audita sections on `AUDITA_LLM_API_KEY` while
retaining their existing independently overrideable variables.
## Governing Policies
- [The Ansible house style](../../ansible.md) governs the direct desired-state
implementation, native configuration interface, and ordinary module
convergence.
- [The testing house style](../../testing.md) governs synthetic, native,
behavior-oriented validation without live provider calls or filesystem
metadata assertions.
- [The MVP roadmap](../mvp.md) assigns pipeline-wide secret delivery,
application-version coordination, and cache policy to the suite role.
- [Decision 0002](../../decisions/0002-shared-readable-pipeline-filesystem-policy.md)
defines the selected runtime group as the authorization boundary and fixes
`0750` directory and `0640` file modes for shared credential material.
- [Feature 0009](0009-shared-pipeline-filesystem-and-execution.md) establishes
the service-user and existing-group-member invocation model.
- [Feature 0010](0010-dnd-notarius-extraction-integration.md) establishes the
Notarius pipeline, FHS cache roots, automatic chunk-plan reuse, and checkpoint
recording extended by this feature.
- Narratio's immutable v2.1.0 release documentation and current configuration
and Notarius integration references are authoritative for the application
fields, resolution semantics, forced-run behavior, and redaction contract.
## Scope
- Advance the standalone Narratio role's selected application release from
v2.0.0 to v2.1.0 without changing its established source-build task flow.
- Expose the three new native optional fields through nullable, field-specific
role variables: `narratio_notarius_llm_api_key`,
`narratio_notarius_resume`, and `narratio_notarius_chunk_cache`.
- Keep the standalone role generic. All three variables default to null and
are omitted unless a caller selects them, leaving Narratio's native defaults
in control.
- Advance the pipeline role's compatible Narratio application version to
v2.1.0 and pin its Narratio role dependency to the reviewed revision that
provides the new interface.
- Use `/usr/local/etc/narratio/secrets`, the conventional directory adjacent
to `/usr/local/etc/narratio/pipeline.yml`, as the suite's sole managed
credential location.
- Create that directory as the selected pipeline runtime user and group with
mode `0750`.
- Add one public `dnd_pipeline_secrets` mapping from environment-variable names
to string file contents. Each supplied entry means that the named credential
file must be present with that content; an omitted key is unmanaged.
- Default `dnd_pipeline_secrets` to an empty mapping so the role never invents
credentials and remains usable with externally prepared process environment
values.
- Validate selected keys as environment-variable names and values as strings
before constructing a destination path.
- Write supplied credential files as the selected runtime user and group with
mode `0640`.
- Suppress credential values from Ansible task output during validation,
creation, and updates.
- Keep ordinary application configuration limited to non-secret credential
reference names.
- Coordinate Audita proposal and validation on the suite-default
`AUDITA_LLM_API_KEY` name and pass that name through the standalone Narratio
role's existing `narratio_audita_llm_api_key` interface.
- Add `dnd_pipeline_narratio_notarius_llm_api_key`, default it to
`OPENROUTER_API_KEY` for Notarius's selected production profile, and pass it
through Narratio's typed Notarius credential field.
- Add `dnd_pipeline_narratio_notarius_resume`, default it to true, and pass it
through Narratio so ordinary extraction requests reuse of the checkpoints
already recorded by the suite's Notarius configuration.
- Expose Narratio's native `notarius.chunk_cache` in the standalone role but do
not duplicate it behind a suite variable or set it from the pipeline role.
The suite already configures Notarius's ordinary chunk-plan mode as `auto`;
Narratio v2.1.0 independently owns its forced-extraction refresh override.
- Preserve Scriptorium's application-owned `api_key_env` profile selection.
Narratio's secrets bootstrap supplies the selected environment value and the
existing Scriptorium adapter passes that named credential to its child.
- Document the mapping interface, Ansible Vault inventory pattern, process
environment precedence, shared-group authorization boundary, application
credential flow, and checkpoint-reuse policy.
- Add focused integration coverage using distinctive synthetic values and
native Narratio configuration loading. No default test contacts a model
provider.
## Non-goals
- Storing raw credentials in Narratio, Audita, Notarius, or Scriptorium YAML.
- Providing real credentials, unencrypted example values, or a default secret
mapping.
- Implementing Ansible Vault, choosing a vault password mechanism, or requiring
one specific inventory encryption workflow.
- Integrating an external secret manager, cloud vault, hardware-backed key
store, or dynamic credential broker.
- Making the pipeline role authoritative for files omitted from
`dnd_pipeline_secrets`, purging the whole directory, or recursively changing
pre-existing content.
- Adding a launcher script, shell profile, environment file, systemd unit,
scheduler, or persistent service merely to inject credentials.
- Passing arbitrary caller-defined environment variables through Narratio's
subprocess boundary.
- Managing human accounts or their membership in the runtime group.
- Running Audita, Notarius, or Scriptorium against a live endpoint during the
default integration suites.
- Testing Notarius checkpoint reuse end to end in the Ansible role. Narratio
and Notarius own that behavior; the role validates the selected native
configuration and immediate Ansible convergence.
- Setting Narratio's optional `notarius.chunk_cache` field redundantly when
the deployed Notarius configuration already selects `auto`.
- Changing Narratio's native forced-extraction refresh policy.
- Rotating credentials, retaining prior values, validating provider
authorization, or recovering deliberately corrupted secret files.
- Adding storage or publishing credentials before the suite selects a storage
or publishing feature.
- Modifying any upstream application source.
## Target End State
The standalone Narratio role installs v2.1.0 by default and can render all
three new Notarius fields when a caller supplies them. It owns no credential
files and selects no D&D-specific credential or cache policy.
The pipeline role owns this conventional restricted subtree:
```text
/usr/local/etc/narratio/
├── pipeline.yml
└── secrets/ narratio:narratio 0750
├── AUDITA_LLM_API_KEY narratio:narratio 0640
└── OPENROUTER_API_KEY narratio:narratio 0640
```
The filenames are suite-selected reference names, never credential values.
The selected runtime user and group remain configurable through the existing
pipeline interface.
A consumer may keep encrypted values in inventory without embedding any value
in ordinary configuration:
```yaml
dnd_pipeline_secrets:
AUDITA_LLM_API_KEY: "{{ vault_dnd_audita_llm_api_key }}"
OPENROUTER_API_KEY: "{{ vault_dnd_openrouter_api_key }}"
```
The role owns only the supplied named entries for this invocation and leaves
every omitted name alone. The actual `vault_dnd_*` values belong in encrypted
inventory and must not appear in examples, plans, test logs, commits, or
ordinary generated configuration.
When Narratio runs without `--secrets-dir`, it discovers the sibling directory
and loads its immediate regular files before resolving the pipeline. An
already-set process environment value wins over the corresponding file. The
base and `testing` profiles use the same delivery mechanism; profiles select
models and application profiles, not a second credential store.
The suite deliberately uses `narratio:narratio`, directory mode `0750`, and
file mode `0640` rather than Narratio's general single-user recommendation of
`0700` and `0600`. Membership in the selected runtime group is an explicit
authorization to invoke this pipeline with its shared provider credentials.
No world access is granted. Deployments that do not trust every group member
must use separate process-environment or `--secrets-dir` provisioning and are
outside this shared-operator policy.
Audita's proposal and validation configuration both reference
`AUDITA_LLM_API_KEY` by default. Narratio resolves that typed reference and
passes the value explicitly to the Audita child. Callers may still override
the existing Audita reference variables, but a custom split-key design also
requires an application boundary capable of forwarding both values and is not
promised by this feature.
Narratio's effective Notarius configuration names `OPENROUTER_API_KEY`, or a
caller-selected replacement, through `notarius.llm_api_key`. Narratio resolves
the named secret and forwards only that exact name and value to Notarius. It
does not infer a provider from Notarius configuration or forward unrelated
credentials.
Ordinary extraction sets `notarius.resume: true`. Notarius continues to own
checkpoint recording, identity, and storage beneath the configured
`/var/cache/notarius/checkpoints` root. Narratio requests reuse but does not
inspect the cache. The pipeline leaves Narratio's `notarius.chunk_cache` field
unset because the Notarius root configuration already selects `auto` at the
native owner. Forced extraction follows Narratio v2.1.0 behavior: resume is
omitted and the active chunk plan is refreshed without deleting unrelated
cache content.
Scriptorium continues to select credential names through its PromptKit
profiles. The Narratio process receives those names from the secret bootstrap,
and its existing adapter forwards the selected profile credential.
## Repository Ownership
- `../narratio` at immutable tag `v2.1.0` is the read-only application
authority for secrets bootstrap, typed Notarius credential forwarding,
checkpoint reuse, forced refresh, and subprocess redaction.
- `ansible-role-narratio` advances the application release and exposes the
three native Notarius fields through its generic field-specific interface.
It does not manage secret files or select suite policy.
- `ansible-role-dnd-pipeline` owns the conventional secrets directory, managed
credential mapping, suite-level Audita and Notarius reference coordination,
checkpoint-reuse selection, consumer documentation, and behavioral tests.
- `ansible-workspace-dnd` owns this roadmap, the settled MVP policy, progress,
and independent review record.
- The Audita, Notarius, and Scriptorium application roles remain unchanged;
they continue to own only their native configuration interfaces.
- The collection, asset, remaining application, and reference repositories
remain unchanged.
## Constraints and Settled Decisions
- Raw credential bytes never enter ordinary application YAML, Git-tracked
examples, workspace plans, or committed test fixtures.
- The role manages secret values only through `ansible.builtin.copy` content
or an equally direct secret-safe module operation with `no_log: true`.
- The conventional directory path is fixed because automatic Narratio
discovery depends on its relationship to the fixed root pipeline document.
- Credential filenames must match the environment-variable grammar accepted
by ConfigKit. Validation exists to prevent a caller-controlled key from
becoming a path outside the secrets directory.
- Credential values are written as supplied strings. ConfigKit and the typed
application reference own any nonempty-value requirement when a credential
is selected for use.
- An omitted mapping key is outside the role's ownership. Exact-directory
mirroring and deletion of unlisted files are intentionally excluded.
- The shared runtime group is an authorization group. Its members may read the
managed credentials; all other local users are denied access.
- The suite's group-readable credential policy deliberately differs from
Narratio's general single-user mode recommendation. ConfigKit does not
enforce those recommended modes, and the selected policy grants no world
access.
- Application adapters, rather than Ansible, own the secure transfer of loaded
values to child processes. Ansible does not create wrappers or reconstruct
the subprocess environment.
- Notarius's root configuration remains the single owner of ordinary
chunk-plan mode. Narratio's native `resume` field expresses the distinct
request to load compatible recorded checkpoints.
- Production convergence performs no provider call, credential validity test,
cache probe, content checksum bookkeeping, backup, or post-write reread.
## Simplest Viable Implementation Shape
The standalone Narratio role needs only a release update and three nullable
field-specific variables rendered through its existing template. It remains
generic and does not own credential files or suite policy.
The pipeline role needs one empty credential mapping, two Narratio Notarius
policy variables, coordinated Audita reference defaults, and ordinary
dependency wiring. Credential convergence consists of one directory task, one
validation loop, and one copy loop for supplied entries. Both secret-bearing
loops suppress their output.
Documentation and focused native integration coverage complete the public
interface. No state probe, handler, template assembly, manifest, wrapper,
directory scan, or role-private bookkeeping is required. The validation loop
is deliberate: the mapping key becomes a filesystem path, so rejecting
anything other than a valid environment-variable name protects the declared
destination boundary.
## Rationale and Alternatives
Narratio's native ConfigKit bootstrap is preferable to a shell wrapper or
service-specific environment file because every pipeline-loading command uses
the same application-owned behavior, whether invoked by the service account or
an authorized human operator. It also preserves the application's existing
environment-precedence and redaction rules.
A mapping is more ergonomic for inventory than a list of file objects because
the native identity of each entry is already its environment-variable name.
Omitted files remain unmanaged so consumers can combine Ansible-managed
credentials with another provisioning mechanism. Credential removal and
directory mirroring remain outside this feature until an operator-facing
lifecycle requirement is expressly selected.
Per-user `0700` directories would follow Narratio's general recommendation but
would require separate keys or an additional invocation convention for every
authorized human. The selected shared group already defines who may execute
the suite with shared state, so group-readable and world-inaccessible
credentials provide the intended operational model with less duplication.
Selecting Narratio checkpoint reuse completes the suite's earlier decision to
enable every available Notarius cache. Duplicating `chunk_cache: auto` in both
Narratio and Notarius configuration would add no ordinary behavior, so the
pipeline leaves the optional Narratio override unset and relies on each
application's documented ownership boundary.
## Acceptance Criteria
- The standalone Narratio role installs an explicitly selected v2.1.0 and can
render representative non-null and falsey values for
`narratio_notarius_llm_api_key`, `narratio_notarius_resume`, and
`narratio_notarius_chunk_cache` while omitting null values.
- The pipeline role selects Narratio v2.1.0 and pins the reviewed standalone
role revision that provides its native fields.
- The pipeline role creates `/usr/local/etc/narratio/secrets` with the selected
runtime ownership and suite credential-directory mode.
- `dnd_pipeline_secrets` defaults to an empty mapping and accepts valid
environment names with string values.
- Invalid names and non-string values fail before any destination outside the
declared secret directory can be constructed.
- Supplied entries converge to regular files with the selected runtime
ownership and mode `0640`; omitted names remain unmanaged.
- Credential values are suppressed from Ansible output and never appear in
application YAML, generated examples, native effective-configuration output,
test logs, or committed fixtures.
- Audita proposal and validation use `AUDITA_LLM_API_KEY` by default, and
Narratio's typed Audita field names that reference so the adapter explicitly
supplies the loaded value.
- Narratio's effective pipeline selects `OPENROUTER_API_KEY` through the typed
Notarius field and selects checkpoint resume for ordinary extraction.
- Narratio's optional chunk-cache override remains absent from the suite
configuration while Notarius's effective root configuration continues to
select `auto`.
- Scriptorium continues to receive the credential named by its selected
profile through the existing adapter behavior.
- A synthetic pipeline integration invocation with the relevant ambient
variables unset loads credentials through the conventional directory and
succeeds at native offline configuration validation as the service account
and one existing-group-member fixture.
- A distinctive synthetic secret never appears in captured integration output.
- The baseline credential application reports `changed=0` and `failed=0` on
an immediate identical repeat.
- Syntax checking, production-profile lint, and the complete standalone
Narratio and pipeline integration entry points pass.
- No live provider, WhisperX service, storage backend, model call, or
application cache execution occurs in default tests.
## Dependencies and Follow-up Work
- Features 0005, 0006, 0008, 0009, and 0010 are complete prerequisites.
- Narratio v2.1.0 at immutable tag `c45e042` satisfies the former typed
Notarius credential and cache-control prerequisite.
- The completed upstream feature request was removed from Narratio's active
roadmap during its v2.1.0 release cleanup; the release reference now owns the
delivered behavior.
- The standalone Narratio-role commit produced by this feature must be
available from its canonical Git origin before the pipeline's isolated
dependency test can use it.
- Collection assembly should follow this feature so the first assembled
collection packages a pipeline with complete credential delivery and cache
reuse.
- Storage and publishing policy may later add S3 or other credential reference
names to consumer inventory without changing the file-delivery mechanism.
- Operator selection, group-membership management, services, scheduling,
upgrades, removal, and external secret-manager integration remain separate
features.
## Potential Future Hardening
- Integrate a dedicated external secret manager or short-lived credential
broker.
- Support distinct per-operator secret directories for deployments that do
not treat runtime-group membership as shared credential authorization.
- Add explicit credential rotation orchestration and provider-side validity
checks.
- Add an explicit credential-removal or directory-lifecycle contract if an
operator need is identified.
- Add platform-specific mandatory-access-control policy for credential files.

View File

@@ -0,0 +1,304 @@
# Feature 0012: Assemble the D&D Collection
Status: done
## Summary
Turn the existing `ansible-collection-dnd` repository into a valid, buildable
`rakestraw.dnd` Ansible collection that exposes the independently developed
pipeline role as `rakestraw.dnd.pipeline`. The collection will carry a
self-contained snapshot of the pipeline role, publish the collection
dependencies Ansible can resolve natively, and provide one consumer bootstrap
manifest for the five Git-hosted application roles.
## Problem or Opportunity
The standalone application roles and the opinionated pipeline role are now
implemented and independently tested, but the collection repository still
contains only a placeholder README and repository metadata. A consumer cannot
build or install `rakestraw.dnd`, invoke the intended fully qualified role
name, or reproduce the reviewed combination of application-role dependencies
from that repository.
The pipeline role must remain independently developed, versioned, and usable.
At the same time, the collection artifact must contain the role it advertises;
it cannot depend on a sibling checkout, a symbolic link, or workspace-only
tooling at runtime. The assembly boundary therefore needs an explicit,
repeatable source-import convention and focused integration coverage of the
packaged result.
## Governing Policies
- [The Ansible house style](../../ansible.md) governs collection metadata,
dependency declarations, documentation, and the preference for native
Ansible packaging behavior.
- [The testing house style](../../testing.md) governs behavior-oriented,
state-based validation and the avoidance of tests that merely restate file
layout or implementation details.
- [The MVP roadmap](../mvp.md) establishes the collection name, independently
released role repositories, Git-hosted application-role dependencies, and
the collection as the compatibility record for an assembled release.
- Features [0006](0006-pipeline-role-composition-foundation.md) through
[0011](0011-managed-pipeline-credential-delivery.md) define the pipeline
role behavior being assembled; this feature does not reopen those contracts.
## Scope
- Add valid Ansible Galaxy metadata for collection namespace `rakestraw`, name
`dnd`, development version `0.1.0`, the repository's existing license and
README, and its supported Ansible version.
- Declare the exact `ansible.posix` and `community.general` versions already
selected by the pipeline role as collection dependencies.
- Import the complete standalone pipeline-role repository into
`roles/pipeline` as a squashed Git subtree at an explicitly reviewed commit.
- Treat `ansible-role-dnd-pipeline` as authoritative: changes are made and
reviewed there first, then deliberately imported into the collection. Do
not edit role behavior directly beneath the collection's subtree prefix.
- Document the initial subtree import and subsequent update commands so the
source relationship is reproducible without custom tooling or private
knowledge.
- Ensure the standalone pipeline role's collection-facing documentation
distinguishes its standalone role name and invocation from
`rakestraw.dnd.pipeline` use without changing its public behavior.
- Add `meta/runtime.yml` with `requires_ansible: ">=2.18.0"`, matching the
implemented roles' supported baseline.
- Add one root `requirements.yml` that combines the five Git-hosted
application-role dependencies with the two collection dependencies needed
to bootstrap the assembled suite.
- Pin application roles to the exact reviewed commits already selected by the
standalone pipeline role during development. Keep the root bootstrap
manifest and the imported role's dependency manifests consistent.
- Configure collection builds to omit development-only content embedded in the
role subtree, including its integration suite, local Ansible configuration,
and nested dependency manifests. Retain operator-facing role documentation
and licensing in the source collection unless Ansible packaging requires
otherwise.
- Replace the collection's placeholder README with concise instructions for
dependency bootstrap, collection build and installation, FQCN invocation,
subtree provenance and updates, supported platform, and the distinction
between development commit pins and future released role tags.
- Add a focused collection integration suite that starts with isolated role
and collection paths, installs the root bootstrap manifest and the locally
built collection artifact, invokes `rakestraw.dnd.pipeline`, validates the
assembled pipeline through the applications' native configuration
interfaces, and verifies an immediate second application converges with no
reported changes.
## Non-goals
- Publishing the collection to Ansible Galaxy, Automation Hub, Gitea, or any
other registry.
- Creating the first collection release tag or application-role release tags.
- Replacing development commit pins with immutable role tags before those tags
exist.
- Vendoring any of the five standalone application roles into the collection.
- Moving authoritative pipeline-role development into the collection
repository or permitting collection-local role forks.
- Changing pipeline defaults, host convergence, application versions,
application configuration, asset deployment, credentials, or runtime
behavior.
- Adding collection plugins, modules, filters, playbooks, execution
environments, CI workflows, release automation, or a general-purpose sync
framework.
- Repeating every standalone pipeline integration scenario inside the
collection suite or asserting the exact contents of metadata and manifests
as an implementation snapshot.
- Supporting installation without network access. The collection artifact is
self-contained for the pipeline role, but its declared external role and
collection dependencies must still be made available to Ansible.
## Target End State
The collection repository has this durable shape:
```text
ansible-collection-dnd/
├── galaxy.yml
├── meta/
│ └── runtime.yml
├── requirements.yml
├── roles/
│ └── pipeline/ imported pipeline-role subtree
├── tests/
│ ├── converge.yml
│ ├── integration assembled-artifact behavior test
│ └── inventory
├── LICENSE
└── README.md
```
`ansible-galaxy collection build` produces a valid
`rakestraw-dnd-0.1.0.tar.gz` artifact. After the documented bootstrap installs
the root dependency manifest and the built artifact into clean Ansible paths,
a consumer can invoke:
```yaml
- name: Install and configure the D&D transcript pipeline
hosts: pipeline_hosts
roles:
- role: rakestraw.dnd.pipeline
```
The collection contains ordinary role files at `roles/pipeline`; it has no
runtime link to the standalone repository. Git history records that directory
as a squashed subtree import from `ansible-role-dnd-pipeline`. Maintainers make
pipeline changes in the standalone repository, validate and commit them there,
then update the collection subtree from the desired reviewed commit.
The root bootstrap manifest is the consumer-facing compatibility manifest for
development. It contains the same five application-role sources and reviewed
commit pins as the imported pipeline role, plus exact versions of
`ansible.posix` and `community.general`. The collection's Galaxy metadata also
declares those two collection dependencies because Ansible can resolve them as
native collection dependencies. This intentional duplication serves two
different installation boundaries and must remain consistent.
Development-only files may remain in the subtree source for faithful
provenance, but they are excluded from the built artifact. The collection's
own integration suite exercises the artifact rather than the repository role
directory, with role and collection paths isolated from ordinary user
installations.
## Repository Ownership
- `ansible-collection-dnd` owns collection metadata, the consumer bootstrap
manifest, the imported pipeline snapshot, collection-facing documentation,
build exclusions, and assembled-artifact integration coverage.
- `ansible-role-dnd-pipeline` remains authoritative for all pipeline-role code,
defaults, templates, dependency metadata, standalone documentation, and its
comprehensive integration suite. This feature changes only the wording
needed to document both standalone and collection use.
- The five standalone application-role repositories remain authoritative for
their roles and are read-only inputs to this feature.
- `campaigns` and `narratio-prompts` remain independently managed asset
repositories and are read-only integration inputs.
- `ansible-workspace-dnd` owns this feature roadmap, progress tracking, and the
later independent review record.
- Application source repositories and `rakestraw-ansible` remain unchanged.
## Constraints and Settled Decisions
- The collection is `rakestraw.dnd`; the bundled role's FQCN is
`rakestraw.dnd.pipeline`.
- A squashed Git subtree is the selected incorporation mechanism. It yields a
normal, self-contained collection artifact while preserving an auditable
upstream relationship and avoiding submodule checkout requirements,
symbolic links, manual copying, or custom synchronization state.
- The subtree prefix is `roles/pipeline`, and the standalone pipeline
repository remains the only place where role behavior is authored.
- The first development build uses collection version `0.1.0`. This version
enables ordinary Galaxy build and install validation but does not itself
authorize publication or establish a release tag.
- Development dependencies use exact reviewed commits. A later release pass
must replace all application-role commit pins with immutable role release
tags and revalidate the assembled artifact before publishing.
- Collection dependencies remain exactly `ansible.posix` 2.2.0 and
`community.general` 13.3.0, matching the existing reviewed pipeline
manifests.
- Galaxy metadata cannot install arbitrary standalone Git roles. The root
unified requirements manifest and documented bootstrap are therefore part
of the collection's public installation contract.
- The collection integration suite must not receive dependencies from the
developer's normal Ansible paths. Its success must demonstrate that the
documented manifest and built artifact are sufficient.
- The collection suite owns only the packaging boundary: buildability,
dependency bootstrap, FQCN resolution, representative assembled behavior,
native configuration acceptance, and convergence. Detailed pipeline feature
matrices remain in the standalone role's tests.
- The collection does not add probes, manifests, checksums, copied-file
comparisons, or private state to police the subtree. Git and the documented
subtree workflow are the provenance mechanism.
## Simplest Viable Implementation
Use Ansible's conventional collection layout and metadata directly. Import the
reviewed pipeline repository with ordinary `git subtree add --squash`, then
exclude only the subtree's development fixtures and nested bootstrap files
from Galaxy builds. No wrapper role, generated role, symbolic link, submodule,
or synchronization script is required.
Derive the root unified dependency manifest directly from the pipeline role's
two existing manifests. The only deliberate duplication is the collection
dependency declaration in `galaxy.yml`, because the artifact and the source
bootstrap have distinct native Ansible dependency interfaces.
Use one representative integration path: build into a temporary directory,
install dependencies and the artifact into isolated temporary Ansible paths,
apply `rakestraw.dnd.pipeline` using the same offline synthetic inputs already
proven by the standalone suite, run native application configuration
validation, and apply the play a second time to assert `changed=0` and
`failed=0`. This tests the behavior unique to collection assembly without
duplicating the standalone role's full test matrix.
## Rationale and Alternatives
A squashed subtree is preferable to a Git submodule because Ansible collection
archives require real role content and should build correctly from an ordinary
checkout without a second initialization step. It is preferable to a symbolic
link because archive behavior and installed collection paths would be fragile.
It is preferable to an unrecorded copy because subtree history retains the
source relationship and provides a standard update command. Squashing avoids
injecting the pipeline repository's entire development history into the
collection while still recording each reviewed import.
Moving the role permanently into the collection would simplify assembly, but
would discard the settled requirement that the suite role remain independently
developed, tested, versioned, and usable. A thin collection wrapper that
depends on `rakestraw.dnd_pipeline` would avoid source import but would not
actually bundle the role or satisfy the desired FQCN without adding another
runtime dependency layer.
Keeping one unified root requirements file gives consumers one bootstrap
command for both dependency kinds. Retaining the imported role's own
requirements files in source preserves standalone repository fidelity; build
exclusion prevents those nested development interfaces from confusing users
of the installed artifact.
## Acceptance Criteria
- The collection repository is recognized by `ansible-galaxy` as
`rakestraw.dnd` version `0.1.0` and builds successfully from a clean checkout.
- The built archive contains `roles/pipeline` and excludes the imported role's
development-only integration suite, local Ansible configuration, and nested
dependency manifests.
- The role content at `roles/pipeline` is traceable to a documented reviewed
commit of `ansible-role-dnd-pipeline` through the repository's squashed
subtree history.
- The standalone pipeline README accurately documents both
`rakestraw.dnd_pipeline` and `rakestraw.dnd.pipeline` consumption without
changing role behavior.
- `meta/runtime.yml` selects Ansible 2.18 or newer, and Galaxy metadata declares
the exact two collection dependencies used by the pipeline.
- The root bootstrap manifest contains all five standalone application roles
at the same reviewed commits used by the imported pipeline role and the
exact two required collections.
- Collection documentation provides sufficient commands to install the
bootstrap dependencies, build and install the artifact, invoke the pipeline
FQCN, and update the subtree from a future reviewed pipeline commit.
- The integration suite starts with isolated Ansible role and collection
paths, installs only the declared bootstrap inputs and built artifact, and
resolves `rakestraw.dnd.pipeline` without access to a sibling role checkout.
- The representative assembled deployment passes the applications' native
configuration validation and an immediate identical second run reports
`changed=0` and `failed=0`.
- Existing standalone pipeline-role validation continues to pass after its
documentation-only change.
- No application role, application source, asset behavior, or pipeline host
convergence behavior changes as part of this feature.
## Dependencies and Follow-up Work
- Features 0001 through 0011 and their reviewed role commits are prerequisites.
- A subsequent release feature must create immutable role tags, replace
development commit pins, select the release collection version, validate the
tagged combination, create release notes and tags, and publish or distribute
the artifact.
- CI automation may later run the collection integration suite after a local,
repeatable workflow exists.
## Potential Future Hardening
- Sign collection artifacts or publish checksums and software bills of
materials when a distribution threat model requires them.
- Automate subtree provenance checks and dependency-pin synchronization if
manual collection updates become frequent enough to justify that machinery.

View File

@@ -0,0 +1,285 @@
# Feature 0013: Publish the First Coordinated Suite Release
Status: done
## Summary
Publish the reviewed D&D pipeline as the first immutable, remotely installable
release of its five application roles, standalone pipeline role, and
`rakestraw.dnd` collection. The release establishes `v0.1.0` tags in the
projects' public Gitea repositories, replaces development commit pins with
those role tags, and makes the built `rakestraw-dnd-0.1.0.tar.gz` collection
artifact available from the collection's Gitea release.
## Problem or Opportunity
The application roles, pipeline role, and collection have been implemented,
reviewed, and tested as one compatible suite. Their current dependency
manifests still select application roles by development commit, however, and
none of the seven Ansible repositories has an immutable release tag. The
collection documentation consequently describes a development build rather
than a published release, and a consumer cannot bootstrap the reviewed suite
entirely from named releases and a published collection artifact.
The initial release should turn the existing reviewed compatibility set into a
durable public installation boundary without changing application behavior or
introducing release automation. It must prove that the release is consumable
from Gitea alone rather than from sibling repositories or unpublished local
artifacts.
## Governing Policies
- [The Ansible house style](../../ansible.md) governs dependency manifests,
collection packaging, and concise consumer documentation.
- [The testing house style](../../testing.md) governs release validation. The
feature reuses behavior-oriented repository suites and adds only validation
specific to the remote publication boundary.
- [The planning policy](../../planning.md) governs the cross-repository
implementation and review workflow.
- [The MVP roadmap](../mvp.md) defines independent role releases, immutable
release pins, the collection as the compatibility record, and public Gitea
as the release source.
- [Feature 0012](0012-collection-assembly.md) defines the authoritative
pipeline subtree, unified consumer manifest, and assembled-artifact testing
boundary that this feature releases without redesigning.
## Scope
- Publish `v0.1.0` as the initial release of each standalone application role:
`rakestraw.audita`, `rakestraw.narratio`, `rakestraw.notarius`,
`rakestraw.seriatim`, and `rakestraw.scriptorium`.
- Point those application-role tags at the exact reviewed commits already
selected by the pipeline compatibility manifest. No application-role code
or default changes are part of release preparation.
- Replace the five development commit pins in the authoritative pipeline
role's root dependency manifest with the corresponding immutable `v0.1.0`
role tags.
- Update the pipeline documentation to describe the released dependency pins
and its standalone installation path without changing its role interface or
runtime behavior.
- Validate and publish `v0.1.0` of the standalone pipeline role after its
release manifest and documentation are complete.
- Import the published pipeline `v0.1.0` state into the collection's
`roles/pipeline` subtree using the established remote-only, squashed subtree
workflow.
- Replace the collection's five application-role commit pins with the same
`v0.1.0` tags used by the authoritative pipeline role, retaining the exact
`ansible.posix` and `community.general` version pins already selected.
- Retain collection version `0.1.0` in `galaxy.yml`, update collection
documentation from development-build language to released installation
instructions, and identify the release as the compatibility record for the
seven selected component versions.
- Create and push public, immutable `v0.1.0` tags for all seven Ansible
repositories.
- Build `rakestraw-dnd-0.1.0.tar.gz` from the tagged collection content and
create a concise public Gitea `v0.1.0` collection release whose attachment
is that exact artifact.
- Validate that a clean consumer can obtain the tag-pinned dependency manifest
and collection archive from their public Gitea URLs, install them into
isolated Ansible paths, invoke `rakestraw.dnd.pipeline`, and obtain an
immediate clean repeat.
- Record the completed release and its immutable compatibility set in the
workspace status and durable release-facing documentation.
## Non-goals
- Changing application versions, role defaults, pipeline configuration,
filesystem policy, credentials, assets, or deployed runtime behavior.
- Synchronizing future versions of independently released roles. The shared
initial version is a convenient baseline, not a lockstep release policy.
- Publishing the collection to Ansible Galaxy, Automation Hub, or another
package registry.
- Vendoring the five application roles into the collection or changing the
selected pipeline subtree model.
- Adding CI/CD, a release script, a changelog generator, dependency-update
automation, or a general-purpose release framework.
- Adding tests that snapshot manifest text, tag names, defaults, task traces,
or other implementation details. Release validation should exercise the
public installation and deployed behavior.
- Signing tags or artifacts, generating checksums or software bills of
materials, mirroring dependencies, or adding other supply-chain hardening.
- Defining upgrade, downgrade, removal, scheduling, or optional human-operator
account management.
## Target End State
Each public application-role repository has an immutable `v0.1.0` tag for the
exact role revision already reviewed as part of the assembled suite:
| Role | Released revision |
| --- | --- |
| `rakestraw.audita` | `66ebea9a47ce82bfdbdc5e2855f3dfaaff8e2a16` |
| `rakestraw.narratio` | `292d8669e7aad5cfe80b0c469d22b6177e8cf0f1` |
| `rakestraw.notarius` | `14a38e04e35ef524d6a97fa7fb5a04981a0a2161` |
| `rakestraw.seriatim` | `e08c63c0b078658bdfa2d10a2e6e1e4f9372a075` |
| `rakestraw.scriptorium` | `8b4c86e48e7d8655e479b26dc510bf01683a0c8f` |
The standalone pipeline role has its own immutable public `v0.1.0` tag. Its
role dependency manifest selects all five application roles with
`version: v0.1.0`, and its collection dependency manifest retains
`ansible.posix` 2.2.0 and `community.general` 13.3.0. The pipeline release is
independently installable under `rakestraw.dnd_pipeline`.
The collection's `roles/pipeline` subtree is a faithful squashed import of the
published pipeline `v0.1.0` release. Its consumer-facing `requirements.yml`
contains the same five role tags and collection versions as the standalone
pipeline manifests. `galaxy.yml` remains version `0.1.0`, and the collection
repository has an immutable `v0.1.0` tag and corresponding public Gitea
release to carry the built artifact.
The collection release includes the archive produced from that released tree,
named `rakestraw-dnd-0.1.0.tar.gz`. Its public release notes identify the exact
five application-role versions, pipeline-role version, native collection
dependencies, supported platform, and consumer bootstrap steps. A consumer
can fetch the tagged manifest and archive through public Gitea URLs and
install the suite without access to this development workspace.
## Repository Ownership
- The five standalone application-role repositories own their respective
`v0.1.0` tags. Their reviewed role content remains unchanged by this
feature.
- `ansible-role-dnd-pipeline` owns its tag-pinned role manifest, standalone
release documentation, and `v0.1.0` tag.
- `ansible-collection-dnd` owns the released pipeline subtree, unified
tag-pinned consumer manifest, collection release documentation, collection
tag, built artifact, and Gitea release attachment.
- `ansible-workspace-dnd` owns this roadmap, cross-repository compatibility
record, active implementation plan, progress tracking, and independent
release review.
- The application source repositories, campaign repository, prompt-library
repository, and `rakestraw-ansible` are unchanged release inputs.
## Constraints and Settled Decisions
- Public repositories beneath
`https://gitea.maximumdirect.net/eric/` are the authoritative publication
channel for this release.
- Every Ansible repository uses initial release tag `v0.1.0`. The collection's
Galaxy version remains the corresponding unprefixed `0.1.0`, as required by
collection metadata and artifact naming.
- Tags are immutable release boundaries. A release candidate must be validated
before its tag is created and pushed; published tags must not be moved to
repair a failed release.
- The five application-role tags identify the exact reviewed commits shown in
the target end state. Release metadata must not create otherwise unnecessary
commits in those repositories.
- Released role dependency manifests use tag names, not branches or commit
hashes. Application repositories remain independently versioned after this
shared initial baseline.
- The pipeline repository remains authoritative. Its release must be pushed
to Gitea before the collection imports the `v0.1.0` revision through the
documented remote-only subtree command.
- The collection tag identifies the exact source tree from which the attached
artifact is built. The attached file must not be rebuilt from a later or
dirty tree while retaining the same version.
- The public collection release attachment is the selected binary publication
interface. The repository tag remains the source publication interface.
- Consumer validation must not use sibling checkouts, normal user Ansible
paths, preinstalled project roles, or an unpublished local collection
archive.
- The collection's Gitea release description and existing repository
documentation are
sufficient for the initial release. This feature does not introduce
repository-local changelog files solely to duplicate those notes.
## Simplest Viable Implementation
Use ordinary Git tags, one collection Gitea release, existing Ansible
dependency manifests, the established subtree command, and `ansible-galaxy
collection build`. The five application roles need validation and tags only.
The pipeline and collection need small manifest and documentation changes
before their respective release tags are created.
Reuse the existing repository-local integration entry points as release gates.
The collection integration suite already exercises isolated dependency
bootstrap, archive construction and installation, FQCN resolution, native
application behavior, and clean repeated convergence. Adapt its inputs only as
necessary to consume the release tags, and use a focused final smoke path to
download the published manifest and attached archive from Gitea. Do not add a
second release framework or duplicate the detailed behavior matrices owned by
the standalone repositories.
Publication is intentionally manual for the first release. The work does not
yet justify release scripts, workflow files, persistent staging state, or a
new packaging service.
## Rationale and Alternatives
Immutable role tags give consumers meaningful versions while preserving the
settled model of independently released repositories. Publishing only commit
hashes would be reproducible but would not establish the named release
contract required by the MVP. Publishing branches would not be immutable.
Using `v0.1.0` for every initial role and the collection makes the first
compatibility baseline easy to understand. Future role releases remain
independent, and future collection releases record whatever combination is
then supported; no synchronized-version policy is implied.
Attaching the Galaxy-built archive to the public Gitea collection release
provides a direct installation artifact without introducing another registry.
Requiring consumers to clone and build the collection would expose unnecessary
development steps, while publishing to Ansible Galaxy or Automation Hub would
add an unselected distribution channel and account lifecycle.
Manual publication is appropriate for one initial release and keeps the
release contract visible. Automation can be considered after repeated release
work demonstrates a stable process worth encoding.
## Acceptance Criteria
- Each application-role repository advertises a public, immutable `v0.1.0`
tag at the exact reviewed revision listed in this roadmap.
- Each application role's existing syntax, lint, integration, and clean-repeat
validation passes for the candidate being tagged; no role behavior is
changed merely to create the release.
- The pipeline role's released manifest selects all five application roles by
`v0.1.0`, and its collection dependency versions remain unchanged.
- The pipeline's existing validation installs its application-role
dependencies from the public Gitea tags, exercises the role through its
public interface, and passes its immediate clean repeat.
- The pipeline repository advertises a public, immutable `v0.1.0` tag at the
validated release commit.
- The collection subtree matches the published pipeline `v0.1.0` tree outside
repository-specific Git metadata and records the remote Gitea import in Git
history.
- The collection's root manifest uses the same five `v0.1.0` application-role
pins and exact native collection versions as the released pipeline role.
- `ansible-galaxy collection build` from the collection release candidate
produces `rakestraw-dnd-0.1.0.tar.gz`, and the existing artifact-boundary
exclusions remain effective.
- The collection's existing integration suite passes against the release
candidate, including isolated bootstrap, installed-artifact FQCN use,
representative native application checks, and immediate `changed=0` and
`failed=0` convergence.
- The collection repository advertises a public, immutable `v0.1.0` tag and
matching Gitea release. The archive attached to that release is the artifact
built from the tagged tree.
- A clean remote-only smoke validation downloads the public tag-pinned
manifest and public collection attachment, installs into isolated paths,
resolves `rakestraw.dnd.pipeline`, and completes with a clean immediate
repeat without referencing any sibling repository or unpublished artifact.
- Release-facing documentation no longer describes collection `0.1.0` or the
role release tags as future or unpublished, and it gives the complete public
Gitea installation path without requiring the development workspace.
- All participating repositories are clean, their release commits and tags
are present upstream, and workspace status records the published
compatibility baseline.
## Dependencies and Follow-up Work
Feature 0012 and its remediation must remain complete. Credentials capable of
pushing commits and tags and creating the public collection Gitea release and
attachment must be available during implementation.
Potential later features include release automation, publication to an Ansible
registry, independently versioned follow-up releases, optional suite-level
operator membership management, and defined upgrade, downgrade, or removal
behavior. None is required for the initial release.
## Potential Future Hardening
- Signed Git tags or release artifacts.
- Published checksums, provenance attestations, or software bills of
materials.
- Automated verification and publication in a controlled CI environment.

View File

@@ -0,0 +1,240 @@
# Feature 0014: Enroll Existing Pipeline Operators
Status: done
## Summary
Let consumers name existing human accounts that the D&D pipeline role should
add to its shared runtime group. The interface is empty by default, manages
membership additively, and leaves account creation and removal outside the
role.
## Problem or Opportunity
The pipeline's shared filesystem and credential policy already supports
invocation by the dedicated `narratio` service account or by a human member of
the selected runtime group. The role does not yet select human operators or
manage their membership. Consumers must currently repeat a small
`ansible.builtin.user` task beside the role even though group enrollment is a
natural suite-level access choice.
The role must not silently become a general account-management interface.
Human account identity, login policy, credentials, home directories, and
removal remain host or organization concerns. The pipeline needs only a
concise way to enroll explicitly selected existing accounts in the group that
already defines pipeline authorization.
## Governing Policies
- [The Ansible house style](../../ansible.md) requires the smallest direct
desired-state implementation and permits state inspection only when its
result is independently required.
- [The testing house style](../../testing.md) requires a representative
public-interface test of deployed behavior and immediate clean convergence,
without retesting `getent` or `user` module internals.
- [The MVP roadmap](../mvp.md) defines the runtime group as the shared
operator and credential-authorization boundary.
- [Feature 0009](0009-shared-pipeline-filesystem-and-execution.md) establishes
the service-user and human-group-member execution model.
- [Feature 0011](0011-managed-pipeline-credential-delivery.md) establishes
that runtime-group membership authorizes access to the suite's shared
credentials.
- [Feature 0012](0012-collection-assembly.md) makes the standalone pipeline
repository authoritative and requires reviewed changes to enter the
collection through its public Gitea subtree source.
## Scope
- Add `dnd_pipeline_operator_users`, a list of existing account names that
defaults to an empty list.
- Declare the variable as a list of strings in the pipeline role's argument
specification.
- Require every selected account to exist before changing any selected
account's group membership.
- Add each selected account to `dnd_pipeline_runtime_group` with additive
supplementary-group semantics.
- Preserve the existing account, its primary group, and all other
supplementary groups.
- Leave omitted accounts and memberships unmanaged.
- Document the existing-account contract, additive behavior, authorization
consequence, and need to begin a new login session before newly granted
supplementary membership is visible to a long-lived user session.
- Adapt the existing pipeline integration fixture to exercise enrollment
through the new public variable and retain its representative configuration,
secret-access, shared-cache, and clean-repeat behavior.
- Import the reviewed, pushed pipeline commit into the collection through the
established squashed subtree workflow and validate the assembled artifact.
## Non-goals
- Creating, deleting, locking, or otherwise managing human accounts.
- Managing UIDs, primary groups, passwords, SSH keys, shells, home
directories, sudo access, or login policy.
- Removing a user from the runtime group when the user is omitted from the
list or removed from a later inventory value.
- Managing external identity-provider or directory-service membership.
- Adding per-user access controls, separate credential sets, or a second
operator group.
- Changing the `narratio` service account, runtime group, filesystem modes,
ACL policy, credential policy, or application configuration.
- Adding handlers, sidecar state, membership snapshots, post-change
verification, or a custom account-management abstraction.
- Publishing a new pipeline-role or collection release as part of this
implementation.
## Target End State
The pipeline role exposes this optional interface:
```yaml
dnd_pipeline_operator_users:
- eric
- alice
```
The default is `[]`, so existing consumers retain their current behavior. If
the list is nonempty, every named account must already exist on the managed
host. The role fails before its enrollment task when any selected account is
absent; it does not create a partially specified account as a side effect.
Each existing selected account is an additive member of
`dnd_pipeline_runtime_group`. Existing primary and supplementary memberships
remain intact. Membership in that group grants the pipeline access already
defined by Features 0009 and 0011, including shared writable runtime roots and
group-readable suite credentials. Existing login sessions may need to be
restarted before the operating system exposes newly granted supplementary
membership.
Removing a name from `dnd_pipeline_operator_users` does not revoke membership.
Account and access removal require an explicit lifecycle policy and remain
separate work.
The collection's `rakestraw.dnd.pipeline` role contains the same reviewed
interface through a squashed import from the authoritative public pipeline
repository. The published `v0.1.0` release remains unchanged until a later
release feature selects and validates a new version.
## Repository Ownership
- `ansible-role-dnd-pipeline` owns the public variable, existing-account
prerequisite, additive enrollment, operator documentation, and detailed
behavioral integration coverage.
- `ansible-collection-dnd` owns the faithful subtree import and its existing
assembled-artifact validation boundary. It does not independently
reimplement or duplicate the pipeline behavior test.
- `ansible-workspace-dnd` owns this roadmap, the settled MVP decision, active
implementation plan, status, and review record.
- The standalone application roles, application sources, asset repositories,
and `rakestraw-ansible` remain unchanged.
## Constraints and Settled Decisions
- The public interface is a simple list of usernames, not a mapping of account
definitions. A richer structure would imply ownership of account creation
and login policy that this feature expressly excludes.
- All selected accounts must exist before enrollment begins. A single
`ansible.builtin.getent` loop over the `passwd` database is justified because
`ansible.builtin.user` with `state: present` would otherwise create a missing
account. No registered fact, separate assertion, or post-enrollment query is
required.
- The enrollment task uses `ansible.builtin.user` with the selected runtime
group and `append: true`. The module owns membership convergence; the role
does not inspect or reconstruct current group lists.
- The enrollment task uses `become: true`. The account-existence lookup does
not require elevation.
- The runtime group continues to be created by the existing Narratio role
dependency before the pipeline role's ordinary tasks execute.
- Empty input naturally skips both loops. No separate conditional, fact, or
branching task is needed.
- Omission is unmanaged, not absent. The feature adds access but does not
define revocation or exact-list reconciliation.
- No username grammar stricter than the managed host's account database is
introduced. The `getent` lookup and `user` module retain ownership of their
native input and error handling.
## Simplest Viable Implementation
Add the empty-list default and matching argument-spec entry. Add one
`ansible.builtin.getent` task that loops over the selected names with database
`passwd` and relies on its default missing-key failure, followed by one
privileged `ansible.builtin.user` task that loops over the same names, selects
`dnd_pipeline_runtime_group`, and uses `append: true`.
Replace the README's consumer-owned membership example with the role variable
and its exact ownership boundary. In the existing integration driver, create
the temporary operator without `narratio` membership before the first role
application, pass that account through `dnd_pipeline_operator_users`, and
retain the existing native configuration and shared-access exercises. Do not
add a missing-user test, inspect `/etc/group`, assert module return data, or
create a second operator scenario.
After the authoritative pipeline change is committed, validated, and pushed,
use the documented public Gitea `git subtree pull --squash` workflow to import
that exact commit into `ansible-collection-dnd`. Run the collection's existing
artifact-boundary integration suite without expanding its detailed feature
matrix.
## Rationale and Alternatives
Keeping membership entirely in each consumer play would avoid two role tasks,
but it leaves every deployment to reproduce access policy already owned by the
suite. An empty-by-default list adds the ergonomic path without affecting
consumers that prefer external membership management.
Passing complete account definitions to the pipeline role would permit it to
create users, but it would also require defaults and policy for homes, shells,
authentication, IDs, and account removal. Those concerns are not pipeline
requirements and belong to host identity management.
Calling `ansible.builtin.user` without first checking existence would be more
compact but would create missing accounts with implicit properties. The
`getent` lookup is therefore independently required to enforce the selected
ownership boundary; it is not defensive re-verification of state already
owned by another module.
Exact-list reconciliation would make removal declarative, but omission has
not been selected as revocation and could remove access managed elsewhere.
Additive enrollment is the smaller and safer contract until lifecycle policy
is designed explicitly.
## Acceptance Criteria
- `dnd_pipeline_operator_users` defaults to an empty list and is declared as a
list of strings in the public argument specification.
- An empty list introduces no account or membership change.
- Every explicitly selected account must already exist, and a missing account
causes convergence to fail before the enrollment task can create or modify
any selected account.
- Each selected existing account is added to
`dnd_pipeline_runtime_group` additively without replacing its other groups.
- Omitted accounts and prior memberships remain unmanaged.
- The role uses only one account-existence task and one enrollment task; it
adds no handler, registered fact, assertion layer, command, private state,
or post-change verification.
- The pipeline documentation explains the variable, existing-account
prerequisite, additive non-removal behavior, group authorization boundary,
and login-session caveat.
- The existing temporary-operator integration scenario enrolls its fixture
through the public variable, demonstrates representative pipeline access,
and the immediate identical second role application reports `changed=0`
and `failed=0`.
- Syntax checking, production-profile lint, the complete standalone pipeline
integration suite, and `git diff --check` pass.
- The exact reviewed pipeline commit is pushed to public Gitea before the
collection imports it.
- The collection subtree contains the reviewed pipeline change through the
documented remote-only squashed import, and the existing collection
integration suite passes against the built and installed artifact.
- No application repository, asset repository, release tag, published
artifact, application configuration, filesystem policy, or credential value
changes.
## Dependencies and Follow-up Work
Features 0009, 0011, 0012, and 0013 are prerequisites. The completed Feature
0013 workspace and collection closeout commits should be pushed before the
implementation sprint begins so local and remote baselines agree.
Upgrade, downgrade, account revocation, exact-membership reconciliation,
application removal, and publication of a release containing this feature
remain separate future work.

View File

@@ -0,0 +1,424 @@
# Feature 0015: Enable D&D S3 Storage and Publishing
Status: done
## Summary
Make the D&D pipeline operational with Narratio's current S3 storage,
publication, caching, cleanup, and restore capabilities. The pipeline role
will select the established Backblaze B2 destination, reference two typed
object-storage credentials delivered through its existing secrets directory,
publish the useful transcript and D&D artifact outputs, and retain maximum S3
audio caching.
The standalone Narratio role already exposes Narratio v2.1.1's complete
configuration surface for this behavior. This feature supplies D&D suite
policy through that existing interface; it does not add another storage
implementation or credential mechanism.
## Problem or Opportunity
The pipeline role currently installs Narratio v2.1.0 and configures the full
processing graph, but deliberately leaves Narratio storage and publishing at
their application-level defaults. Its README consequently describes storage,
publishing, and end-to-end external execution as deferred. The resulting suite
can validate configuration and process local state, but it does not select the
remote archive or publish the outputs needed for an operational deployment.
Narratio v2.1.0 also rejected a valid publish list when a rule explicitly set
`required` while omitting a derivable `dest`. Narratio v2.1.1 corrects that
resolution bookkeeping defect without changing the publish schema or
destination rules. This feature therefore advances the pipeline application
pin to v2.1.1 and retains explicit suite-owned requiredness together with
native destination derivation.
The prior test-machine configuration records the intended Backblaze B2
endpoint, bucket, prefix, credential names, publication set, and post-publish
workspace cleanup. Narratio's current contract has since replaced the legacy
credential field names and secrets configuration with ConfigKit typed
references and a conventional sibling `secrets/` directory. The Ansible suite
already implements that new credential-delivery boundary for Audita and
Notarius, so S3 needs only to join the same path.
## Governing Policies
- [The Ansible house style](../../ansible.md) requires suite policy to flow
through the standalone role's field-specific interface and optional fields
to remain application-owned unless the suite deliberately selects them.
- [The testing house style](../../testing.md) requires representative
public-interface and native-application validation without duplicating AWS
SDK, ConfigKit, or Ansible module behavior.
- [The MVP roadmap](../mvp.md) makes the pipeline role responsible for
cross-application configuration and end-to-end validation.
- [Feature 0011](0011-managed-pipeline-credential-delivery.md) establishes the
managed Narratio secrets directory and typed credential-forwarding policy.
- [Feature 0012](0012-collection-assembly.md) makes the standalone pipeline
repository authoritative and imports reviewed changes through public
Gitea.
- [Feature 0016](0016-deploy-dnd-pipeline-to-pipeline-dnd.md) consumes this
feature's reviewed interface for the first real-host deployment.
## Scope
- Advance the suite's Narratio application version from `v2.1.0` to the
backward-compatible `v2.1.1` bugfix release.
- Add suite-owned pipeline variables for the selected Narratio workspace,
S3, cache, and publish settings.
- Select the S3 backend with these D&D deployment defaults:
| Setting | Suite default |
| --- | --- |
| Endpoint | `https://s3.us-east-005.backblazeb2.com` |
| Bucket | `rakestraw-assets` |
| Root prefix | `dnd` |
| Region | `us-east-1` |
| Force path style | `true` |
| Access-key reference | `OBJECT_STORAGE_KEY_ID` |
| Secret-key reference | `OBJECT_STORAGE_KEY` |
- Pass the two credential reference names to the standalone Narratio role.
Their values use the existing `dnd_pipeline_secrets` map and managed
`/usr/local/etc/narratio/secrets/` directory.
- Enable S3 audio caching explicitly so the suite retains Narratio's maximum
available audio reuse.
- Enable run publication and publish these complete native output rules:
| Source | Required |
| --- | --- |
| `narratio.transcript.final` | `true` |
| `narratio.transcript.final_trimmed` | `true` |
| `narratio.transcript.final_markdown` | `true` |
| `narratio.transcript.final_trimmed_markdown` | `true` |
| `narratio.artifact.session_recap` | `true` |
| `narratio.artifact.hostile_rumors` | `true` |
| `narratio.artifact.deranged_rumors` | `false` |
- Let Narratio derive each destination from the built-in transcript path or
configured artifact output path rather than duplicating those paths in the
publish list.
- Enable workspace cleanup only after Narratio records successful run
publication. Leave spool-audio deletion under Narratio's existing default
because the suite has selected no policy requiring source-audio removal.
- Keep the production and `testing` profile storage and publishing behavior
identical. The existing overlay remains limited to model-profile selection.
- Document the four credentials normally required by the operational suite:
`AUDITA_LLM_API_KEY`, `OPENROUTER_API_KEY`,
`OBJECT_STORAGE_KEY_ID`, and `OBJECT_STORAGE_KEY`.
- Document the operator-visible publication, restore, S3-session-audio, lock,
caching, and cleanup capabilities enabled by the selected configuration,
while linking Narratio's canonical CLI and operations documentation for
command details.
- Preserve every accepted Notarius lane as its existing
`narratio.extraction.<output_key>` source. Future Narratio artifact
definitions can consume those sources during analyze without first making
the extraction lanes separate published outputs.
- Adapt the existing pipeline integration scenario to resolve synthetic S3
credentials and validate one explicitly supplied representative storage and
publishing configuration through Narratio's native interface without
contacting object storage.
- Import the reviewed public pipeline commit into the collection through the
established squashed subtree workflow, adapt the collection's artifact-level
fixture to supply the added credential names, and validate the assembled
artifact.
## Non-goals
- Implementing an S3 client, publication engine, remote commit format,
restore mechanism, publish-lock mechanism, or audio cache in Ansible.
Narratio owns all of those behaviors.
- Placing credential values in role defaults, templates, documentation,
tests, ordinary inventory, or the generated pipeline configuration.
- Adding a second secret-delivery mechanism, environment wrapper, service
unit, credential synchronizer, or AWS configuration-file manager.
- Managing Backblaze buckets, object lifecycle policy, application keys,
retention policy, versioning, encryption, quotas, or network access.
- Managing per-session `session.yml` files or selecting local versus S3 audio
input for an individual session.
- Running a paid or networked publication test from a repository-local test
suite. Feature 0016 owns the representative live end-to-end exercise.
- Publishing every Notarius extraction lane as a named current output. The
lanes remain available as analyze inputs independently of publication; stable
remote destinations require an explicit operator need.
- Setting Narratio's optional `notarius.chunk_cache` override. The managed
Notarius configuration remains the single owner of its ordinary `auto`
cache policy, and Narratio v2.1 already requests refresh for forced
extraction.
- Adding notification providers. Narratio v2.1 supports only its existing
`noop` notification mode.
- Releasing new role or collection versions as part of this implementation.
- Modifying Narratio, ConfigKit, or the standalone Narratio role. Narratio
v2.1.1 is an already published prerequisite, and the existing generic role
can install the selected application tag through `narratio_version`.
## Target End State
The standalone pipeline role exposes these suite variables with the selected
defaults:
```yaml
dnd_pipeline_narratio_version: v2.1.1
dnd_pipeline_narratio_workspace_cleanup_after_publish: true
dnd_pipeline_narratio_storage_backend: s3
dnd_pipeline_narratio_storage_s3_bucket: rakestraw-assets
dnd_pipeline_narratio_storage_s3_root_prefix: dnd
dnd_pipeline_narratio_storage_s3_region: us-east-1
dnd_pipeline_narratio_storage_s3_endpoint: >-
https://s3.us-east-005.backblazeb2.com
dnd_pipeline_narratio_storage_s3_force_path_style: true
dnd_pipeline_narratio_storage_s3_access_key_id: OBJECT_STORAGE_KEY_ID
dnd_pipeline_narratio_storage_s3_secret_access_key: OBJECT_STORAGE_KEY
dnd_pipeline_narratio_cache_s3_audio: true
dnd_pipeline_narratio_publish_enabled: true
dnd_pipeline_narratio_publish_upload_run: true
dnd_pipeline_narratio_publish_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
required: true
- source: narratio.artifact.hostile_rumors
required: true
- source: narratio.artifact.deranged_rumors
required: false
```
Each value is declared in the pipeline argument specification and passed
directly to its corresponding `narratio_*` variable in the pipeline role's
Narratio dependency. Narratio's existing root template renders the native
configuration. No new pipeline fragment or production task is required.
The ordinary generated configuration contains only the credential names:
```yaml
storage:
backend: s3
s3:
access_key_id: OBJECT_STORAGE_KEY_ID
secret_access_key: OBJECT_STORAGE_KEY
```
Consumers supply the two values beside the existing model-provider values
through encrypted inventory:
```yaml
dnd_pipeline_secrets:
AUDITA_LLM_API_KEY: "{{ vault_dnd_audita_llm_api_key }}"
OPENROUTER_API_KEY: "{{ vault_dnd_openrouter_api_key }}"
OBJECT_STORAGE_KEY_ID: "{{ vault_dnd_object_storage_key_id }}"
OBJECT_STORAGE_KEY: "{{ vault_dnd_object_storage_key }}"
```
The example defines references only; no roadmap, role, or test contains real
credential values. The existing credential task writes the selected entries
with the suite's established group-authorized secret modes. Omitted map keys
remain unmanaged, as defined by Feature 0011.
With valid credentials, Narratio can accept either local or S3 audio selected
by each session file, cache S3 audio beneath `/var/cache/narratio`, publish an
immutable run and the selected stable outputs, use remote publication locks,
restore committed state, and clean the published workspace. These are native
Narratio commands and lifecycle rules rather than additional Ansible tasks.
The ten accepted Notarius outputs continue to enter Narratio's artifact
catalog as `narratio.extraction.*` sources. Analyze-stage Scriptorium artifacts
may reference those sources directly in their input mappings. Feature 0015
does not yet add such artifact definitions, but its publication choices do not
remove, rename, or constrain this future composition path.
## Repository Ownership
- `ansible-role-dnd-pipeline` owns the D&D suite variables, opinionated
defaults, dependency mappings, consumer documentation, and representative
integration scenario.
- `ansible-role-narratio` remains the generic owner of installation and native
pipeline rendering. Its reviewed `v0.1.0` role interface is compatible with
Narratio v2.1.1 and already covers every
configuration field required by this feature and should remain unchanged.
- `ansible-collection-dnd` owns the faithful pipeline subtree import, the
unified consumer dependency manifest, and artifact-boundary validation.
- `ansible-workspace-dnd` owns this roadmap, the later implementation plan,
status, and independent review record.
- `narratio` v2.1.1 is the released compatibility prerequisite and a read-only
source of storage, publication, credential, caching, cleanup, restore, and
CLI contracts during this implementation.
- `rakestraw-ansible` remains unchanged until Feature 0016 consumes this
interface on `pipeline-dnd`.
## Constraints and Settled Decisions
- The S3 endpoint, bucket, prefix, region, and path-style values are deliberate
D&D suite defaults. They are ordinary variables and remain overrideable by
inventory.
- Credential references are also policy defaults, but credential values have
no defaults. Operators must supply matching entries through
`dnd_pipeline_secrets` or another environment source supported by Narratio.
- The two credential-reference variables are nullable as a pair. Setting both
to `null` omits the references and preserves Narratio's AWS SDK provider-chain
path; configuring only one remains invalid under Narratio's native contract.
- The role does not assert that the secrets map contains particular keys.
Narratio's native loader owns typed-reference resolution, and external
environment values remain a supported higher-precedence source.
- `dnd_pipeline_narratio_publish_outputs` is one complete native list. A caller
replacing it assumes responsibility for the entire selected publication
set; the role does not merge rules.
- Publish destinations remain omitted where Narratio can derive them. The
configured source identity and artifact output path remain the single source
of truth.
- Narratio v2.1.1 is the minimum application version for this feature because
it preserves destination derivation when `required` is explicit. Do not work
around older behavior by duplicating destinations or omitting deliberate
requiredness.
- Workspace cleanup is gated by Narratio's own successful-publication
evidence. Ansible does not independently inspect remote state or remove
runtime content.
- S3 audio caching is enabled, and ordinary cleanup preserves the cache.
Explicit operator cache clearing remains a Narratio CLI operation.
- The testing profile does not silently disable Notarius, storage,
publication, cleanup, or credentials. It continues to differ only in the
already selected inexpensive Scriptorium model profile.
- S3 storage also enables Narratio's native restore and publication-lock
commands without another configuration surface. Ansible documentation may
describe availability but must not duplicate Narratio's detailed operating
manual.
- Notarius extraction-source availability and remote publication are separate
concerns. Analyze consumes `narratio.extraction.*` sources from the accepted
extraction catalog; `publish.outputs` selects only which sources also receive
stable published destinations.
## Simplest Viable Implementation
Advance `dnd_pipeline_narratio_version` to v2.1.1. Add the selected variables to
the pipeline defaults and argument specification, then map them into the
existing `rakestraw.narratio` dependency. Update the pipeline README to document
the policy, credential names, complete-list replacement semantics, and native
capabilities now available. Do not add a template, task, handler, fact, probe,
or storage-specific validation layer.
In the existing pipeline integration driver, extend the synthetic secrets map
with object-storage values and explicitly supply representative S3 and publish
variables. Use `narratio config validate` and its secret-safe effective
configuration output to prove that the public inputs compose into a valid
configuration. Retain the immediate clean repeat and secret non-disclosure
checks. Do not call a real S3 service or assert that the representative values
equal current role defaults.
Push the reviewed pipeline commit, import that exact public revision into the
collection through `git subtree pull --squash`, and extend only the
collection-level fixture inputs needed for native validation. The collection
suite should continue to prove artifact installation and one representative
assembled convergence rather than duplicate the detailed pipeline matrix.
## Rationale and Alternatives
Implementing storage behavior in Ansible would duplicate a mature native
application boundary. Narratio already owns credential resolution, AWS SDK
provider construction, immutable commits, verification, locks, restore,
caching, and cleanup. Passing declarative configuration through the generic
role is both smaller and more reliable.
Using the AWS SDK's ambient provider chain would avoid named secret files, but
the initial deployment has explicit Backblaze application credentials and the
suite already has a suitable managed typed-secret path. Keeping the two
credential-reference variables nullable preserves the ambient-provider
alternative: consumers can set both suite variables to `null` when their
deployment uses another provider.
Copying destinations into every publish rule would make the output layout more
visible locally, but it would duplicate paths already owned by Narratio's
built-in sources and the configured artifact definitions. Native destination
derivation keeps path coordination automatic.
Omitting explicit `required: true` values would avoid the v2.1.0 failure only
by relying on an unrelated defaulting path. Changing the generic role's YAML
format would not repair the underlying sequence-resolution mismatch. Narratio
v2.1.1 fixes the owning application boundary, allowing the suite to state its
requiredness policy directly without duplicating destinations.
Deleting spool audio after publication would minimize transient disk usage,
but no such retention policy has been selected, and local-audio sessions may
depend on that content. Leaving the field omitted preserves Narratio's default
while enabling the explicitly requested S3 audio cache.
Publishing all ten Notarius extraction lanes would create stable remote output
contracts that have not been requested. It is also unnecessary for the stated
future use: analyze-stage artifacts can consume `narratio.extraction.*`
directly. The immutable published run retains the processing result, while the
selected transcript and human-facing artifact outputs match the known
operational workflow.
## Acceptance Criteria
- The pipeline role declares and documents every suite variable shown in the
target state, with matching argument-spec entries and direct Narratio
dependency mappings.
- The pipeline installs Narratio v2.1.1, whose released configuration loader
supports explicit requiredness together with derived publish destinations.
- The two credential-reference variables accept paired `null` overrides so a
caller can deliberately select Narratio's ambient AWS SDK provider chain.
- The default effective Narratio configuration selects the specified
Backblaze-compatible S3 destination, typed credential names, S3 audio cache,
successful-publication workspace cleanup, run upload, and seven output
rules.
- The publish list relies on Narratio's native destination derivation and
retains `deranged_rumors` as optional while the other six outputs are
required.
- Spool-audio deletion remains unset by the pipeline role, and the testing
profile introduces no storage or publication override.
- `dnd_pipeline_secrets` remains a generic empty-by-default mapping; the role
documents all four expected operational entries without embedding any
credential value.
- No new production task, template, handler, fact, state file, wrapper, or
storage-validation command is introduced.
- The standalone Narratio role remains unchanged because its `v0.1.0` role
interface can install Narratio v2.1.1, renders the required native fields,
and preserves null omission.
- The existing pipeline integration scenario explicitly supplies
representative S3 and publish inputs, resolves synthetic values for all four
typed credentials, passes Narratio's native configuration validation, and
exposes no synthetic value in captured output.
- The immediate identical second pipeline application reports `changed=0`
and `failed=0`; syntax checking, production-profile lint, the complete
standalone integration suite, and `git diff --check` pass.
- The exact reviewed pipeline commit is pushed to public Gitea before the
collection imports it through the documented remote-only squashed subtree
workflow.
- The collection fixture supplies the added synthetic credential names, and
its existing build, isolated installation, FQCN resolution, native
validation, and clean-repeat suite passes without a duplicate S3 behavior
test.
- No real object-storage request, paid model request, application repository
change during the remaining implementation, asset change, new release tag,
or published artifact is required. The existing Narratio v2.1.1 release is a
prerequisite rather than an implementation deliverable.
- Pipeline documentation links operators to Narratio's canonical procedures
for S3 session audio, publish, restore, locks, status, and cleanup and no
longer describes storage and publishing as deferred.
- Documentation distinguishes accepted Notarius extraction sources from
published outputs and confirms that future analyze-stage artifacts may use
`narratio.extraction.<output_key>` inputs without publishing those lanes.
## Dependencies and Follow-up Work
Features 0009, 0011, 0012, 0013, and 0014 and the public Narratio v2.1.1 bugfix
release are prerequisites. In particular, Feature 0011 supplies the credential
directory and Feature 0014 supplies the human-operator access needed for the
eventual live deployment.
[Feature 0016](0016-deploy-dnd-pipeline-to-pipeline-dnd.md) follows this work.
It will put the four actual values in encrypted host inventory, pin the exact
reviewed suite revision in `rakestraw-ansible`, converge `pipeline-dnd`, and
exercise one real session through remote publication. Bucket lifecycle policy,
backup policy, credential rotation, additional publish outputs, automated
scheduling, and cleanup of the proof-of-concept deployment remain separate
future work.
A later artifact-development feature may add D&D-specific Narratio artifact
definitions whose Scriptorium input mappings consume selected
`narratio.extraction.*` sources. That feature should define each artifact's
purpose, inputs, prompt, output contract, and publication choice; it does not
require a storage-interface change.

View File

@@ -0,0 +1,149 @@
# Feature 0016: Prepare the D&D Deployment Playbook for `pipeline-dnd`
Status: done
## Summary
Write and commit the consumer playbook, necessary host variables, dependency
manifest, and concise usage documentation in `rakestraw-ansible`. This feature
ends with repository preparation. Deployment to a controller or target host
and execution of the pipeline are separate operator work.
## Scope
- `playbooks/pipeline/dnd.yml` targets the existing `pipeline-dnd` alias and
applies `rakestraw.dnd.pipeline`, using only hosts and roles.
- Host choices belong in `inventory/host_vars/pipeline-dnd/`: the WhisperX
endpoint, initial operator `eric`, default campaign `dilfs`, and credential
references. Unknown required values are explained in adjacent comments.
- Inherit the reviewed suite's storage, publication, caching, cleanup, and
application defaults. Retire obsolete legacy host variables.
- Root `requirements.yml` selects the reviewed public collection snapshot and
its role/native collection dependencies, preserving unrelated entries.
- Document local validation and eventual operator use. Commit the completed
repository changes without requiring remote access or real credentials.
## Non-goals
- Installing or updating anything on the operational controller or target.
- Connecting to `pipeline-dnd`, validating its platform or sudo access,
converging the host, checking runtime identities, or executing a real session.
- Obtaining API keys, choosing a Vault password, populating real credentials,
or selecting acceptance audio/session data.
- Changing application/role behavior, publishing a new suite release, adding
orchestration layers, or retiring the proof-of-concept role/playbook.
## Target End State
The committed playbook is:
```yaml
---
- hosts:
- pipeline-dnd
roles:
- rakestraw.dnd.pipeline
...
```
Existing connection variables remain in the host's `main.yml`. Its
`narratio.yml` contains the following public configuration and comments:
```yaml
dnd_pipeline_operator_users:
- eric
dnd_pipeline_whisperx_transcribe_url: >-
https://transcription.ai.rakestrawhome.com/transcribe
narratio_campaigns_default_campaign_id: dilfs
# Before deployment, define the four vault_dnd_* variables below in an
# Ansible Vault-encrypted host_vars/pipeline-dnd/vault.yml file.
# Values are not known here; leave these references unresolved until supplied.
# Do not put API keys or object-storage credentials in this plaintext file.
dnd_pipeline_secrets:
AUDITA_LLM_API_KEY: "{{ vault_dnd_audita_llm_api_key }}"
OPENROUTER_API_KEY: "{{ vault_dnd_openrouter_api_key }}"
OBJECT_STORAGE_KEY_ID: "{{ vault_dnd_object_storage_key_id }}"
OBJECT_STORAGE_KEY: "{{ vault_dnd_object_storage_key }}"
```
The references and comments are a complete deliverable for unknown secrets.
No encrypted file, placeholder key, or real credential is required for feature
completion. Future operator-supplied values should be Vault-encrypted in Git;
the suite's existing restricted runtime secrets files remain the delivery path.
The manifest pins the collection to
`2a53979069ff8d091172650729ae2135c1603163`, containing pipeline commit
`f48008aa38e1c50adde18aa455d12a8ad77023c2` with Narratio v2.1.2.
Its five standalone role dependencies
use their reviewed `v0.1.0` tags, with `ansible.posix` `2.2.0` and
`community.general` `13.3.0`. Suite Git dependencies use public Gitea URLs;
native collections come from Galaxy. Local sibling checkouts are not dependencies.
The runbook explains that the selected collection snapshot still reports
`0.1.0`, so eventual operator installation must explicitly refresh it from
the pinned commit if an older `0.1.0` is installed. This is an instruction
for future use, not an operation required by this feature.
## Repository Ownership
- `rakestraw-ansible`: consumer files, comments, dependency manifest, and runbook.
- Workspace: roadmap, staged plan, progress, and independent review record.
- Roles, collection, applications, and assets: read-only contract references.
## Constraints and Settled Decisions
The workspace [Ansible](../../ansible.md), [testing](../../testing.md), and
[planning](../../planning.md) policies apply. Feature 0015 has passed review
and supplies the required suite interface.
- Keep playbooks minimal and settings in inventory. Preserve `pipeline-dnd`
and its connection identity; do not rename it to `pipeline.dnd`.
- Preserve `dilfs` using the existing standalone Narratio variable. Remove
legacy `narratio_s3_*` and `narratio_default_campaign_id` host settings.
- Missing operational inputs are documented, not treated as implementation
blockers. No remote controller, SSH identity, Vault password, or session is
required for repository preparation.
- Local dependency installation and syntax/host-selection checks are permitted.
Existing passing evidence may be reused when relevant inputs are unchanged.
- `ansible-doc` rendering is not an acceptance gate. Missing role argument
descriptions are a separate documentation improvement.
## Simplest Viable Implementation
Retain the already-committed minimal playbook, manifest, and public inventory.
Add adjacent comments for unresolved credentials, align the runbook with the
repository-only scope, perform appropriate local checks, and commit. No new
Ansible task, runtime test harness, or deployment automation is needed.
## Acceptance Criteria
- The playbook targets only `pipeline-dnd` and applies only the collection role.
- Host inventory expresses the known choices above and documents unknown
credentials next to their references without real or fake secret values.
- The dependency manifest contains the reviewed public pins and preserves
unrelated dependencies. Public installation and local syntax/host-selection
evidence are available; no documentation-rendering check is required.
- The runbook distinguishes repository readiness from future deployment and
explains how the operator supplies missing values and eventually invokes it.
- Changes are committed in the owning repositories, with clean working trees
for the feature's changes. No controller deployment, target convergence,
clean-repeat run, or real pipeline execution is required or claimed.
- Historical role/playbook files remain available.
## Dependencies and Follow-up Work
Features 0013–0015 supply public dependencies, operator enrollment, and storage
policy. Consumer preparation was completed in `716a80e`, `12b2462`, and
`7f8353d`, and passed independent review with no remediation findings.
Public dependency installation, target-only host listing, syntax checking,
and whitespace validation passed. Subsequent consumer commit `7f4c90a`
updates the collection pin for the Narratio v2.1.2 bug fix; collection build
and syntax validation passed. These changes are committed and published.
The operator may later provision Vault values, install dependencies on their
controller, deploy to the host, and validate real processing/publication.
Those actions require a separate request and are not unfinished Feature 0016
acceptance requirements.

View File

@@ -0,0 +1,199 @@
# Feature 0017: Notarius Testing Overlay
Status: done
## Summary
Selecting Narratio's `testing` profile also selects a separately managed
Notarius `testing` configuration overlay. Operators can develop D&D assets
with economical extraction settings without modifying production configuration
or invoking Notarius separately.
## Problem or Opportunity
The suite's existing testing overlay changes Scriptorium selections but leaves
Notarius on its production configuration. Narratio v2.2.0 now provides the
explicit `pipeline.notarius.config_profile` interface requested by this consumer.
Notarius v0.7.1 retains the corresponding `--config-profile` option and updates
PromptKit and its provider catalogs. This feature adopts v0.7.1 as its baseline.
## Scope
- Expose the optional native selector in the standalone Narratio role.
- Update standalone Notarius and suite version defaults to v0.7.1, with
matching current-version documentation and collection distribution.
- Deploy a Notarius ConfigKit testing overlay through the suite role.
- Explicitly select that overlay from Narratio's existing testing overlay.
- Select `gpt-terra-latest` for production and `gpt-luna-latest` for testing,
while retaining inventory overrides for both choices.
- Document and validate the composed configuration, then distribute the
updated suite through the collection and refresh the consumer dependency pin.
## Non-goals
- Further upstream application changes or a Narratio-side LLM-profile override.
- Automatically propagating profile names between applications.
- Disabling Notarius, caching, publishing, or other pipeline stages for testing.
- New credentials, cache layouts, other production tuning, or deployment automation.
- Live controller/target deployment or paid model calls as completion gates.
## Target End State
### Standalone Narratio Interface
`narratio_notarius_config_profile` defaults to `null`. The role omits
`notarius.config_profile` when null and serializes explicitly supplied values,
including an empty string. Documentation and argument specifications expose
the field without duplicating or narrowing Narratio's selector semantics.
### Explicit Suite Composition
The suite leaves the base selector unset. Its existing Narratio
`profiles/testing.yml` includes:
```yaml
notarius:
config_profile: testing
```
The suite deploys `/usr/local/etc/notarius/profiles/testing.yml`. That file
overlays the selected suite pipeline's `llm_profile`, using
`dnd_pipeline_narratio_notarius_pipeline_id` as the pipeline key and a new
`dnd_pipeline_notarius_testing_llm_profile` variable as the value. It does not
copy the full pipeline definition. ConfigKit performs the ordinary merge.
The default suite pipeline currently inherits its LLM selection at pipeline
level. Caller-supplied binding-level selections retain Notarius's native
precedence; this feature does not rewrite arbitrary caller pipelines or promise
that a pipeline-level default overrides explicit binding choices.
### Production and Testing LLM Defaults
The suite's base `dnd-session` pipeline selects `llm_profile: gpt-terra-latest`
instead of `dnd-extraction`. Callers can continue overriding that choice through
the existing `dnd_pipeline_notarius_pipelines` mapping. The new
`dnd_pipeline_notarius_testing_llm_profile` defaults to `gpt-luna-latest`.
Both IDs are supplied by the OpenRouter catalog `v2.20260922.1` selected by
Notarius v0.7.1. Use those native catalog profiles directly; no operator profile
asset or profile-source setting is needed for these defaults. Retain the
existing `OPENROUTER_API_KEY` credential reference. These are deliberately
moving `latest` selections, not promises of immutable underlying model versions.
This production-model policy belongs to the suite, not the standalone role.
Notarius stays enabled and retains its configured caching, output contracts,
references, and production defaults outside this overlay. Existing Scriptorium
testing overrides remain intact. Credentials continue through the existing
typed reference and suite secrets interfaces; no credential values enter YAML.
Configuration files and directories use the suite's existing owner, group,
and mode variables. The selector and overlay add no new runtime identity or
filesystem-permission policy.
## Repository Ownership
- `ansible-role-narratio`: generic optional selector, documentation, and tests.
- `ansible-role-notarius`: v0.7.1 installation default and corresponding
documentation; existing profile-source settings remain sufficient.
- `ansible-role-dnd-pipeline`: testing policy, overlay assets, and composition.
- `ansible-collection-dnd`: imported pipeline snapshot and compatible dependency
manifest. Its current Narratio-role `v0.1.0` pin must advance to include the
new public variable; changing only the sibling role is insufficient.
- `rakestraw-ansible`: matching dependency pins and concise operator guidance.
- Workspace: roadmap, implementation plan, progress, and review.
- Narratio and Notarius applications: read-only authoritative contracts.
The standalone Notarius role already exposes profile-source settings and
does not need D&D-specific overlay policy.
## Constraints and Settled Decisions
Follow the [MVP roadmap](../mvp.md), [Ansible house style](../../ansible.md),
and [testing house style](../../testing.md). Narratio v2.2.0 is already selected
by the suite; Notarius v0.7.1 is the selected target. Consult these tags, not
only newer application checkouts.
### Notarius v0.7.1 Compatibility
The [upstream release notes](https://gitea.maximumdirect.net/eric/notarius/src/tag/v0.7.1/docs/releases/v0.7.1.md)
describe unchanged CLI, configuration, artifact, and subprocess contracts.
The application-owned `dnd-extraction` fallback retains its settings and no
configuration migration is required. Independently of that upstream behavior,
the user has selected `gpt-terra-latest` as this suite's new production default.
Profile selection must use the catalogs selected by v0.7.1 (PromptKit v0.10.0).
The removed `deepseek-3-2`, `deepseek-4-flash`, and `deepseek-4-pro` catalog IDs
must not be assumed available or silently replaced by similarly named profiles.
This is deployment guidance, not a request for an Ansible catalog validator.
Existing checkpoints with the previous profile-source identity are not reused;
source-keyed chunk plans and existing output artifacts are unaffected. Document
this upstream upgrade behavior without deleting caches or forcing Narratio
extraction automatically.
Each application owns its configuration. Narratio selects the downstream
overlay; Notarius resolves and validates it. Existing application behavior owns
extraction reuse when selections change and explicit-force handling for changes
behind a stable profile name. Do not add Ansible state tracking for either.
## Simplest Viable Implementation
Add one nullable role field and its conditional template output. Extend the
suite's existing directory/template management to deploy the Notarius overlay
and extend the existing Narratio testing template with the explicit selector.
Use native serialization and ordinary file/template modules. Select the two
existing catalog IDs rather than deploying duplicate profile definitions. No assembly facts,
preflight state probes, or generic overlay-management framework is required.
## Rationale and Alternatives
A downstream ConfigKit overlay can own model choices and later Notarius tuning
without expanding Narratio's configuration surface for each setting. Direct
LLM-profile forwarding would solve only the model-selection case. Automatic
profile propagation would couple unrelated profile names and is not selected.
## Acceptance Criteria
- The standalone role omits an unset selector and preserves explicitly supplied
representative values, including the empty-string base selector.
- Native configuration inspection shows Narratio testing selecting Notarius
testing, and Notarius testing selecting the requested LLM profile. Base
configuration retains its production selection.
- A representative inventory-supplied testing selection is supported. Tests
exercise behavior rather than asserting that today's default model stays fixed.
- Notarius's deployed-version validation accepts the composed pipeline and
selected profile. No paid inference is required.
- Existing integration coverage remains valid, and immediate repeated role
convergence reports no changes. Do not independently retest file-module
ownership, modes, or template-file existence.
- The built collection works with its declared public role dependencies; no
local sibling checkout is needed by consumers. Subtree imports follow the
documented public-Gitea workflow, and published tags remain immutable.
## Dependencies and Follow-up Work
The upstream selector shipped in Narratio v2.2.0; the downstream baseline is
now Notarius v0.7.1. Git history preserves the completed implementation plan.
Future testing-specific Notarius settings belong in its overlay but are not
implicitly included in this feature.
## Completion and Review Evidence
Completed and published in Narratio role `330afe7`, Notarius role `a82a83d`,
pipeline role `c56a942`, collection `ce5b838`, and consumer `0ced48c`.
Implementation reported passing full integration suites for both changed
application roles, the pipeline, and the collection, including clean repeated
convergence. Independent review found no code-quality issues, architecture gaps,
or unnecessarily strengthened requirements requiring remediation.
The review independently verified collection build and public dependency
installation, syntax and shell checks, native configuration validation,
consistent dependency pins, and exact subtree/source agreement. It reviewed
the recorded integration results without rerunning host-mutating suites.
Operational deployment and paid inference were neither required nor performed
as part of this feature review.
## Open Questions
None. The user selected `gpt-luna-latest` for testing and `gpt-terra-latest`
for production; both are available in the catalog selected by Notarius v0.7.1.

View File

@@ -0,0 +1,163 @@
# Feature 0018: Adopt Scriptorium v0.15.0 in the Standalone Role
Status: done
## Summary
Update the standalone Scriptorium role from v0.13.0 to v0.15.0 and expose its
new application-configuration settings using our existing nullable-variable
conventions. This is the first feature in the agreed
[application upgrade sequence](../application-upgrade-sequence.md).
## Problem or Opportunity
Although v0.15.0 primarily changes licensing and dependency versions, the
intervening v0.14.0 adopted ConfigKit and added application imports, overlays,
inspection, and transient retry controls. A version bump alone would leave
new configuration settings unavailable through the role's public interface.
The current role already emits `{}` for an unconfigured installation, omits
null optional fields, serializes mappings, and retains explicit falsey values.
Those practices remain compatible with the stricter upstream configuration
contract; no new production validation or migration mechanism is needed.
## Scope
- Adopt v0.15.0 as the standalone role's default source version.
- Expose ConfigKit imports and the application transient-retry setting.
- Confirm existing configuration variables and representative backend mappings
remain usable with the new application version.
- Update role documentation and focused offline integration coverage.
- Record completion and the role revision for later coordinated integration.
## Non-goals
- Changing pipeline, collection, consumer, or other application-role pins.
- D&D model choices, production/testing policy, or new provider credentials.
- Deploying prompt/profile/schema libraries or managing arbitrary overlay files.
- Selecting a runtime overlay for callers, managing a service, or adding HTTP
request/CLI-only controls such as execution reports and run deadlines to YAML.
- Upstream application changes, paid inference, or operational host deployment.
- Relicensing this Ansible role or copying upstream source/license material
into the role repository merely because the installed application changed.
## Target End State
### Installation and Existing Configuration
`scriptorium_version` defaults to `v0.15.0`. Retain the existing source checkout,
Go build, ownership, and permission behavior and the caller-selected version
interface. No build-toolchain change is required: the current Go 1.26 selection
satisfies the release's Go requirement.
Existing application fields keep their public variable names. Optional variables
remain null by default and are omitted; explicit supported zero/empty values
are serialized without truthiness checks. An installation with no application
settings still receives `{}`, not an empty file.
### New Public Variables
| Variable | Default | Rendered field |
| --- | --- | --- |
| `scriptorium_configkit_imports` | `null` | `configkit.imports` |
| `scriptorium_transient_retries` | `null` | `transient_retries` |
Imports are a native list of mapping entries, consistent with the other roles'
ConfigKit interfaces. Serialize the supplied list without reinterpreting path,
glob, or optional-entry semantics. Emit the parent section only when selected.
The caller owns referenced fragment and overlay files; ordinary inventory can
compose the list without a second raw-configuration interface.
Transient retries is an optional integer. Null means omit and inherit the
application/PromptKit default; zero explicitly disables additional transient
attempts. The standalone role does not freeze the upstream default or add a
retry budget of its own. Argument specifications and documentation describe
both variables consistently.
### Compatibility Guidance
Document the distinction between ConfigKit `overlays/` selected by
`--config-overlay` and PromptKit LLM profiles. Imports are configuration-root
relative, while application path values retain their process-working-directory
semantics. Link upstream for detailed validation and precedence rules.
Call out stricter YAML acceptance and changed retry behavior, plus the removal
of legacy DeepSeek catalog IDs, without installing compatibility aliases or
inventing role-side configuration guards. New fields should only be supplied
when selecting an application version that supports them.
Mention that Scriptorium v0.15.0's application grant is GPL-3.0-or-later and link
its tagged licensing notices. Do not conflate the application's grant with the
role's license or introduce legal approval as a deployment gate.
## Repository Ownership
- `ansible-role-scriptorium`: default version, variables, argument specification,
template, README, and repository-local tests.
- Workspace: feature roadmap, staged plan, progress, and review evidence.
- Scriptorium application: read-only tagged configuration/release contracts.
- Pipeline, collection, consumer, and asset repositories remain unchanged.
## Constraints and Settled Decisions
Follow the [Ansible house style](../../ansible.md),
[testing house style](../../testing.md), [MVP roadmap](../mvp.md), and
[upgrade sequence](../application-upgrade-sequence.md). Review the tagged
v0.15.0 contract rather than assuming later application changes apply.
The existing suite continues installing its current Scriptorium role/application
pins until final integration. Standalone adoption is not suite publication.
## Simplest Viable Implementation
Update the version default and extend the existing defaults, argument
specification, and single configuration template with the two optional fields.
Include both in the empty-document condition. Reuse the existing source/build
and file/template tasks unchanged. No additional runtime tasks are needed.
## Acceptance Criteria
- The default role installs v0.15.0 and native offline configuration validation
accepts the default and representative managed configurations.
- Representative non-null and falsey values remain correctly rendered; the new
retry field preserves explicit zero and is omitted when unset.
- A caller-supplied import is composed successfully by native configuration
inspection using a small externally supplied test fragment. An optional test
overlay can demonstrate native composition without adding role-owned overlay
management or retesting ConfigKit's complete precedence/error matrix.
- Existing offline profile/backend inspection remains useful and passes.
Application validation alone does not prove PromptKit source validity.
- Immediate repeated role application reports no changes. Tests assert supplied
configuration outcomes, not today's upstream/default version, catalog contents,
task arrangement, or file-module postconditions.
- Syntax/lint and repository integration checks pass without provider calls,
real secrets, or operational controller access.
- Suite and consumer pins remain unchanged, and completion identifies the role
commit available for the final integration feature.
## Dependencies and Follow-up Work
Git history preserves the completed staged plan.
Audita adoption is next. The eventual suite integration
feature owns propagation of the new role revision, deployment settings, and
coordinated upgrade guidance.
## Completion and Review Evidence
Completed in role commits `61dcafe`, `2fce529`, and `b174c8c`. Implementation
reported passing integration tests, including native configuration validation,
offline profile inspection, imports, explicit retry zero, and clean repeat
convergence. Independent review found no code-quality issues, implementation
gaps, or unnecessarily strengthened requirements requiring remediation.
Independent syntax, production-profile lint, shell syntax, whitespace, native
configuration validation, and focused template checks passed. The review used
recorded integration evidence without rerunning host-mutating suites. No new
production tasks or suite/collection/consumer pin changes were introduced.
No operational deployment is claimed.
## Upstream References
- [v0.15.0 configuration](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.15.0/docs/config.md)
- [v0.14.0 migration notes](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.14.0/docs/releases/v0.14.0.md)
- [v0.15.0 release and licensing notes](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.15.0/docs/releases/v0.15.0.md)

View File

@@ -0,0 +1,199 @@
# Feature 0019: Adopt Audita v2.0.1 in the Standalone Role
Status: done
## Summary
Replace the standalone Audita role's version-1 configuration interface with
Audita v2.0.1's native interface. Keep provider and D&D policy outside the
generic role. This is the second feature in the agreed
[application upgrade sequence](../application-upgrade-sequence.md).
## Problem or Opportunity
The role currently installs Audita v0.9.1 and renders version-1 configuration.
Audita v2 requires version-2 YAML, named backends, and selected PromptKit
profiles. Old per-role endpoint/model/credential/concurrency settings no longer
apply. A version-only update would produce an unusable deployment.
Unlike the previous minimal configuration, a valid v2 configuration requires
at least one backend and a proposal profile whose file exists. The generic role
must not invent a provider, endpoint, model, or credential to meet that contract.
The caller-input boundary is settled below.
## Scope
- Default to Audita v2.0.1 and configuration version 2.
- Replace retired public configuration variables with native v2 settings.
- Preserve still-supported domain controls and inventory composition.
- Document the breaking role-variable migration and caller prerequisites.
- Adapt offline integration tests to real v2 configuration/profile fixtures.
## Non-goals
- Updating pipeline, collection, or consumer application/dependency pins.
- Choosing D&D models, endpoints, credentials, concurrency, or retry budgets.
- Compatibility shims, automatic v1 conversion, or a dual-schema template.
- Live inference, operational deployment, report ingestion, service management,
or runtime configuration validation tasks.
- Imports: Audita deliberately disables ConfigKit imports. Do not add an import
variable merely because other applications expose one.
- Automatically provisioning secret values or selecting runtime overlays.
## Target End State
### Installation and Schema
`audita_version` defaults to `v2.0.1`; `audita_config_version` defaults to `2`.
Retain the existing source checkout, conditional Go build, dependency management,
configuration location, and owner/group/mode interfaces. Go 1.26 remains suitable.
The role renders v2 only; selecting an older application does not translate its
configuration. Operators needing v1 retain the previous role revision.
### Public Configuration Interface
Use these field-specific variables; optional settings default to null and are
omitted, allowing Audita to own defaults. Serialize native values and preserve
intentional zero, false, empty strings, and empty collections where supported.
| Role variable | Native field | Ownership |
| --- | --- | --- |
| `audita_profiles_dir` | `profiles_dir` | Optional caller profile location |
| `audita_backends` | `backends` | Caller-supplied native mapping |
| `audita_llm_proposal_profile` | `llm.proposal_profile` | Caller-selected required profile |
| `audita_llm_validation_profile` | `llm.validation_profile` | Optional; omission inherits proposal |
| `audita_llm_transient_retries` | `llm.transient_retries` | Optional native retry budget |
| `audita_llm_repair_attempts` | `llm.repair_attempts` | Optional native repair budget |
| `audita_llm_operation_timeout` | `llm.operation_timeout` | Optional duration string |
| `audita_validation_max_prompt_tokens` | `validation.max_prompt_tokens` | Optional batching control |
| `audita_reporting_enabled` | `reporting.enabled` | Optional report policy |
| `audita_reporting_stdout_dir` | `reporting.stdout_dir` | Optional report destination |
| `audita_diagnostics_debug` | `diagnostics.debug` | Optional debug policy |
Retain existing variables for modules, output schema, chunking, normalization,
thresholds, context description, and diagnostics work directory. Normalization
gap/duration fields now represent numeric seconds, not duration strings.
Argument specifications must accept the native integer/fractional values without
turning them into quoted strings in YAML. Do not add a duration-conversion layer.
Remove the old `audita_llm_{proposal,validation}_{base_url,model,api_key_env,timeout,max_retries}`,
`audita_concurrency_{total_llm,proposal_llm,validation_llm}`, and
`audita_diagnostics_retention` interfaces from defaults, templates, argument
specifications, and current examples. Document their replacements rather than
silently interpreting them under different semantics or adding deprecation probes.
The backend mapping carries endpoint, credential reference, concurrency, and
queue capacity using Audita's schema. Inventory can compose it with ordinary
Jinja expressions. Credential values stay outside the role; every surviving
backend reference must be available when Audita loads configuration, even when
that backend is not selected. Do not introduce separate per-role secret variables.
Null role variables mean omission, not literal YAML null. In particular, omit
an unset validation profile so Audita can inherit the proposal selection.
Backend mapping values retain native semantics, including a null credential.
### Profile and Overlay Ownership
Callers provide `audita_backends` and `audita_llm_proposal_profile`; neither has
a fabricated concrete default. Callers also deploy the selected profile files
before invoking Audita. `audita_profiles_dir` may be supplied or omitted to use
Audita's conventional sibling `profiles/` directory. Keep profile documents and
ConfigKit `overlays/` content caller-owned in this feature.
The later suite feature will own its D&D profile assets and coordinate their
deployment with Narratio's new external Audita configuration contract. The role
does not start processing or validate file availability during convergence.
## Repository Ownership
- `ansible-role-audita`: generic installation/configuration interface, migration
documentation, and local tests.
- Workspace: roadmap, active plan, progress, and review evidence.
- Audita application: read-only tagged schema, migration, and profile contracts.
- Other applications/roles, assets, pipeline, collection, and consumer: unchanged.
## Constraints and Settled Decisions
Follow the [Ansible house style](../../ansible.md),
[testing house style](../../testing.md), [MVP roadmap](../mvp.md), and
[upgrade sequence](../application-upgrade-sequence.md). The suite continues to
use its old compatible role/application set until final integration; Narratio v2
must not be accidentally paired with Audita v2 through a changed suite pin.
Old timeouts and retries do not map one-to-one to profile per-attempt timeouts,
logical-operation deadlines, transport retries, and structural repair. Expose
native controls without choosing replacement tuning for the D&D suite here.
## Simplest Viable Implementation
Update the version/schema defaults and replace the single configuration template's
retired sections with native v2 sections. Align argument specifications and the
README. Keep ordinary file/template/source/build tasks. Use the existing test
harness with caller-owned local backend/profile fixtures; add no state assembly,
profile resolver, migration command, or production probe.
## Acceptance Criteria
- The role installs v2.0.1 and renders native v2 configuration from supplied
backend/profile choices and optional settings.
- Native offline validation and effective-settings/profile inspection accept
representative configuration with an externally supplied profile and local
fixture endpoint; no provider request is needed.
- Tests cover supplied mapping composition, omission/inherited validation
selection, representative numeric seconds, and meaningful zero/false values.
Avoid a comprehensive schema matrix or assertions of current upstream defaults.
- Existing useful build and clean-repeat coverage remains. Immediate repeated
role convergence reports no changes; do not test module postconditions.
- Documentation explains required caller inputs and the breaking variable/schema
migration, linking Audita for full field and report semantics.
- No suite, collection, or consumer pins change. Completion records the reviewed
standalone role revision for the final integration feature.
## Rationale and Alternatives
Native backend mappings and named profiles preserve Audita's ownership instead
of reproducing per-role endpoint/model settings in Ansible. A dual-schema role
would add maintenance and ambiguity without a selected requirement; retaining
the previous role revision is the simpler boundary for old deployments.
## Dependencies and Follow-up Work
Git history preserves the completed staged plan. Notarius adoption is next.
D&D backend/profile assets,
tuning migration, testing overlays, credential lists, and coordinated deployment
belong to the later integration feature.
## Settled Caller-Input Decision
The user approved required `audita_backends` and `audita_llm_proposal_profile`
inputs through the ordinary role argument interface, with caller-owned profile
files. Do not give these variables null or fabricated defaults. A no-input role
invocation is no longer valid; examples and tests supply explicit choices.
Role-managed profile definitions are not part of this feature.
## Open Questions
None.
## Completion and Review Evidence
Completed in role commits `6137ff2`, `52f67fe`, and `c3dd59f`. Implementation
reported passing integration tests with native v2 validation, offline profile
inspection, mapping composition, omission, numeric seconds, falsey values,
build/recovery coverage, and clean repeated convergence.
Independent review found no code-quality issues, implementation gaps, or
unnecessarily strengthened requirements needing remediation. Independent
Ansible syntax, production-profile lint, shell syntax, whitespace, and focused
template checks passed. The review used recorded native/integration results
without rerunning the host-mutating suite.
No production tasks were added. Profile files remain caller-owned, and suite,
collection, and consumer pins remain unchanged. No operational deployment or
paid inference was performed as part of this review.
## Upstream References
- [v2.0.1 configuration](https://gitea.maximumdirect.net/eric/audita/src/tag/v2.0.1/docs/config.md)
- [v2 migration guide](https://gitea.maximumdirect.net/eric/audita/src/tag/v2.0.1/docs/migrations/v2.md)
- [v2.0.1 release](https://gitea.maximumdirect.net/eric/audita/src/tag/v2.0.1/docs/releases/v2.0.1.md)

View File

@@ -0,0 +1,173 @@
# Feature 0020: Adopt Notarius v0.8.1 in the Standalone Role
Status: done
## Summary
Update the standalone Notarius role from v0.7.1 to v0.8.1, expose the new
PromptKit transient-retry setting, and document the ConfigKit overlay rename.
This is the third feature in the agreed
[application upgrade sequence](../application-upgrade-sequence.md).
## Problem or Opportunity
Notarius v0.8.0 renamed configuration selection to `--config-overlay` and
`overlays/<name>.yml`, removing the previous flag and lookup directory. It also
introduced configurable provider transport retries. v0.8.1 updates ConfigKit
and PromptKit to v0.4.2 and v0.11.2 without further intentional configuration or
subprocess-contract changes.
The standalone role currently renders schema version 5, supports native imports
and caller-supplied pipelines, and leaves profile assets externally managed.
Those boundaries remain appropriate. The suite, however, still uses the old
downstream selector; its application and dependency pins must not advance yet.
## Scope
- Default the standalone role to Notarius v0.8.1.
- Expose `promptkit.transient_retries` through one nullable role variable.
- Verify existing imports, pipeline composition, profile-source settings, and
cache configuration remain compatible with the target release.
- Update standalone compatibility guidance and focused offline tests.
- Record the reviewed role revision for later coordinated suite integration.
## Non-goals
- Updating suite, collection, consumer, or other application-role pins.
- Migrating suite-owned testing files or Narratio's downstream selector.
- Deploying arbitrary overlay or LLM-profile assets in the generic role.
- Choosing D&D model, retry, timeout, or credential policy.
- Automatic renames, compatibility aliases, cache deletion, forced extraction,
or production validation tasks.
- Upstream application changes, live inference, or operational deployment.
## Target End State
### Installation and Configuration
`notarius_version` defaults to `v0.8.1`. Configuration remains schema version 5.
Preserve existing build, dependency, path, and owner/group/mode interfaces.
The existing Go selection remains unchanged.
Add `notarius_promptkit_transient_retries: null`, documented and declared as an
optional integer in argument specifications. When non-null, serialize it as
`promptkit.transient_retries`. Include it in the parent-section condition so a
retry-only configuration renders correctly. Null means omit the field; zero
disables additional transient attempts. Do not copy PromptKit's default into
role defaults, add a second retry mechanism, or reinterpret existing module
and validator retry settings.
Keep all existing supported native configuration variables. Preserve caller
mapping/list composition and omission of unset optional settings. The role does
not resolve, inspect, or rewrite caller-owned profile or overlay files.
### Overlay Migration Guidance
Document `--config-overlay` and the conventional `overlays/` directory for
operators invoking the new application. The old `--config-profile` and ConfigKit
`profiles/` lookup no longer work. This does not rename PromptKit LLM-profile
sources: `notarius_promptkit_profile_dir`, `notarius_promptkit_profile_file`,
pipeline `llm_profile`, and `--llm-profile` retain their separate meanings.
Caller-owned configuration overlay files must be migrated by their owner. In
this workspace the D&D suite owns its testing overlay, so that migration belongs
to final integration together with Narratio's new selector. Do not add generic
file-moving tasks or broaden this feature to fix the old suite in place.
### Retry and Checkpoint Compatibility
Explain that transport retries are additional attempts per generation and are
separate from pipeline/validator retries. Omission inherits upstream behavior;
operators may explicitly select zero. Later suite planning will review combined
retry and timeout budgets rather than copying old values mechanically.
Document v0.8.1's changed profile-source checkpoint identity: old matching
checkpoint identities are not reused, while source-keyed chunk plans and
published output are unaffected. Leave cache lifecycle with Notarius and do not
delete data or force Narratio stages as part of installing the role.
## Repository Ownership
- `ansible-role-notarius`: version default, optional retry field, argument
specification, template, documentation, and repository-local tests.
- Workspace: feature roadmap, staged plan, progress, and independent review.
- Notarius application: read-only tagged configuration/release contracts.
- Pipeline, collection, consumer, other roles, and assets remain unchanged.
## Constraints and Settled Decisions
Follow the [Ansible house style](../../ansible.md),
[testing house style](../../testing.md), [MVP roadmap](../mvp.md), and
[upgrade sequence](../application-upgrade-sequence.md). Use v0.8.1's contract,
including the intervening v0.8.0 migration notes, not assumptions from a newer
application checkout.
Retain meaningful tests that explicitly install v0.7.0 to prove caller-selected
version behavior. Leave the new retry field unset in those older-version cases;
do not change them merely because the role default advances.
## Simplest Viable Implementation
Update the application version and add one optional variable, argument-spec
entry, and conditional template field. Extend the existing integration fixture
with explicit retry zero and native configuration inspection. No new production
tasks, state probes, compatibility framework, or role-managed assets are needed.
## Rationale and Alternatives
The role manages persistent configuration; application invocation owns overlay
selection. Adding an overlay-selection variable or file-migration tasks here
would confuse those responsibilities. Documenting the breaking invocation
change and coordinating it later preserves independently usable roles and the
existing suite compatibility set.
## Acceptance Criteria
- The default role installs v0.8.1, and native offline validation accepts the
baseline and representative managed configurations.
- Null retry selection is omitted; explicitly supplied zero is rendered and
visible through native effective-configuration inspection. A retry-only
configuration produces its enclosing PromptKit section.
- Existing useful coverage for native import/pipeline composition, profile
configuration, cache settings, selected application version, and supplied Go
executable remains valid. Do not add a comprehensive upstream schema matrix.
- Immediate repeat convergence reports no changes. Tests assert supplied values
and role outcomes, not today's version/catalog defaults or module postconditions.
- Documentation accurately distinguishes configuration overlays from LLM
profiles and describes retry/checkpoint upgrade consequences.
- Syntax/lint and repository integration checks pass without live provider
calls or operational-host access.
- Suite, collection, and consumer pins stay unchanged; the reviewed standalone
revision is recorded for final integration.
## Dependencies and Follow-up Work
Implementation and independent review are complete. Git history preserves the
completed staged plan. Narratio v3 standalone adoption is next. Final integration
owns the coordinated overlay/credential/configuration migration and public suite
dependency updates. No open product decision is required for this narrow scope.
## Implementation Evidence
- Standalone role commits: `b1b922c` (v0.8.1 default and optional retry
interface), `380b6a3` (integration coverage), and `6aef48b` (upgrade
guidance). No production tasks or suite dependencies changed.
- Syntax check and production-profile lint passed. `bash -n` and the local
integration harness passed with native offline configuration validation,
rendered/effective retry checks, older-version and supplied-Go behavior,
import and pipeline composition, and clean immediate repeats. Role and
workspace whitespace checks passed.
- Independent review of all three role commits found no required remediation
or unjustified strengthening of requirements. Syntax, production-profile
lint, shell syntax, whitespace checks, and installed v0.8.1 native
configuration validation passed again during review. The review used the
recorded successful integration run rather than rerunning its host-mutating
scenarios. No remediation document was changed.
- Reviewed standalone revision: `6aef48b`. Narratio adoption and coordinated
suite migration remain separate follow-up work; suite pins are unchanged.
## Upstream References
- [v0.8.1 configuration](https://gitea.maximumdirect.net/eric/notarius/src/tag/v0.8.1/docs/config.md)
- [v0.8.0 migration notes](https://gitea.maximumdirect.net/eric/notarius/src/tag/v0.8.0/docs/releases/v0.8.0.md)
- [v0.8.1 release notes](https://gitea.maximumdirect.net/eric/notarius/src/tag/v0.8.1/docs/releases/v0.8.1.md)

View File

@@ -0,0 +1,234 @@
# Feature 0021: Adopt Narratio v3.0.0 in the Standalone Role
Status: done
## Summary
Update the standalone Narratio role from v2.2.0 to v3.0.0 and align its
configuration interface with the new Audita and Notarius contracts. This is
the fourth feature in the agreed
[application upgrade sequence](../application-upgrade-sequence.md). Suite
integration remains a separate, subsequent feature.
## Problem or Opportunity
Narratio v3 replaces configuration-profile terminology with overlays, replaces
singular downstream credential references with lists, and delegates Audita v2
configuration to Audita. The existing role still exposes retired fields that
v3 rejects. Advancing only the executable would therefore leave callers and
the representative configuration fixture with an incompatible interface.
## Scope
- Default the standalone role to Narratio v3.0.0.
- Align defaults, argument specifications, template, examples, and tests with
the changed downstream configuration fields.
- Document operator migration, ownership boundaries, and native compatibility
consequences without automating session or asset migration.
- Record the independently reviewed role revision for final suite integration.
## Non-goals
- Updating pipeline, collection, consumer, or other application-role pins.
- Deploying downstream applications, changing D&D defaults, or migrating
suite-owned testing overlays and credentials.
- Creating arbitrary overlay assets or selecting Narratio's runtime overlay
through an installer variable.
- Compatibility aliases, dual-version template branches, automatic migration
of existing manifests, cache deletion, or forced stage reruns.
- New production validation, credential discovery, runtime version gates,
forwarding/redaction machinery, or upstream application changes.
- Live providers, operational deployment, or publication.
## Target End State
### Standalone Installation
`narratio_version` defaults to `v3.0.0`. Preserve source-build behavior, Go
selection, service account, filesystem paths, owner/group/mode interfaces, and
the required caller-supplied WhisperX URL. Configuration continues to use the
existing root document shape and one ordinary template task. Unchanged native
fields and caller composition remain supported.
### Audita Interface
Add the following optional variables with null defaults. Field paths below
refer to the root configuration document's `audita` section; upstream prose
also calls this `pipeline.audita`.
| Role variable | Native field | Argument type |
| --- | --- | --- |
| `narratio_audita_credentials` | `audita.credentials` | list of strings |
| `narratio_audita_overlay` | `audita.overlay` | string |
| `narratio_audita_proposal_profile` | `audita.proposal_profile` | string |
| `narratio_audita_validation_profile` | `audita.validation_profile` | string |
Remove these retired role variables and their rendered fields:
- `narratio_audita_llm_api_key`
- `narratio_audita_base_url`
- `narratio_audita_model`
- `narratio_audita_total_llm_concurrency`
- `narratio_audita_proposal_llm_concurrency`
- `narratio_audita_validation_model`
- `narratio_audita_validation_llm_concurrency`
- `narratio_audita_work_dir_retention`
- `narratio_audita_report`
Retain binary, timeout, modules, transcript description, config path, and output
schema variables. Null modules are omitted; explicit `[]` means no correction
modules. Audita owns backend definitions, model/profile contents, concurrency,
reporting, and debug policy. Document migration to Audita's own configuration
without trying to infer replacements for those policies.
### Notarius Interface
Replace `narratio_notarius_config_profile` with
`narratio_notarius_config_overlay`, an optional nullable string rendered as
`notarius.config_overlay`. Preserve supplied empty strings, `default`, and
named selectors exactly; null omits the selector. Selection is independent of
Narratio's own overlay and is not a PromptKit LLM-profile selection.
Replace `narratio_notarius_llm_api_key` with
`narratio_notarius_credentials`, an optional nullable list of strings rendered
as `notarius.credentials`. Preserve other Notarius configuration interfaces,
including cache controls, references, and output mappings.
### Rendering and Credential Ownership
Use `is not none`, appropriate serialization, and parent-section conditions
covering the new variables. Null omits a field; empty lists and strings remain
explicit. Do not copy native defaults into optional role defaults.
Credential lists contain environment-variable/secret-reference **names**, not
secret values. Narratio resolves and forwards them under their exact names.
The role neither resolves credentials nor infers them from downstream files.
Null omits the field and `[]` emits an explicit empty list; Narratio overlays
replace lists rather than append to them. Operators must list every backend
credential needed by the selected Audita configuration, including configured
but unselected backends. Notarius likewise requires names matching its selected
provider configuration. Resolution occurs at pipeline loading, even when a
downstream stage will not execute.
Removing retired variables is a documented breaking role-interface migration.
Do not add alias precedence, version-dependent rendering, or special guards
for old inventory. Users retaining old deployments retain their old role pin.
### Operator Upgrade Guidance
- Replace Narratio `--profile` with `--overlay` and selected `profiles/` files
with `overlays/`. Explicit imports from a directory named `profiles` remain
valid; this is not a blanket filesystem rename or an LLM-profile rename.
- Migrate downstream Notarius selection to `config_overlay` and its selected
files to `overlays/`. Named selection needs a supporting Notarius executable;
v0.8.1 is the tested baseline, not a new unconditional role version gate.
- Audita v2 must be configured independently before running polish. Narratio
does not generate its config or infer downstream overlay/profile selectors.
- Link the tagged manifest migration procedure: back up old manifests and
migrate `effective_config.selected_profile` to `selected_overlay` while
preserving progress/checkpoint state. Do not rewrite immutable remote
snapshots or infer that every stage must rerun.
- Note the native extraction-resume consequence for renamed named Notarius
selectors: the next applicable run regenerates extraction with normal
dependent invalidation. Omitted/base selections do not gain invalidation
solely from this rename. The role does not implement this behavior.
## Repository Ownership
- `ansible-role-narratio`: standalone interface, template, documentation, and
repository-local tests.
- Workspace: roadmap, later staged plan, status, and independent review.
- `../narratio`: read-only authoritative v3.0.0 contracts.
- Pipeline, collection, consumer, assets, and other roles remain unchanged.
## Constraints and Settled Decisions
Follow the [Ansible house style](../../ansible.md),
[testing house style](../../testing.md), [MVP roadmap](../mvp.md), and
[upgrade sequence](../application-upgrade-sequence.md). Use tagged v3.0.0
contracts rather than assuming a newer checkout has the same interface.
Keep meaningful explicit v2.1.0 version-selection and supplied-Go recovery
tests where their baseline inputs remain compatible. Do not turn configurable
version selection into a promise that new configuration fields work on old
applications; new fields stay unset in those cases.
## Simplest Viable Implementation
Change the version default and the affected defaults, argument-spec entries,
and conditional template fields. Adapt existing representative fixtures and
native validation to the new public interface. No additional production tasks,
state probes, file migration, or configuration assembly mechanism is needed.
## Rationale and Alternatives
Expose the native v3 interface directly instead of retaining aliases or
translating legacy Audita tuning into guessed backend/profile definitions.
This preserves application ownership and avoids a compatibility framework in
the generic installer. Coordinated suite migration can then make explicit D&D
policy choices against already-reviewed standalone roles.
## Acceptance Criteria
- The default role installs Narratio v3.0.0; native offline validation accepts
baseline and representative rendered configuration.
- Added and renamed fields agree across defaults, argument specifications,
template, examples, and documentation. Retired native fields are not emitted.
- Focused behavioral cases demonstrate null omission, supplied credential-name
lists, explicit empty lists, named/empty downstream selectors, and existing
meaningful falsey and artifact-composition behavior. Keep this representative,
not a matrix of every native rule or a snapshot of today's defaults.
- Native validation uses synthetic credential values supplied only to the test
process as needed; managed configuration contains names, not values. No live
provider calls or reimplementation of upstream forwarding/redaction tests is
required. Preserve existing useful log checks without expanding their scope.
- Immediate identical role application reports no changes. Selected-version
and supplied-Go/missing-binary outcomes remain covered.
- Syntax/lint and local repository integration checks pass. No operational
controller, target deployment, downstream pipeline execution, or real keys
are prerequisites for standalone-role acceptance.
- Documentation explains breaking variable changes and links upstream upgrade
procedures. No production validation or automatic migration has been added.
- Suite, collection, and consumer pins remain unchanged. Independent review
records the standalone revision for coordinated integration.
## Dependencies and Follow-up Work
Standalone adoption and independent review are complete for all four upgraded
applications. Git history preserves the completed staged plan. The next,
coordinated integration feature owns D&D
configuration, credentials, overlay assets, coordinated dependency pins,
collection assembly, and consumer migration guidance. It must deliberately
review retry/timeout budgets rather than copying retired tuning mechanically.
## Open Questions
None identified for this standalone scope.
## Implementation Evidence
- Standalone role commits: `a28f22c` (v3 interface and migrated fixtures),
`45f6836` (selector and credential-list coverage), and `3c0700b` (upgrade
guidance). Production tasks, suite dependencies, collection, and consumer
remain unchanged.
- `bash -n` and the local integration harness passed. The harness includes
syntax check and production-profile lint and exercised native offline
baseline, named, and explicit-empty validation, selected v2.1.0 behavior,
supplied-Go recovery, synthetic credential loading, and clean immediate
repeats. Role and workspace whitespace checks passed.
- Independent review on 2026-09-29 found no required remediation or unjustified
strengthening of requirements. Syntax checks, production-profile lint, shell
syntax, whitespace checks, and native v3.0.0 configuration validation passed
again during review. The review used recorded successful integration runs
rather than rerunning their host-mutating scenarios. No remediation document
was changed.
- Reviewed standalone revision: `3c0700b`. Coordinated suite migration remains
separate follow-up work; suite, collection, and consumer pins are unchanged.
## Upstream References
- [Narratio v3.0.0 release](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/releases/v3.0.0.md)
- [Configuration](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/config.md)
- [Audita integration](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/integrations/audita.md)
- [Notarius integration](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/integrations/notarius.md)
- [Operator migration procedures](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/operations.md)

View File

@@ -0,0 +1,300 @@
# Feature 0022: Integrate the Reviewed Application Upgrades
Status: done
## Summary
Bring the four reviewed standalone upgrades into the D&D pipeline role,
collection, and deployment consumer as one compatible configuration set.
This completes the agreed
[application upgrade sequence](../application-upgrade-sequence.md).
## Problem or Opportunity
The standalone roles now support the new releases, but the suite intentionally
retains its previous pins and configuration. Audita still receives v1 settings;
Narratio and Notarius testing selection still uses retired profile terminology.
Updating executable versions alone would break the deployed configuration.
## Scope
- Adopt the reviewed application/role versions together.
- Provide Audita v2 backend configuration and suite-owned PromptKit profiles.
- Migrate Narratio credential forwarding and Narratio/Notarius testing overlays.
- Preserve D&D processing, artifact composition, storage/publishing, shared
filesystem, and operator-access behavior.
- Update the collection snapshot, public dependency manifests, consumer pins,
operator guidance, and focused offline integration coverage.
## Non-goals
- Deploying to the operational controller or `pipeline-dnd` host, running real
transcripts, or calling inference, WhisperX, or object-storage services.
- New models, prompts, artifact families, extraction lanes, or processing policy
beyond migration choices expressly approved here.
- Automatic manifest conversion, cache deletion, forced stage reruns, broad
directory cleanup, compatibility aliases, or runtime version/integrity probes.
- Changing generic standalone-role ownership or adding production validation.
- A newly tagged collection release or replacement of published 0.1.0 assets.
This feature updates the public development compatibility set; formal release
packaging remains a separate decision.
## Target End State
### Coordinated Versions and Distribution
| Application | Suite version | Reviewed standalone role revision |
| --- | --- | --- |
| Scriptorium | v0.15.0 | `b174c8c` |
| Audita | v2.0.1 | `c3dd59f` |
| Notarius | v0.8.1 | `6aef48b` |
| Narratio | v3.0.0 | `3c0700b` |
| Seriatim | v1.5.0, unchanged | existing v0.1.0 role pin |
Dependency manifests use full immutable revisions resolved from these reviewed
commits. The pipeline role remains authoritative; the collection imports its
completed revision through the established public Gitea subtree workflow, never
by editing `roles/pipeline` directly. The collection continues bundling the
pipeline role and declaring standalone role dependencies separately.
Relevant reviewed commits must be published to their existing public origins
before downstream manifests/subtree imports depend on them. Publication of the
required Git commits is part of the eventual implementation workflow, not this
roadmap-writing pass. Do not rewrite tags or publish unrelated changes.
The consumer keeps its minimal playbook and host-vars organization. Its role
and collection pins select the same compatibility set. No controller install
or remote playbook execution is an acceptance gate.
### Audita Backend and Profile Ownership
The pipeline role supplies `audita_backends`, profile selection, and schema-2
settings to the standalone Audita role. The pipeline owns the missing profile
assets under `/usr/local/etc/audita/profiles/`, using its runtime owner/group and
configuration modes. This directory contains PromptKit LLM profiles, not
ConfigKit overlays; it must not be renamed to `overlays`.
Approved suite interface:
- `dnd_pipeline_audita_backends`: native backend map, defaulting to one backend
named `dnd`, endpoint `https://inference.ai.rakestrawhome.com/v1`, credential
reference `AUDITA_LLM_API_KEY`, and shared concurrency `4`. Omit queue capacity
to inherit the native default.
- `dnd_pipeline_audita_profiles`: a native profile mapping keyed by file/profile
ID, with complete `dnd-proposal` and `dnd-validation` entries. Each selects
backend `dnd`, model `google/gemma-4-31b-it`, and per-attempt
`timeout_seconds: 900`. Other model controls inherit native behavior.
- `dnd_pipeline_audita_llm_proposal_profile` and
`dnd_pipeline_audita_llm_validation_profile` select those respective IDs.
Render each supplied profile as one safely serialized native mapping with its
matching ID. Document profile-map keys as filename-safe IDs. Do not introduce
per-provider templates, profile merging, or discovery of external assets.
Callers can compose native maps in inventory and replace the supplied maps.
As with existing managed secrets, removing a map entry does not imply pruning
arbitrary files; only selected profiles participate in normal execution.
Preserve the ordered module sequence, `audita-v1` output, chunking values,
thresholds, context description, and normalization limits. Convert normalization
duration defaults from `3s`, `3s`, and `240s` to numeric `3.0`, `3.0`, and
`240.0` seconds. Preserve meaningful setting names where native semantics are
unchanged; update argument types accordingly.
Remove retired per-role endpoint/model/credential/concurrency/retry variables
in favor of the native backend/profile interface. Document their replacements;
do not infer a conversion from arbitrary old inventory. Remove diagnostics
retention; leave debug disabled through native defaults. Retain the existing
diagnostics work-directory choice where still supported. Reporting follows
Audita's native configuration; Narratio consumes its ordinary output contract.
Production and testing continue using the same Audita endpoint and model.
No separate Audita testing overlay is needed for an identical configuration.
### Credential Lists and Overlay Selection
Replace the suite's singular Narratio Notarius credential variable with
`dnd_pipeline_narratio_notarius_credentials`, default `[OPENROUTER_API_KEY]`.
Add `dnd_pipeline_narratio_audita_credentials`, default `[AUDITA_LLM_API_KEY]`.
Pass both through the reviewed Narratio role's native list variables. These
lists contain names, never values, and can be replaced with `[]`. Operators
overriding Audita backends must explicitly list all referenced credentials;
the suite does not inspect configurations to discover names.
Preserve `dnd_pipeline_secrets`, existing secret names, Vault references,
protected secret directory/files, and ordinary world-readable nonsecret
configuration. No credential rotation, secret relocation, or forwarding logic
is required in Ansible.
Deploy the suite-owned testing files at:
- `/usr/local/etc/narratio/overlays/testing.yml`
- `/usr/local/etc/notarius/overlays/testing.yml`
Narratio testing sets `notarius.config_overlay: testing`; production omits the
selector. Notarius remains enabled in both modes. Its production pipeline
continues selecting `gpt-terra-latest`, testing selects `gpt-luna-latest`, and
the existing caller-overridable pipeline map/ID behavior remains intact.
Scriptorium testing still selects `gemini-flash-latest`; production continues
using the prompt assets' selections. Retain separate artifact/family fragments.
Use Narratio `--overlay testing` and Notarius `--config-overlay testing` in
tests and operator examples. Deploy the new files declaratively; leave ignored
legacy `profiles/testing.yml` files alone and document that they are obsolete.
Do not delete `profiles/` directories or conflate them with PromptKit profiles.
### Runtime Paths and Existing Suite Behavior
Keep Narratio's explicit downstream binaries/config paths, output handoffs,
Notarius `/var/cache/notarius` roots and resume behavior, shared writable
directories/ACLs, service user, operator enrollment, and S3/publishing choices.
Audita profiles are configuration assets, not shared output directories.
No new runtime storage architecture is required.
### Retry and Timeout Policy
Retain the previously selected per-attempt Audita profile timeouts of 900
seconds while inheriting the new applications' retry,
repair, and whole-operation defaults. Expose nullable suite pass-throughs for
`audita_llm_transient_retries`, `audita_llm_repair_attempts`,
`audita_llm_operation_timeout`, `notarius_promptkit_transient_retries`, and
`scriptorium_transient_retries`, prefixed with `dnd_pipeline_` in the public
suite interface. Null means omit; explicit zero is preserved where valid.
Do not mechanically translate old `max_retries: 3` into both transport retries
and structural repairs. Preserve explicitly authored Notarius module retries;
they are a separate behavior. Keep Narratio stage timeouts unchanged. Explain
the nested budgets and the changed semantics, not a guarantee of identical
provider cost or timing.
## Repository Ownership
- `ansible-role-dnd-pipeline`: suite defaults, argument specs, dependency wiring,
Audita profile assets, testing overlays, documentation, and integration tests.
- `ansible-collection-dnd`: imported pipeline snapshot, dependency manifest,
collection tests, and compatibility guidance.
- `rakestraw-ansible`: matching dependency pins and deployment guidance; adjust
host variables only where required. Preserve Vault content and unrelated
inventory. Keep the hosts-and-roles playbook minimal.
- Standalone role repositories: reviewed commits are reused/published, not
redesigned. Application and campaign/prompt repositories are read-only
contracts/assets unless a concrete incompatibility is raised for discussion.
- Workspace: roadmap, later staged plan, decisions, progress, and review.
## Constraints and Settled Decisions
Follow the [Ansible](../../ansible.md), [testing](../../testing.md), and
[planning](../../planning.md) policies, [MVP roadmap](../mvp.md), and
[upgrade sequence](../application-upgrade-sequence.md). New D&D policy remains
in the pipeline role; optional generic application defaults remain null.
## Simplest Viable Implementation
Update dependency variables/pins and existing templates, add an ordinary
Audita profile directory task and one looped template deployment, and change
testing destinations to `overlays/`. Reuse existing declarative convergence,
secret delivery, and collection assembly. No production validation, state
fingerprints, migration framework, or generated credential inference is needed.
## Acceptance Criteria
- Pipeline and collection installations produce a compatible set of the four
upgraded applications while Seriatim remains unchanged.
- Native offline inspection/validation accepts Audita settings and selected
profiles, Notarius base/testing configurations, Scriptorium configuration,
and Narratio base/testing composition with synthetic credential inputs.
Direct Audita validation receives credential environment variables explicitly:
it does not bootstrap Narratio's secrets directory on its own.
- Focused cases prove caller-supplied backend/profile configuration and
credential lists, testing selection, and existing important composition and
path handoffs. Assert supplied values, not fixed copies of today's defaults.
- Immediate repeated convergence is clean. Existing meaningful shared-user,
cache, artifact-composition, and installed-collection behavior remains covered
without expanding into upstream module/runtime regression matrices.
- Collection build/install and consumer syntax checks use the established
public dependency manifests. No sibling application/role checkout is needed
by an external consumer. Required referenced commits exist on public Gitea.
- Consumer inventory retains comments/Vault references for unknown secrets;
no actual keys or operational deployments are required for completion.
- Guidance covers breaking inventory fields, new CLI selectors, obsolete
testing-file locations, and upstream manifest migration. Back up and migrate
local provenance without deleting progress or editing immutable snapshots;
document normal named-selector invalidation rather than forcing reruns.
## Open Questions
None. The user approved deferring to application defaults wherever possible,
with nullable inventory overrides, and confirmed retaining the existing
900-second Audita per-attempt policy. Do not freeze native retry, repair, or
operation-deadline defaults in suite variables. Operators should note that an
attempt may consume the entire logical-operation budget; these are separate
controls, not additive timeout guarantees.
## Dependencies and Follow-up Work
Features 0018–0021 provide the reviewed standalone revisions. Implementation,
independent review, and remediation are complete. Git history preserves the
completed staged implementation plan. Actual deployment,
session migration, live processing, and a formal tagged release are separate
operator actions, not completion gates for this feature.
## Implementation Evidence and Review Handoff
On 2026-09-29, the four reviewed standalone role revisions were published to
their existing public Gitea `origin/main` branches and verified after fetch:
Scriptorium `b174c8c2990bb79f8149d8f288c5e06ccb42bd73`, Audita
`c3dd59f5ac9b942306ffe540ae9e71d493998137`, Notarius
`6aef48b7e12e3651971444b8c224d96ff1879e6c`, and Narratio
`3c0700b5323293d44e3b1e67a50074d82d7a3bff`.
The pipeline role at public revision
`ea8b09e190419586ede6df3815d1ea999a0f4391` passed `bash -n`, its full
`tests/integration` harness twice (configuration migration and representative
override coverage), and `git diff --check`. The collection imported that exact
public revision by subtree; public collection revision
`3d77eb382bcb4c1742015d3c32e23630bb8c73bf` passed `bash -n`, its full
artifact-based `tests/integration`, and `git diff --check`. Both harnesses used
synthetic credentials and offline native application validation, with clean
repeats. The consumer's local commit
`f694dad9426ee21138b175e44a3855d42be99d4b` passed public dependency
installation into disposable paths, real-inventory `--list-hosts` limited to
`pipeline-dnd`, `--syntax-check`, and `git diff --check`. Its commit was not
pushed. Seriatim and native collection pins remain unchanged, and manifests
across the three repositories agree.
The local integration harnesses converged only the development installation;
there was no operational deployment or live inference, transcription, or object
storage call. Vault values and target access were not needed or verified.
After the override harness passed, a formatting-only split of its fixture JSON
line was checked with `bash -n`, JSON parsing, and `git diff --check` without
rerunning the long integration harness. Independent review subsequently found
the three issues resolved below. No tagged release was created.
## Remediation Follow-up
The three independent-review findings are resolved; see
[remediation evidence](../remediation.md). Public pipeline `37b1cf6` and
collection `b3bc045` remove default-identity assertions and correct migration
and credential guidance. Local consumer `15f0f4e` selects the corrected public
snapshot. Shell/whitespace checks, pipeline and installed-collection syntax and
lint, collection build/install, and real-inventory consumer target/syntax checks
passed. Full host-mutating convergence was not rerun for these documentation
and test-only changes. Application versions/defaults and runtime behavior are
unchanged.
## Closeout
Closed on 2026-09-29 after independent review and resolution of all three
findings. This completes the agreed application upgrade sequence. The active
implementation plan is retired; no additional implementation is required for
this feature. Consumer commits remain local. Operational upgrade, session
migration, live production/testing checks, and any new tagged release require
separate operator action and were not performed as part of closeout.
## Upstream References
- [Audita v2 migration](https://gitea.maximumdirect.net/eric/audita/src/tag/v2.0.1/docs/migrations/v2.md)
- [Audita configuration](https://gitea.maximumdirect.net/eric/audita/src/tag/v2.0.1/docs/config.md)
- [Narratio v3 release](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/releases/v3.0.0.md)
- [Narratio operations and migration](https://gitea.maximumdirect.net/eric/narratio/src/tag/v3.0.0/docs/operations.md)
- [Notarius v0.8.0 migration](https://gitea.maximumdirect.net/eric/notarius/src/tag/v0.8.0/docs/releases/v0.8.0.md)
- [Scriptorium v0.14.0 migration](https://gitea.maximumdirect.net/eric/scriptorium/src/tag/v0.14.0/docs/releases/v0.14.0.md)

View File

@@ -0,0 +1,206 @@
# Feature 0023: Adopt Narratio v3.1.0 and Forward Scriptorium Credentials
Status: done
## Summary
Update the standalone Narratio role and D&D pipeline to Narratio v3.1.0 and
expose its Scriptorium credential list. Deliver the coordinated change through
the collection and existing deployment consumer without deploying to a host.
## Problem or Opportunity
The operator's deployment to `pipeline-dnd` failed during trim bounds generation
with Scriptorium reporting HTTP 401. Narratio v3.0.0 filtered provider keys out
of the child environment without offering a public Scriptorium credential
selection. Analyze had the same forwarding gap. Provisioning a key through
Ansible alone could not repair that boundary.
Upstream has released explicit Scriptorium credential forwarding in v3.1.0.
The original report is preserved in Narratio commit `9389f69`;
the upstream change is `44a3186`, with release documentation at `40cbf42`.
These are planning references, not substitutes for the released application tag.
## Scope
- Adopt Narratio v3.1.0 in the standalone role and suite version selections.
- Expose its native credential-list field through the standalone role and
supply overrideable D&D defaults through the pipeline role.
- Refresh the Narratio role dependency, public pipeline subtree snapshot,
collection dependency manifest, and existing consumer pins together.
- Extend existing configuration/composition coverage and document operator
credential requirements and normal retry behavior.
## Non-goals
- Changing upstream applications, other application versions, models, prompts,
profile selections, or the existing filesystem and credential-storage policy.
- Adding a credential loader, wrapper, environment file, provider discovery,
or per-stage credential-selection interface.
- Live inference, deployment to a controller or `pipeline-dnd`, credential
verification against providers, or modifying Vault contents.
- Publishing new Ansible release tags or collection release artifacts.
- Reimplementing upstream credential forwarding, redaction, or checkpoint
behavior in Ansible or its test suites.
## Target End State
### Standalone Narratio role
`narratio_version` defaults to `v3.1.0`. The optional public variable
`narratio_scriptorium_credentials` defaults to null, is documented as a list
of strings, and renders `scriptorium.credentials` in the native root pipeline
file only when non-null. An explicit empty list renders `credentials: []`;
nonempty lists preserve the caller's exact credential names. Include the field
in the enclosing Scriptorium-section condition so it works independently of
other optional Scriptorium variables. No provider-specific default belongs in
the standalone role.
### D&D pipeline policy
`dnd_pipeline_narratio_version` selects `v3.1.0`.
`dnd_pipeline_narratio_scriptorium_credentials` defaults to
`[OPENROUTER_API_KEY]` and is passed through the existing Narratio dependency
variables. Inventory can replace the list, including with `[]`, or set null
to omit the field through the standalone role's interface.
The testing overlay inherits this list; no duplicate testing-specific setting
is needed for the currently selected profiles. The existing Notarius reference
to the same key remains independent. Operators selecting different providers
can supply the corresponding names through the ordinary inventory interface.
Credential bytes continue to come from Narratio's process environment or its
existing secrets mechanism. `dnd_pipeline_secrets` remains an optional managed
file-provisioning mechanism, not the only valid credential source. No new secret
file or migration is needed where `OPENROUTER_API_KEY` is already provisioned.
### Upstream contract and operator handoff
Narratio calls the field `pipeline.scriptorium.credentials` internally; the
root pipeline YAML uses `scriptorium: {credentials: [...]}` without an extra
`pipeline:` wrapper. The list applies to trim, analyze (including character
families), and render-debug calls. It forwards names and resolved values without
overriding Scriptorium's own provider/profile selection.
Upstream resolves selected names to nonempty values at configuration load,
including for commands that do not execute Scriptorium. Tests and operator
guidance must account for that existing contract. Omitted/null/empty lists
forward nothing; a native overlay replaces the full list. After upgrading and
provisioning the selected key, retry failed trim/analyze normally; do not force
successful work solely because a credential was added or rotated. See the
upstream references below for the authoritative behavior.
## Repository Ownership
- `ansible-role-narratio`: version default, public variable, argument spec,
template, documentation, and focused configuration tests.
- `ansible-role-dnd-pipeline`: suite version/credential defaults, dependency
wiring and pin, documentation, and composition coverage.
- `ansible-collection-dnd`: exact public pipeline subtree import, matching
dependency manifest, and installed-artifact validation.
- `rakestraw-ansible`: updated consumer dependency pins and concise upgrade
guidance only; preserve its minimal playbook, inventory, and Vault content.
- Workspace: feature tracking, later staged plan, and review evidence.
- Narratio and the remaining applications/assets: read-only upstream contracts.
## Constraints and Settled Decisions
Follow the [Ansible](../../ansible.md), [testing](../../testing.md), and
[planning](../../planning.md) policies and the [MVP architecture](../mvp.md).
Preserve generic application roles versus opinionated suite policy. Reuse the
existing declarative source-build and template tasks; add no production checks.
Required dependency commits must be public before external consumer use; subtree
imports use public Gitea, not sibling paths. Do not alter unrelated pins.
## Simplest Viable Implementation
Add one nullable standalone configuration variable and its ordinary template,
argument-spec, and documentation entries. Add one suite default and dependency
mapping. Advance the Narratio version and coordinated dependency pins, then
reuse the existing collection import and consumer refresh workflow. No new
production task or persistent state is needed.
## Acceptance Criteria
- The standalone role and assembled suite build the released v3.1.0 source.
Any version assertion explicitly supplies the version under test rather than
freezing the current default.
- Representative explicit credential names reach the deployed native
configuration; null omission and explicit `[]` are supported. Extend existing
cases rather than adding a separate exhaustive matrix.
- Suite composition preserves an explicitly supplied credential list in base
and testing configurations. Use synthetic credential values for offline
native validation; do not assert today's default list as a permanent invariant.
- The real role and installed collection pass their existing relevant
validation, including immediate repeated convergence with no changes.
Credential-forwarding internals and provider authentication remain upstream
responsibilities; no live service or new subprocess simulation is required.
- Collection and consumer manifests resolve the coordinated public revisions;
consumer host listing/syntax checks work without deployment or Vault
decryption. Leave the existing hosts-and-roles playbook unchanged.
- Guidance explains load-time credential requirements, existing environment or
file provisioning, dependency refresh, and ordinary retry after the fix.
## Dependencies and Follow-up Work
The public Narratio v3.1.0 tag was verified on 2026-09-29 at
`40cbf4243838b0a1db6caf4c8f790d914ccb96cc`, matching the reviewed release
documentation and configuration contract. The release prerequisite is satisfied.
Use that release rather than substituting a moving branch.
The completed staged implementation plan is preserved in Git history.
Required Ansible dependency commits are public as recorded below. Operational
deployment and a paid/live smoke run remain separate operator activities, not
feature-completion gates.
## Implementation Evidence
Implementation completed on 2026-09-29. The public Narratio role revision is
`758aed7a74c9a64ad02e13ff551b4f7aea16b3af`; the public D&D pipeline role
revision is `0f841fd91ffc533aeec0ec688e81c24bd187a845`; the public
collection revision is `002e86c9deb90820a2f1c2f55e1f4d8be59b7c96`.
The consumer revision `67cc22f37f042fa12ada09547efa677022242284` is
committed locally and not published, preserving its earlier local commits.
The collection's imported pipeline Git tree exactly matches the public source
revision. No release tag or artifact was created.
The Narratio role, pipeline role, and collection each passed `bash -n
tests/integration`, their full `./tests/integration` harnesses, and `git diff
--check`. The role and collection harnesses passed on their first runs. The
pipeline harness's first run encountered a public Git HTTPS timeout; an
unchanged retry passed, including native base/testing configuration inspection
and a zero-change repeat. The consumer installed the collection manifest's D&D
dependencies and exact collection revision in disposable paths; `--list-hosts`
selected only `pipeline-dnd`, `--syntax-check` passed, and `git diff --check`
passed. No operational controller or target host was contacted.
No implementation scope deviation was needed. Offline configuration and
convergence checks do not prove that the
operator's actual key is valid or that a live trim request will succeed.
## Independent Review and Closeout
Closed on 2026-09-29 after independent review found no actionable code-quality
issues or implementation gaps. Null omission, explicit empty lists, suite
credential selection, testing-overlay inheritance, and coordinated dependency
pins match the approved feature. No additional production machinery was added.
The imported pipeline Git tree matches the authoritative source exactly.
Independent shell syntax, whitespace, role syntax/lint, collection build/install,
public role dependency installation, and real-inventory consumer target/syntax
checks passed. Review used the recorded full integration and clean-repeat
results rather than rerunning host-mutating convergence. No operational host or
live provider was contacted. No remediation document change was needed.
The active plan is retired. Consumer and workspace commits remain local;
operational deployment and provider-key validity remain outside this closeout.
## Open Questions
None identified.
## Upstream References
- [Narratio v3.1.0 release notes](../../../../narratio/docs/releases/v3.1.0.md)
- [Scriptorium credentials](../../../../narratio/docs/config.md#scriptorium-credentials)
- [401 troubleshooting](../../../../narratio/docs/troubleshooting.md#scriptorium-returns-http-401-during-trim-or-analyze)

View File

@@ -1,14 +1,12 @@
# Implementation Plan
Status: pending
No implementation plan is currently active.
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`.
[Feature 0023](features/0023-narratio-scriptorium-credentials.md) was closed on
2026-09-29 after implementation and independent review with no actionable
findings. Its roadmap retains the completion evidence; Git history preserves
the completed staged implementation plan.
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).
Select and approve the next unit of work before replacing this notice with a
new staged implementation plan.
Discuss and select the next unit of work before preparing another plan.
Operational deployment and live provider validation remain separate operator
activities and are not authorized by this notice.

View File

@@ -14,8 +14,10 @@ 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
processing pipeline on a single supported host. Operators or unattended
automation invoke Narratio commands either under the dedicated `narratio`
runtime identity or under an explicitly selected existing human account that
belongs to the `narratio` group, processing D&D session recordings into
transcripts and related artifacts.
## Locked Decisions
@@ -104,6 +106,13 @@ role will manage the native configuration needed to connect to it.
- The collection bundles and exposes the independently developed suite-level
role as `rakestraw.dnd.pipeline`, providing one opinionated interface for
consumers.
- The collection incorporates the pipeline role at `roles/pipeline` as a
squashed Git subtree. The standalone pipeline repository remains
authoritative; maintainers change and validate the role there, then import
a reviewed commit into the collection rather than editing the subtree copy.
- The subtree makes the collection artifact self-contained for its bundled
role without requiring submodule initialization, symbolic links, sibling
repositories, or custom synchronization tooling.
- The pipeline role owns compatible application-version selection,
cross-application configuration, D&D campaign deployment, prompt-library
deployment, operator access, the pipeline-wide secret-delivery policy, and
@@ -133,6 +142,10 @@ role will manage the native configuration needed to connect to it.
collection dependencies. During active development, the Git roles are
pinned to reviewed commits; released manifests replace those commits with
immutable role release tags.
- The collection supplies one consumer-facing root `requirements.yml` that
combines those same Git-hosted role pins with the shared collection
dependencies. Its Galaxy metadata separately declares the native collection
dependencies that Ansible can resolve while installing a collection.
- The pipeline role composes the five roles through ordinary Ansible role
dependency metadata. It exposes suite-prefixed variables for the small set
of values the suite must coordinate, and does not duplicate every downstream
@@ -170,13 +183,24 @@ application-role releases in one source repository.
- Development dependency manifests may temporarily refer to branches or
commits while the roles are changing rapidly.
- The projects' public repositories beneath
`https://gitea.maximumdirect.net/eric/` are the authoritative release
sources. Standalone roles are published through immutable Git tags.
- Every released dependency manifest must pin each Git-hosted role dependency
to an immutable role release tag.
- The collection release is the compatibility record for the exact set of
application-role versions it composes.
- A collection release consists of its immutable repository tag, matching
Gitea release, and the `ansible-galaxy collection build` archive produced
from that tagged tree and attached to the Gitea release.
- Collection integration tests must install and exercise the same pinned role
combination delivered to consumers, starting from an environment in which
the dependencies are not already installed.
- Collection integration tests build and install the collection artifact into
isolated Ansible paths, resolve `rakestraw.dnd.pipeline`, validate one
representative assembled deployment through native application interfaces,
and confirm immediate convergence. Detailed pipeline feature matrices remain
the standalone pipeline role's testing responsibility.
- Updating one application role in the suite requires updating its pinned
version in the collection, validating the assembled suite, and releasing a
new collection version. Unrelated application-role repositories remain
@@ -186,38 +210,106 @@ 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 an existing human
account selected through the pipeline role's
`dnd_pipeline_operator_users` list. The list defaults to empty.
- Every selected human account must exist before pipeline convergence. The
role adds selected accounts to the runtime group with additive supplementary
membership and does not create accounts, replace other group memberships,
or manage omitted accounts.
- Removing a name from `dnd_pipeline_operator_users` does not revoke existing
membership. Account and access removal remain outside the MVP until an
explicit lifecycle policy is selected.
- Newly granted supplementary membership may require the operator to begin a
new login session before it becomes visible to that session.
- 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 lives beneath the conventional
`/usr/local/etc/narratio/secrets` subdirectory owned by
`narratio:narratio`, with directory mode `0750` and file mode `0640`.
Membership in the `narratio` group is an explicit authorization to use the
suite's shared credentials. This deliberately differs from Narratio's
general single-user `0700` and `0600` recommendation while retaining no
world access. Ordinary configuration contains only credential reference
names.
- The pipeline role exposes one empty-by-default credential mapping from valid
environment-variable names to string file contents. Supplied entries manage
the corresponding files; omitted names remain unmanaged. Credential values
are expected to come from encrypted inventory such as Ansible Vault and are
suppressed from task output. Credential removal and directory mirroring are
outside the MVP.
- Narratio's native ConfigKit secrets bootstrap owns loading these files and
process-environment precedence. The suite does not add a wrapper, shell
profile, service environment file, or parallel credential loader.
- The suite coordinates Audita proposal and validation on the
`AUDITA_LLM_API_KEY` reference and selects `OPENROUTER_API_KEY` for
Notarius's production extraction profile. Narratio v2.1.0 resolves those
typed references and forwards only the selected credentials to the
corresponding subprocesses.
- [Decision 0002](../decisions/0002-shared-readable-pipeline-filesystem-policy.md)
records the complete rationale and boundary for this policy.
### Narratio configuration
@@ -239,6 +331,54 @@ 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. Narratio v2.1.0 requests reuse
of compatible recorded checkpoints during ordinary extraction; forced
extraction omits checkpoint loading and refreshes the active chunk plan.
- 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.
- The D&D suite selects its Backblaze-compatible S3 archive, typed
`OBJECT_STORAGE_KEY_ID` and `OBJECT_STORAGE_KEY` references, maximum S3 audio
caching, run publication, human-facing transcript and artifact outputs, and
cleanup of successfully published workspace state. Feature 0015 owns the
exact overrideable defaults and publication set.
- Accepted Notarius lane outputs remain addressable inside Narratio as
`narratio.extraction.<output_key>` sources. Future analyze-stage Scriptorium
artifacts may consume those sources directly; publishing an extraction lane
to a stable remote destination is an independent policy choice.
### Execution model
@@ -255,19 +395,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 suite-managed restricted credentials
- `/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 +423,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
@@ -286,14 +434,6 @@ remain to be designed.
## Design Work Still Open
The following areas require investigation and decisions before implementation:
The following area requires 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
- 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,144 @@
# Feature 0006 Remediation Review
# Feature 0022 Remediation Review
Status: resolved
Reviewed implementation commits:
Reviewed on 2026-09-29:
- Pipeline `8ea8621` and `ea8b09e`.
- Collection subtree import through `a78c309` and assembly `3d77eb3`.
- Consumer `f694dad`.
- `b515968 Compose the D&D pipeline roles`
- `61869d1 Add focused pipeline composition coverage`
The production wiring implements the approved coordinated versions, Audita
backend/profile assets, credential lists, overlay paths, and nullable retry
controls. The collection's imported pipeline tree exactly matches the source
role. The following test-policy and operator-documentation issues were found
and have now been addressed as recorded below.
Git history preserves the previously resolved Feature 0013 remediation record.
Remediation commit:
## Finding 1: New assertions freeze unconfigured suite defaults
- `4ea4358 Clean up pipeline composition review findings`
Priority: P2
Owners: pipeline role and collection tests.
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.
Locations:
- `ansible-role-dnd-pipeline/tests/integration:172`–173.
- `ansible-collection-dnd/tests/integration:104`–105 and 108–109.
The review identified two repository-quality findings.
The new baseline assertions require specific Audita profile IDs and Narratio
credential lists, but the cases do not explicitly supply the corresponding
selection/list variables. Supplying synthetic values in `dnd_pipeline_secrets`
does not select the credential lists. These assertions therefore fail when
legitimate defaults change, even if installation and caller overrides work.
## Finding 1: Remove the Misleading Placeholder README Sentence
Required correction: remove redundant default-identity assertions from the
baseline smoke case, or explicitly supply the relevant public inputs and
assert those values. The pipeline already has a useful custom-credential
override case; prefer reusing its coverage. Keep native validation and clean
repeats. Do not replace literals by reading role defaults into expectations;
that would still test implementation identity rather than caller behavior.
Severity: low
This strengthens acceptance beyond the user's state-based testing policy.
The approved plan explicitly asked for supplied-value tests, not default
snapshots.
`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.
## Finding 2: Upgrade guidance confuses configuration with session migration
The supported-platform summary also names Ubuntu 26.04 without recording the
roadmap's `amd64` and `arm64` boundary.
Priority: P2
Owners: pipeline README and consumer deployment guidance.
### Required Remediation
Locations:
- `ansible-role-dnd-pipeline/README.md:166`–168 and 337–338.
- `rakestraw-ansible/docs/pipeline-dnd.md:86`–104.
- 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.
The pipeline links “Audita's v2 manifest migration” to Audita's configuration
migration guide, but does not identify Narratio's actual session-manifest
migration. The consumer likewise refers to “Audita manifests” and only
generically warns about Narratio manifests. The roadmap specifically requires
guidance on backing up and migrating local provenance while preserving
progress and immutable snapshots. Existing Narratio manifests containing
`effective_config.selected_profile` are rejected by v3.
### Resolution
Required correction:
- Describe Audita's change as a configuration/backend/profile migration.
- Link Narratio v3's exact operations section
`#migrating-manifest-overlay-provenance`; briefly explain backup and
`effective_config.selected_profile` → `selected_overlay` (or removal as
upstream permits), preserving stage/checkpoint state and leaving immutable
remote snapshots unchanged. Do not add automatic migration or forced reruns.
- Correct or remove the stale claim that Notarius v0.8.1 selects PromptKit
v0.10.0. Its tagged release specifies v0.11.2; prefer linking upstream release
notes over duplicating dependency/catalog versions.
The retained sentence was removed, and the introduction now records the
supported `amd64` and `arm64` architectures without expanding the role's
claimed scope.
This is a missing operator handoff, not a request for additional runtime code.
## Finding 2: Give the Isolated Dependency Path Resolution Priority
## Finding 3: Documentation makes managed secret files mandatory
Severity: low
Priority: P2
Owners: pipeline README and consumer deployment guidance.
`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:
Locations:
- `ansible-role-dnd-pipeline/README.md:160`–163.
- `rakestraw-ansible/docs/pipeline-dnd.md:69`–71.
```sh
export ANSIBLE_ROLES_PATH="$(dirname "$repository_root"):$test_tmp/roles"
```
The new text requires each credential to be supplied through
`dnd_pipeline_secrets`. Runtime behavior does not require that: Narratio can
resolve listed names from its process environment or existing secret files.
The README's existing managed-credentials section already describes environment
precedence and an empty default secrets map.
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 correction: require the credential names in the forwarding lists,
but describe managed secret files as the suite-supported provisioning option,
not the only permitted source. Preserve the consumer's chosen Vault workflow
without imposing it on every standalone suite user. No code or new tests are
needed for this wording correction.
### Required Remediation
This is an unintended documentation-level strengthening of the requirements.
Put the fresh dependency path first while retaining the workspace parent only
as the fallback that resolves the pipeline role under test:
## Review Validation
```sh
export ANSIBLE_ROLES_PATH="$test_tmp/roles:$(dirname "$repository_root")"
```
Shell syntax, changed-commit whitespace checks, pipeline syntax checking with
locally available collections, production-profile lint, and collection build
passed. Source and imported pipeline Git tree hashes match exactly. Reviewed
the recorded successful role/collection integration and consumer syntax runs;
did not rerun host-mutating convergence. A fresh dependency installation stalled
and was stopped, so this review does not independently establish a complete
fresh public dependency installation. No operational host was contacted.
Do not add dependency-content comparisons, source-revision assertions, or
other verification machinery. Ordinary Ansible role lookup with the correct
path precedence is sufficient.
## Remediation Boundaries
### Resolution
Fix authoritative pipeline files first, then publish and re-import the corrected
pipeline revision through the existing public Gitea subtree workflow. Do not
edit its collection copy directly. Update collection-owned tests and consumer
pins/links to the corrected public snapshot as needed. Preserve all agreed
application versions, configuration defaults, and runtime behavior. Validate
affected tests in proportion to the changes; no operational deployment,
credentials, live inference, or session migration is required.
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.
## Resolution Evidence
## Final Validation
All three findings were addressed on 2026-09-29:
From `ansible-role-dnd-pipeline`, run:
```text
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.
## 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.
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.
- Finding 1: pipeline `37b1cf6` removes redundant baseline credential-list
assertions while preserving custom-input coverage; collection `d9abb62`
removes default profile-ID and credential-list assertions. Native profile
inspection, configuration validation, and immediate clean-repeat checks remain.
- Findings 2 and 3: pipeline `37b1cf6` and consumer `15f0f4e` distinguish
Audita configuration migration from Narratio session migration, link the
exact provenance procedure, preserve progress and immutable snapshots,
and allow environment or file-based credential provisioning. The stale
Notarius dependency/catalog claim is replaced by tagged release guidance.
- The public pipeline revision is
`37b1cf6fab71c6a1212e49357c2e825cb0237a00`; collection subtree import and
public revision `b3bc0457efb7ea14ed11789978edd440537860fc` contain its exact
Git tree. Both remote branch heads were independently checked with
`git ls-remote`. Consumer `15f0f4e` selects that collection and links the
corrected source README; the consumer commit remains local.
- Shell syntax and whitespace checks passed. Pipeline and installed-collection
syntax checks and production-profile lint passed. Collection build and
disposable artifact installation passed. Consumer real-inventory host
listing selected only `pipeline-dnd`, and syntax checking passed without
deployment or Vault decryption.
- Validation used the previously downloaded public role dependencies and
available local collections. Full host-mutating integration was not rerun:
production code/defaults are unchanged, test changes remove assertions and
unused parsing, and prior full-run evidence remains applicable to unchanged
behavior. No operational system or session state was modified.

View File

@@ -1,10 +1,18 @@
# Workspace Status
Last updated: 2026-09-10
Last updated: 2026-09-29
Current milestone: M1-03 suite-level pipeline role
Current milestone: Operational D&D pipeline deployment
Current focus: Select the next suite-level pipeline role feature.
Current focus: Feature 0023 is complete after independent review with no findings.
Narratio v3.1.0 and Scriptorium credential selection are wired through the
standalone role, D&D suite, collection, and local consumer pins. No active
implementation plan remains. Deployment of this update and live credential
validation remain operator activities; neither was performed by this feature.
Feature 0022 and the application upgrade sequence remain complete. Broader
downgrade/removal policy remains unselected design work.
See the [upgrade sequence](roadmap/application-upgrade-sequence.md) and
[feature evidence](roadmap/features/0023-narratio-scriptorium-credentials.md).
| ID | Deliverable | Owner | State | Evidence or next step |
| --- | --- | --- | --- | --- |
@@ -15,15 +23,32 @@ 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-04 | Collection assembly | ansible-collection-dnd | proposed | Select and implement the pipeline-role incorporation mechanism |
| M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | done | Features 0006 through 0011 completed through remediation commit `de1b191` |
| M1-04 | Collection assembly | ansible-collection-dnd | done | Implemented and independently reviewed through collection remediation commit `da67b34` |
| 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 |
| F0003 | Install and configure Notarius | ansible-role-notarius | done | Implemented and validated through remediation commit `eb4f511` |
| 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 | done | Implemented and independently reviewed through remediation commit `bbf01e1` |
| F0011 | Deliver pipeline credentials and Notarius reuse | ansible-role-narratio and ansible-role-dnd-pipeline | done | Implemented and independently reviewed through remediation commit `de1b191` |
| F0012 | Assemble the D&D collection | ansible-collection-dnd and ansible-role-dnd-pipeline | done | Pipeline `600eb21` assembled and validated through collection remediation commit `da67b34` |
| F0013 | Publish the first coordinated suite release | all Ansible repositories and workspace | done | Public [`rakestraw.dnd` 0.1.0 release](https://gitea.maximumdirect.net/eric/ansible-collection-dnd/releases/tag/v0.1.0); documentation remediation completed in pipeline `78afffe` and collection `5e695f3` |
| F0014 | Enroll existing pipeline operators | ansible-role-dnd-pipeline, ansible-collection-dnd, and workspace | done | Pipeline `c13f726` and collection import `c0b0ebd` passed their complete integration suites and independent review with no remediation findings |
| F0015 | Enable D&D S3 storage and publishing | ansible-role-dnd-pipeline, ansible-collection-dnd, and workspace | done | Pipeline `51566afcf69083cdbb5b5718f2544c86b079001c`, collection fixture `cf3de016ee09edf91afc3bc1addfd926d4a172ad`, collection squash `77f67adbc0f700e88bc15554e02052eaa22f1033`, and collection merge `46913446765e86ecfb29ebad9955d579ef6a4c7e` passed the complete repository suites and independent review with no remediation findings |
| F0016 | Prepare the D&D deployment playbook for `pipeline-dnd` | rakestraw-ansible and workspace | done | Consumer `716a80e`, `12b2462`, and `7f8353d` passed independent review with no findings; public dependency installation, target-only host listing, syntax and whitespace checks passed. Follow-up `7f4c90a` pins collection `2a53979` for Narratio v2.1.2; collection build and syntax checks passed |
| F0017 | Compose the Notarius testing overlay | Narratio role, pipeline role, collection, consumer, and workspace | done | Published through Narratio `330afe7`, Notarius `a82a83d`, pipeline `c56a942`, collection `ce5b838`, and consumer `0ced48c`; independent review found no remediation issues; validation evidence is in the feature roadmap |
| F0018 | Adopt Scriptorium v0.15.0 | Scriptorium role and workspace | done | Role commits `61dcafe`, `2fce529`, and `b174c8c` passed independent review with no findings; feature roadmap records validation; suite pins unchanged |
| F0019 | Adopt Audita v2.0.1 | Audita role and workspace | done | Role `c3dd59f`, following `6137ff2` and `52f67fe`, passed independent review with no findings; [roadmap](roadmap/features/0019-audita-v2-adoption.md) records validation; suite pins unchanged |
| F0020 | Adopt Notarius v0.8.1 | Notarius role and workspace | done | Role `6aef48b`, following `b1b922c` and `380b6a3`, passed independent review with no findings; [feature roadmap](roadmap/features/0020-notarius-v0-8-adoption.md) records evidence; suite pins unchanged |
| F0021 | Adopt Narratio v3.0.0 | Narratio role and workspace | done | Role `3c0700b`, following `a28f22c` and `45f6836`, passed independent review with no findings; [feature roadmap](roadmap/features/0021-narratio-v3-adoption.md) records evidence; suite pins unchanged |
| F0022 | Integrate the reviewed application upgrades | Pipeline role, collection, consumer, and workspace | done | Closed after review and resolution of all three findings; public pipeline `37b1cf6`, public collection `b3bc045`, local consumer `15f0f4e`; [remediation evidence](roadmap/remediation.md) |
| A0001 | Audit completed standalone-role test suites | workspace and standalone roles | done | Findings recorded in `docs/roadmap/test-suite-audit-findings.md` |
| F0023 | Adopt Narratio v3.1.0 and forward Scriptorium credentials | Narratio role, pipeline role, collection, consumer, and workspace | done | Public Narratio role `758aed7a`, pipeline `0f841fd`, collection `002e86c`; local consumer `67cc22f`. Independent review found no actionable issues; [feature evidence](roadmap/features/0023-narratio-scriptorium-credentials.md) |
| R0001 | Simplify completed standalone-role test suites | workspace and standalone roles | done | Role commits `e08c63c`, `d2d0b9d`, and `cfecf37` passed implementation and independent review |
## Updating This File