Compare commits
147 Commits
5713ce582e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 31c01f0fce | |||
| 7f957e14bc | |||
| ed91180899 | |||
| 827c734fdd | |||
| 62f5f5e93f | |||
| 2d2f67f66e | |||
| e1aa245054 | |||
| 43ecdebcc5 | |||
| 6829439807 | |||
| fec2f89b48 | |||
| 1f41045830 | |||
| f964b24f7e | |||
| 8b8c232043 | |||
| 1b1382fe6e | |||
| c0a0dae794 | |||
| 82e672b888 | |||
| f084988c80 | |||
| 005a1c8ad5 | |||
| ced9e66382 | |||
| 0dc7e5b965 | |||
| 2477189047 | |||
| 8c689ea113 | |||
| e93ebea771 | |||
| a0414244bb | |||
| ae8d93f71a | |||
| bcaf48155e | |||
| 760a172b34 | |||
| 8111f66de5 | |||
| f58c960b56 | |||
| 5301dac921 | |||
| c0582faa24 | |||
| e0153d938b | |||
| 86836879eb | |||
| e7f5e4753a | |||
| 98abc1b905 | |||
| aa9338b135 | |||
| 5a8e3fccc9 | |||
| 3bc042ea22 | |||
| 47129b213d | |||
| 8cd642ffa6 | |||
| ad739671f6 | |||
| 0b2a45a327 | |||
| 59b472d0a1 | |||
| 38dfb0422c | |||
| 58738e4efc | |||
| a231b57294 | |||
| 1d1f34fc8b | |||
| f9901f17d1 | |||
| f8fe8dd0c6 | |||
| e482ea4b01 | |||
| bbb7acc315 | |||
| d0c776b47e | |||
| 45599bb020 | |||
| bb0f8cf84b | |||
| 76c10f79f5 | |||
| f399be34cd | |||
| 2feb622937 | |||
| 974b57e33e | |||
| a95a0ea280 | |||
| e262b61292 | |||
| ec69f5a03b | |||
| bf81461de6 | |||
| 839b63a61e | |||
| 3233bf6b9b | |||
| a5bc701f60 | |||
| eda361fa5d | |||
| 06e1b35f25 | |||
| 539c75cb18 | |||
| fc8f5709b0 | |||
| 0e0034ef02 | |||
| 40ca08a352 | |||
| 956c50cc2f | |||
| e24e8d0d05 | |||
| 943ece7a65 | |||
| b98fb5783f | |||
| 253d283234 | |||
| 8f57e1bcf5 | |||
| b359eee321 | |||
| 2b1448ab91 | |||
| ec3c0b9706 | |||
| 1a81db660e | |||
| bc1cf31f0e | |||
| 9a86cdb57e | |||
| 54a2362c02 | |||
| d2bd48cc99 | |||
| 731a799873 | |||
| bbc8d25d64 | |||
| 9b0949f2ac | |||
| 358051af98 | |||
| 6d9b4b87f8 | |||
| 7ac9220e87 | |||
| 7f8ce88b43 | |||
| 5b2effd68a | |||
| 88a0eaacf5 | |||
| 1806bfaf7f | |||
| f91871ba0f | |||
| 69961180a2 | |||
| f605fa0c1a | |||
| 1e0d4d0788 | |||
| dcc1103358 | |||
| daa08e6156 | |||
| fa348e9376 | |||
| 7d92867ba7 | |||
| 398562a2ca | |||
| efc7905798 | |||
| 8143732741 | |||
| cb90d63a2b | |||
| 52fa8ac918 | |||
| f6b6c7196b | |||
| a7d718970f | |||
| e63b334887 | |||
| 562eb540b8 | |||
| 870fc7b739 | |||
| 9f0d11d897 | |||
| 663dce1a9c | |||
| b83b778751 | |||
| daab85ae7e | |||
| fb3c95d462 | |||
| ca0380b208 | |||
| 3b2c47d236 | |||
| 4765586004 | |||
| 5fdd92b297 | |||
| e46c8182f1 | |||
| 0beda58192 | |||
| 05f100e2bf | |||
| a84a6383ec | |||
| 8e34f56f81 | |||
| e418edc5ef | |||
| e7607f45f7 | |||
| 7c2c9fe287 | |||
| 860651966a | |||
| 6034691350 | |||
| 8150dd2555 | |||
| bbeecc0055 | |||
| 77dcf8f7f7 | |||
| 3f20cf4b18 | |||
| 332bc4742b | |||
| 6d6b2307ff | |||
| ca82dd76aa | |||
| e4a307578c | |||
| 9ceaa2a5f1 | |||
| 1714b60dfe | |||
| 482e8473c2 | |||
| 4177b4de81 | |||
| f87962ca13 | |||
| 5dc879ecd7 | |||
| a3af153895 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,6 +7,8 @@
|
||||
/ansible-role-scriptorium/
|
||||
/ansible-role-seriatim/
|
||||
/rakestraw-ansible/
|
||||
/assets/campaigns/
|
||||
/assets/narratio-prompts/
|
||||
|
||||
# Local tool state.
|
||||
/.codebase-memory/
|
||||
|
||||
12
AGENTS.md
12
AGENTS.md
@@ -12,9 +12,13 @@ is an independent Git repository.
|
||||
- Read [the workspace orientation](docs/orientation.md) before selecting,
|
||||
inspecting, or modifying a repository. It maps the repositories and defines
|
||||
the canonical sources of truth.
|
||||
- Read [the workspace conventions](docs/conventions.md) before reviewing or
|
||||
changing Ansible, preparing a feature roadmap or implementation plan, or
|
||||
making any repository change. It defines the normative house style and
|
||||
working conventions.
|
||||
- Read [the workspace conventions](docs/conventions.md) before making any
|
||||
repository change. They define the workspace-wide rules and route work to
|
||||
specialized policy.
|
||||
- Read [the Ansible house style](docs/ansible.md) before designing,
|
||||
implementing, or reviewing Ansible roles or collections, including plans
|
||||
that specify such work.
|
||||
- Read [the testing house style](docs/testing.md) before creating, changing,
|
||||
reviewing, or auditing tests, including plans that specify test work.
|
||||
- Read [the planning policy](docs/planning.md) before preparing a feature
|
||||
roadmap or implementation plan or managing an ongoing work stream.
|
||||
|
||||
@@ -7,8 +7,8 @@ only workspace documentation, planning, and shared development utilities.
|
||||
|
||||
## Start Here
|
||||
|
||||
- [`AGENTS.md`](AGENTS.md) describes repository boundaries and working
|
||||
conventions.
|
||||
- [`AGENTS.md`](AGENTS.md) describes repository boundaries and routes each
|
||||
kind of work to its required policy documents.
|
||||
- [`workspace.yml`](workspace.yml) inventories the repositories used during
|
||||
development.
|
||||
- [`docs/roadmap/mvp.md`](docs/roadmap/mvp.md) records settled MVP decisions
|
||||
|
||||
52
assets/configs/audita/config.yml
Normal file
52
assets/configs/audita/config.yml
Normal 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
|
||||
160
assets/configs/narratio/pipeline.yml
Normal file
160
assets/configs/narratio/pipeline.yml
Normal 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
|
||||
154
assets/configs/notarius/config.yml
Normal file
154
assets/configs/notarius/config.yml
Normal 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
|
||||
5
assets/configs/scriptorium/config.yml
Normal file
5
assets/configs/scriptorium/config.yml
Normal 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
|
||||
97
docs/ansible.md
Normal file
97
docs/ansible.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Ansible House Style
|
||||
|
||||
This policy is normative for designing, implementing, and reviewing Ansible
|
||||
roles and collections in this workspace.
|
||||
|
||||
## Role Implementation
|
||||
|
||||
- Always use the smallest clear sequence of declarative tasks that reaches the
|
||||
required end state.
|
||||
- Prefer `ansible.builtin` modules where they directly fit the task.
|
||||
`community.general` is an approved, stable dependency and its modules may be
|
||||
selected freely when appropriate; declare and pin the collection wherever a
|
||||
role or collection depends on it.
|
||||
- Do not strengthen the specification. Implement the requested invariants
|
||||
without inventing additional guarantees for integrity, provenance, drift
|
||||
recovery, corruption detection, rollback, or similar behavior.
|
||||
- Prefer convergence over state inspection. Declare what should be true and
|
||||
let the relevant module reconcile it.
|
||||
- Trust Ansible's abstraction boundary. A module that manages state owns the
|
||||
checks necessary to manage that state. Inspect it beforehand only when the
|
||||
observed state is independently required.
|
||||
- State inspection is justified when its result is necessary to decide whether
|
||||
an imperative operation must run, such as checking whether an arbitrary
|
||||
build command's output exists.
|
||||
- Production role tasks establish required application state; they do not test
|
||||
the role's own implementation. Put implementation verification in
|
||||
repository-local tests unless the specification explicitly requires runtime
|
||||
validation during convergence.
|
||||
- For an unavoidable `command` or `shell` task, declare the operation's change
|
||||
semantics as required by ansible-lint. A conditionally executed mutation may
|
||||
use `changed_when: true`; a read-only command should use
|
||||
`changed_when: false`. This describes an imperative operation and does not
|
||||
replace the idempotence of a state-management module.
|
||||
- Apply `become: true` to individual tasks that require elevated privileges.
|
||||
Do not require callers to escalate an entire play merely to use a role.
|
||||
- Complexity requires a requirement. Every additional task, conditional,
|
||||
registered variable, or state probe must correspond to behavior the role is
|
||||
required to provide.
|
||||
- Persisted role-private state is a design smell. Fingerprints, checksum
|
||||
databases, stamps, manifests, and similar bookkeeping require specific
|
||||
justification.
|
||||
- **Assume convergence first.** Before adding machinery for an edge case,
|
||||
determine whether rerunning the ordinary desired-state operations already
|
||||
repairs it.
|
||||
- Consider whether a conditional task or a notified handler best expresses the
|
||||
dependency. A `when` condition keeps triggers visible at the action site but
|
||||
grows with their number. Notifications keep the action independent of the
|
||||
number of notifiers, but distribute the control flow and defer execution
|
||||
until the next handler flush. An explicit
|
||||
`ansible.builtin.meta: flush_handlers` affects all pending handlers in the
|
||||
play.
|
||||
- Treat `rakestraw-ansible` as a style reference for direct tasks, shallow
|
||||
control flow, and concise variable use, while retaining current practices
|
||||
such as fully qualified collection names.
|
||||
|
||||
## Application Configuration Interfaces
|
||||
|
||||
- Expose application configuration through documented, field-specific role
|
||||
variables suitable for `host_vars`, `group_vars`, play variables, and
|
||||
composing roles.
|
||||
- Give structurally required fields concrete defaults. Define optional
|
||||
application settings as `null` unless the role intentionally owns the
|
||||
corresponding policy.
|
||||
- Treat a null optional variable as "omit this field from the rendered
|
||||
configuration." Do not copy documented upstream defaults into role defaults
|
||||
merely to write them back to the application.
|
||||
- Let the application supply its built-in defaults for omitted fields. This
|
||||
avoids freezing a duplicate defaults database in Ansible and permits upstream
|
||||
default changes to take effect naturally.
|
||||
- Use `is not none` when conditionally rendering optional values. Do not use
|
||||
truthiness, because false, zero, an empty string, or an empty collection may
|
||||
be an intentional value.
|
||||
- Emit a nested configuration section only when at least one of its descendant
|
||||
variables is non-null.
|
||||
- Serialize strings and collections with appropriate Ansible or Jinja filters.
|
||||
Do not construct YAML quoting manually.
|
||||
- Keep argument specifications aligned with the public variables. Optional
|
||||
nullable variables are not required; use a permissive type only when the
|
||||
native application accepts more than one scalar type.
|
||||
- Prefer one field-specific interface. Do not provide a parallel raw mapping,
|
||||
template override, or merge mechanism unless a concrete requirement defines
|
||||
its precedence and behavior.
|
||||
- Application roles expose native configuration choices. The suite-level role
|
||||
supplies cross-application and deployment-specific policy through those
|
||||
variables.
|
||||
- Manage the resulting file with one ordinary `ansible.builtin.template` task.
|
||||
Do not add configuration assembly facts, preliminary file inspection, or
|
||||
production validation unless independently required.
|
||||
- Configuration tests should use explicitly supplied representative values to
|
||||
exercise conditional rendering, null omission, intentional falsey values,
|
||||
native configuration validity, and caller-facing composition boundaries.
|
||||
They should follow [the testing house style](testing.md) rather than
|
||||
snapshotting the current default document.
|
||||
|
||||
Role defaults define what Ansible intends to manage, not a mirror of every
|
||||
application default. A concrete default means the role deliberately owns that
|
||||
policy; a null default leaves the policy with the application.
|
||||
@@ -1,6 +1,17 @@
|
||||
# Workspace Conventions
|
||||
|
||||
## Working Conventions
|
||||
These conventions apply to all work in this workspace. Read the specialized
|
||||
policy for the work being performed as well:
|
||||
|
||||
- Read [the Ansible house style](ansible.md) before designing, implementing,
|
||||
or reviewing Ansible roles or collections, including their configuration
|
||||
interfaces.
|
||||
- Read [the testing house style](testing.md) before creating, changing,
|
||||
reviewing, or auditing tests.
|
||||
- Read [the planning policy](planning.md) before preparing or managing a
|
||||
feature roadmap, implementation plan, or active work stream.
|
||||
|
||||
## Workspace-Wide Conventions
|
||||
|
||||
- Confirm the target repository before editing; never treat this directory as
|
||||
a monorepo.
|
||||
@@ -20,48 +31,3 @@
|
||||
run.
|
||||
- Do not duplicate an application contract in workspace documentation when a
|
||||
link and a concise deployment consequence are sufficient.
|
||||
|
||||
## Ansible House Style (Normative)
|
||||
|
||||
- Always use the smallest clear sequence of declarative tasks that reaches the
|
||||
required end state.
|
||||
- Prefer `ansible.builtin` modules where they directly fit the task.
|
||||
`community.general` is an approved, stable dependency and its modules may be
|
||||
selected freely when appropriate; declare and pin the collection wherever a
|
||||
role or collection depends on it.
|
||||
- Do not strengthen the specification. Implement the requested invariants
|
||||
without inventing additional guarantees for integrity, provenance, drift
|
||||
recovery, corruption detection, rollback, or similar behavior.
|
||||
- Prefer convergence over state inspection. Declare what should be true and
|
||||
let the relevant module reconcile it.
|
||||
- Trust Ansible's abstraction boundary. A module that manages state owns the
|
||||
checks necessary to manage that state. Inspect it beforehand only when the
|
||||
observed state is independently required.
|
||||
- State inspection is justified when its result is necessary to decide whether
|
||||
an imperative operation must run, such as checking whether an arbitrary
|
||||
build command's output exists.
|
||||
- Production role tasks establish required application state; they do not test
|
||||
the role's own implementation. Put implementation verification in
|
||||
repository-local tests unless the specification explicitly requires runtime
|
||||
validation during convergence.
|
||||
- Apply `become: true` to individual tasks that require elevated privileges.
|
||||
Do not require callers to escalate an entire play merely to use a role.
|
||||
- Complexity requires a requirement. Every additional task, conditional,
|
||||
registered variable, or state probe must correspond to behavior the role is
|
||||
required to provide.
|
||||
- Persisted role-private state is a design smell. Fingerprints, checksum
|
||||
databases, stamps, manifests, and similar bookkeeping require specific
|
||||
justification.
|
||||
- **Assume convergence first.** Before adding machinery for an edge case,
|
||||
determine whether rerunning the ordinary desired-state operations already
|
||||
repairs it.
|
||||
- Consider whether a conditional task or a notified handler best expresses the
|
||||
dependency. A `when` condition keeps triggers visible at the action site but
|
||||
grows with their number. Notifications keep the action independent of the
|
||||
number of notifiers, but distribute the control flow and defer execution
|
||||
until the next handler flush. An explicit
|
||||
`ansible.builtin.meta: flush_handlers` affects all pending handlers in the
|
||||
play.
|
||||
- Treat `rakestraw-ansible` as a style reference for direct tasks, shallow
|
||||
control flow, and concise variable use, while retaining current practices
|
||||
such as fully qualified collection names.
|
||||
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
|
||||
@@ -10,6 +10,13 @@ Repositories inside this directory:
|
||||
suite-level role exposed by the collection as `rakestraw.dnd.pipeline`.
|
||||
- `ansible-role-{narratio,notarius,audita,seriatim,scriptorium}`: standalone
|
||||
application roles.
|
||||
- `assets/campaigns`: D&D campaign registry content deployed by the pipeline
|
||||
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.
|
||||
@@ -18,15 +25,17 @@ Relevant upstream repositories are siblings of this directory:
|
||||
|
||||
- `../{narratio,notarius,audita,seriatim,scriptorium}`: application source and
|
||||
authoritative application contracts.
|
||||
- `../narratio-prompts`: pipeline prompt-library content.
|
||||
|
||||
Use [the workspace inventory](../workspace.yml) as the complete
|
||||
machine-readable inventory of paths and remotes.
|
||||
|
||||
## Sources of Truth
|
||||
|
||||
- [Workspace conventions](conventions.md): normative working and Ansible house
|
||||
style.
|
||||
- [Workspace conventions](conventions.md): normative workspace-wide rules and
|
||||
policy routing.
|
||||
- [Ansible house style](ansible.md): normative role, collection, and
|
||||
application-configuration practices.
|
||||
- [Testing house style](testing.md): normative behavioral-testing practices.
|
||||
- [Planning policy](planning.md): normative feature planning and progress
|
||||
workflow.
|
||||
- [MVP roadmap](roadmap/mvp.md): settled MVP scope, architecture, and open
|
||||
@@ -41,4 +50,9 @@ machine-readable inventory of paths and remotes.
|
||||
active staged plan or, when no plan is approved, a pending-plan notice.
|
||||
- Application repositories: CLI, configuration, build, and integration
|
||||
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.
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Planning and Progress
|
||||
|
||||
- Read and follow [the workspace conventions](conventions.md) before preparing
|
||||
or revising any roadmap or implementation plan.
|
||||
or revising any roadmap or implementation plan. Also read the specialized
|
||||
policy applicable to the planned work: [the Ansible house style](ansible.md),
|
||||
[the testing house style](testing.md), or both.
|
||||
- Update [the MVP roadmap](roadmap/mvp.md) when a design question becomes a
|
||||
settled scope or architecture decision.
|
||||
- Discuss and select the next unit of work before planning implementation.
|
||||
@@ -28,7 +30,9 @@
|
||||
GPT-5.6-Terra to execute sequentially. Number stages with consecutive
|
||||
integers beginning with `Stage 1`; do not skip numbers or use nested stage
|
||||
numbering. Each stage must identify its repository, preconditions, required
|
||||
behavior, validation, completion criteria, and expected commit.
|
||||
policy reading, behavior, validation, completion criteria, and expected
|
||||
commit. Direct the implementing agent to reread the applicable policy
|
||||
documents immediately before beginning each stage.
|
||||
- Resolve architectural choices during roadmap and plan review. Do not leave
|
||||
unresolved design judgment to the implementation agent.
|
||||
- Update [workspace status](status.md) when cross-repository work starts,
|
||||
|
||||
88
docs/roadmap/application-upgrade-sequence.md
Normal file
88
docs/roadmap/application-upgrade-sequence.md
Normal 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).
|
||||
@@ -37,7 +37,8 @@ the current design from becoming an accidental suite-wide pattern.
|
||||
it at `/usr/local/bin/seriatim`.
|
||||
- Rebuild when the source checkout changes or the binary is absent.
|
||||
- Converge the installed binary to `root:root` ownership and mode `0755`.
|
||||
- Verify the installed version in repository-local integration tests.
|
||||
- Verify an explicitly selected immutable Seriatim version through the native
|
||||
CLI in repository-local integration tests.
|
||||
- Keep the role interface, README, metadata, and focused local tests consistent
|
||||
with the simplified behavior.
|
||||
- Remove obsolete build-state files and implementation machinery from the
|
||||
@@ -213,7 +214,8 @@ used as templates for another role.
|
||||
- Detect arbitrary binary modification independently of reported version.
|
||||
- Protect or recover from unexpected symbolic links and malformed managed
|
||||
paths.
|
||||
- Add dedicated Ubuntu release and architecture test matrices.
|
||||
- Add broader Ubuntu release and architecture test coverage only if future
|
||||
platform behavior warrants it.
|
||||
|
||||
These are candidates for separately selected features if operational
|
||||
experience or a changed threat model justifies them.
|
||||
|
||||
@@ -6,243 +6,245 @@ Status: done
|
||||
|
||||
Provide a small, independently usable `rakestraw.audita` role that installs
|
||||
Audita from a pinned Git tag, builds its executable on the managed host, and
|
||||
manages its versioned YAML configuration. Follow the module-driven Seriatim
|
||||
pattern while adding only the configuration behavior that distinguishes
|
||||
Audita.
|
||||
offers an ergonomic field-specific interface for its versioned YAML
|
||||
configuration. Unspecified optional fields are omitted so Audita retains
|
||||
ownership of its application defaults.
|
||||
|
||||
## Problem or Opportunity
|
||||
|
||||
The `ansible-role-audita` repository currently contains only its initial
|
||||
placeholder files. Audita needs a standalone installer before the suite role
|
||||
can compose the transcript-processing pipeline and supply D&D-specific runtime
|
||||
policy.
|
||||
The completed source-installation flow is concise and correct, but the initial
|
||||
configuration interface exposes only one `audita_config` mapping. That requires
|
||||
every caller to know and reproduce Audita's native nested schema, and it does
|
||||
not provide the ordinary role ergonomics expected for inventory variables.
|
||||
|
||||
An earlier implementation direction depended on the superseded Seriatim
|
||||
fingerprint, sidecar-state, staged-build, and corruption-recovery architecture.
|
||||
This roadmap replaces that direction with a concise implementation that trusts
|
||||
Ansible modules, rebuilds only for required conditions, and keeps production
|
||||
role tasks separate from integration verification.
|
||||
The role should expose documented variables for individual settings and render
|
||||
only values expressly selected by the caller. This permits straightforward
|
||||
`host_vars`, `group_vars`, play variables, and suite-role overrides while
|
||||
allowing upstream default changes to take effect automatically when a setting
|
||||
is not managed by Ansible.
|
||||
|
||||
## Scope
|
||||
|
||||
- Implement `ansible-role-audita` as a conventional standalone role.
|
||||
- Support Ubuntu 26.04 on native `amd64` and `arm64` hosts.
|
||||
- Install Git and the official Go Snap with classic confinement when build
|
||||
dependency management is enabled.
|
||||
- Default the Go Snap channel to `1.26/stable`.
|
||||
- Check out immutable Audita tag `v0.9.1` by default under the root-owned path
|
||||
`/usr/local/src/audita`.
|
||||
- Build Audita with its upstream release build contract and install the native
|
||||
executable at `/usr/local/bin/audita`.
|
||||
- Rebuild when the Git checkout changes or the binary is absent.
|
||||
- Converge the installed binary to `root:root` ownership and mode `0755`.
|
||||
- Manage a versioned Audita YAML configuration at
|
||||
`/usr/local/etc/audita/config.yml`, owned by `root:root` with mode `0644`.
|
||||
- Default the managed configuration to the minimal valid mapping
|
||||
`{"version": 1}`, allowing Audita's own defaults to govern application
|
||||
behavior.
|
||||
- Keep role defaults, argument specifications, README, metadata, dependency
|
||||
declaration, and focused local tests consistent with this contract.
|
||||
- Retain the completed Ubuntu 26.04 `amd64` and `arm64` source installation.
|
||||
- Retain default tag `v0.9.1`, Go Snap channel `1.26/stable`, source path
|
||||
`/usr/local/src/audita`, and binary path `/usr/local/bin/audita`.
|
||||
- Retain rebuild triggers of changed Git checkout or absent binary.
|
||||
- Replace the complete `audita_config` mapping with typed, field-specific
|
||||
configuration variables.
|
||||
- Always render the required configuration schema version, defaulting to `1`.
|
||||
- Define every optional configuration variable as `null` by default and omit
|
||||
its YAML field when it remains null.
|
||||
- Render nested YAML sections only when at least one setting in that section is
|
||||
non-null.
|
||||
- Manage `/usr/local/etc/audita/config.yml` from a Jinja template as
|
||||
`root:root` mode `0644`.
|
||||
- Keep defaults, argument specifications, template, README, metadata,
|
||||
dependency declaration, and focused tests consistent with this contract.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Copying Audita's built-in values into role defaults or the default rendered
|
||||
file.
|
||||
- D&D-specific model selection, concurrency, thresholds, transcript context,
|
||||
or other suite policy. The suite-level role will provide those overrides.
|
||||
- A separate Ansible variable for every field in Audita's configuration
|
||||
schema.
|
||||
- API keys, secret values, environment files, or another secret-delivery
|
||||
mechanism. Configuration may name environment variables but must not contain
|
||||
their secret values.
|
||||
- Creation or management of the `narratio` account, operator groups, campaign
|
||||
data, glossaries, transcript data, or diagnostics directories.
|
||||
- Installation or configuration of another pipeline application.
|
||||
- Services, scheduling, removal behavior, or pipeline composition.
|
||||
- Prebuilt release artifacts or cross-compilation.
|
||||
- Production execution of Audita to validate the build or configuration.
|
||||
- Detection of out-of-band binary modification, compiler changes, or fixed
|
||||
build-command changes.
|
||||
- Build fingerprints, checksums, sidecar state, staged replacement, manual Git
|
||||
cleanup, or special recovery for malformed or adversarial host state.
|
||||
- A shared build helper role or dedicated platform-matrix infrastructure.
|
||||
or other suite policy.
|
||||
- A parallel mapping-based configuration escape hatch or merge/precedence
|
||||
rules between two configuration interfaces.
|
||||
- API keys or other secret values. Variables may select environment-variable
|
||||
names, but the role does not manage their values.
|
||||
- Creation of the `narratio` account or management of runtime, campaign,
|
||||
glossary, transcript, diagnostics, or secret-delivery infrastructure.
|
||||
- Services, scheduling, removal behavior, pipeline composition, prebuilt
|
||||
artifacts, or cross-compilation.
|
||||
- Production execution of Audita for build or configuration validation.
|
||||
- Fingerprints, checksums, sidecar state, staged replacement, manual Git
|
||||
cleanup, compiler inspection, or out-of-band drift detection.
|
||||
|
||||
## Target End State
|
||||
|
||||
On an Ubuntu 26.04 `amd64` or `arm64` host, applying the role with defaults
|
||||
installs or confirms Git and Go, checks out Audita `v0.9.1` at
|
||||
`/usr/local/src/audita`, builds `/usr/local/bin/audita`, and writes
|
||||
`/usr/local/etc/audita/config.yml`. Source and installed files have the stated
|
||||
root ownership and permissions, and the configuration contains `version: 1`.
|
||||
With no configuration overrides, the role writes the minimal valid document:
|
||||
|
||||
An immediate second application reports no changes. A changed Git checkout or
|
||||
missing binary causes one build; configuration changes converge through the
|
||||
ordinary file-management module without rebuilding Audita. Repository-local
|
||||
tests execute the installed CLI to verify the build and validate the managed
|
||||
configuration.
|
||||
```yaml
|
||||
version: 1
|
||||
```
|
||||
|
||||
When a caller sets an optional role variable, the corresponding native Audita
|
||||
field appears in the correct YAML section. Fields whose variables remain null
|
||||
are absent, including their parent sections when no child is selected. Empty
|
||||
lists, empty strings, zero, and other expressly supplied non-null values are
|
||||
rendered rather than mistaken for omission and are left for Audita to validate.
|
||||
|
||||
Installation and configuration converge independently. A configuration-only
|
||||
change does not rebuild the binary, and an immediate repeat reports no changes.
|
||||
Repository-local tests validate managed configurations through Audita. The
|
||||
current CLI has no native release-identity command, so the suite deliberately
|
||||
does not substitute a raw source-commit proxy for version coverage.
|
||||
|
||||
## Repository Ownership
|
||||
|
||||
- `ansible-role-audita` owns the role implementation, public interface,
|
||||
configuration rendering, metadata, dependency declaration, README, and
|
||||
repository-local validation.
|
||||
- `../audita` is the read-only authority for the build, CLI, and configuration
|
||||
contracts.
|
||||
- `rakestraw-ansible` is a read-only style and configuration-policy reference.
|
||||
- `ansible-role-dnd-pipeline` will later own the D&D-specific values supplied
|
||||
through the standalone role's configuration interface.
|
||||
- `ansible-workspace-dnd` owns this roadmap, the eventual staged implementation
|
||||
plan, and aggregate status.
|
||||
- `ansible-role-audita` owns installation, the public configuration interface,
|
||||
template, metadata, README, and repository-local tests.
|
||||
- `../audita` is the read-only authority for build, CLI, configuration schema,
|
||||
and application-default contracts.
|
||||
- `rakestraw-ansible` is a read-only style reference for field-specific role
|
||||
variables and conditional templates; its historical values are not
|
||||
authoritative defaults.
|
||||
- `ansible-role-dnd-pipeline` will later own D&D-specific overrides supplied
|
||||
through the standalone role variables.
|
||||
- `ansible-workspace-dnd` owns this roadmap, the staged plan, and aggregate
|
||||
status.
|
||||
- All other repositories remain unchanged.
|
||||
|
||||
## Constraints and Settled Decisions
|
||||
|
||||
- The selected release is tag `v0.9.1`, which resolves to commit
|
||||
`a84941d68168a1ed9ea7423b6477ae8218be73f9`.
|
||||
- Tags `v0.9.0` and `v0.9.1` resolve to the same commit, so `v0.9.0` cannot
|
||||
exercise checkout-change rebuilding. Focused integration may temporarily
|
||||
select buildable commit `46b7356a3b54a2771ce9a617e4fa3e8d13728cac`
|
||||
before restoring the default tag.
|
||||
- The tag declares Go 1.24.0. The suite-standard Go Snap channel remains
|
||||
`1.26/stable`.
|
||||
- The upstream release build uses package
|
||||
`gitea.maximumdirect.net/eric/audita/cmd/audita`, `CGO_ENABLED=0`,
|
||||
`GOWORK=off`, `GOTOOLCHAIN=local`, `-trimpath`, and linker flags `-s -w -X
|
||||
gitea.maximumdirect.net/eric/audita/internal/buildinfo.Version=<version>`.
|
||||
- Audita exposes no release-version command needed by production convergence.
|
||||
The role uses only checkout change and binary absence as build triggers.
|
||||
- Audita configuration schema version `1` is strict. The native command
|
||||
`audita config validate --config <path>` reports `config is valid` for a
|
||||
valid file and is used only by tests.
|
||||
- Audita's default configuration search order prefers
|
||||
`/usr/local/etc/audita/config.yml` over `/etc/audita/config.yml`; the role
|
||||
manages the preferred path.
|
||||
- Configuration is exposed as one mapping rather than many field-specific
|
||||
variables. This preserves Audita's schema and gives the suite role one clear
|
||||
override boundary.
|
||||
- Configuration contains no secrets by default. Consumers use Audita's
|
||||
`api_key_env` fields and arrange secret environment variables outside this
|
||||
feature.
|
||||
- Tasks that install dependencies or manage root-owned application state use
|
||||
task-level `become: true`.
|
||||
- `community.general` is an approved dependency and supplies Snap management;
|
||||
pin version `13.3.0` in the role's collection requirements.
|
||||
- Tag `v0.9.1` resolves to
|
||||
`a84941d68168a1ed9ea7423b6477ae8218be73f9` and retains the build contract
|
||||
already implemented and validated through role commit `3a8c21f`.
|
||||
- Audita's strict schema version is `1`; all other top-level fields are
|
||||
optional and overlay application defaults.
|
||||
- `audita_config_version` names the schema version so `audita_version` remains
|
||||
unambiguously the selected application release.
|
||||
- Optional variables are present in role defaults with YAML null values. This
|
||||
documents the interface and enables argument validation without emitting
|
||||
upstream defaults.
|
||||
- Template conditions use `is not none`, not truthiness, so expressly supplied
|
||||
falsey values are rendered.
|
||||
- String and list values must be safely encoded as YAML values rather than
|
||||
interpolated with hand-written quoting.
|
||||
- A parent mapping is emitted only when at least one corresponding child value
|
||||
is non-null.
|
||||
- The role does not validate Audita's semantic constraints during production
|
||||
convergence. Native validation remains integration-test behavior.
|
||||
- Task-level `become: true`, `community.general` 13.3.0, and all existing
|
||||
installation decisions remain unchanged.
|
||||
|
||||
## Fixed Public Interface
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `audita_version` | `v0.9.1` | Git revision and release value supplied to the build |
|
||||
| `audita_repository_url` | `https://gitea.maximumdirect.net/eric/audita.git` | Source repository |
|
||||
| `audita_source_dir` | `/usr/local/src/audita` | Managed source checkout |
|
||||
| `audita_binary_path` | `/usr/local/bin/audita` | Installed executable |
|
||||
| `audita_manage_build_dependencies` | `true` | Whether to install Git and Go |
|
||||
| `audita_go_snap_channel` | `1.26/stable` | Go Snap channel |
|
||||
| `audita_go_binary` | `/snap/bin/go` | Go executable used for the build |
|
||||
| `audita_config_path` | `/usr/local/etc/audita/config.yml` | Managed configuration file |
|
||||
| `audita_config` | `{"version": 1}` | Complete versioned configuration mapping |
|
||||
Retain these installation variables:
|
||||
|
||||
The package, build flags, linker symbol, environment values, file ownership,
|
||||
and file modes are fixed implementation details. The selected version is both
|
||||
the Git revision and the value supplied to the upstream linker flag.
|
||||
| Variable | Default |
|
||||
| --- | --- |
|
||||
| `audita_version` | `v0.9.1` |
|
||||
| `audita_repository_url` | `https://gitea.maximumdirect.net/eric/audita.git` |
|
||||
| `audita_source_dir` | `/usr/local/src/audita` |
|
||||
| `audita_binary_path` | `/usr/local/bin/audita` |
|
||||
| `audita_manage_build_dependencies` | `true` |
|
||||
| `audita_go_snap_channel` | `1.26/stable` |
|
||||
| `audita_go_binary` | `/snap/bin/go` |
|
||||
| `audita_config_path` | `/usr/local/etc/audita/config.yml` |
|
||||
|
||||
Provide these configuration variables:
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `audita_config_version` | `1` | `version` |
|
||||
| `audita_pipeline_modules` | `null` | `pipeline.modules` |
|
||||
| `audita_output_schema` | `null` | `output.schema` |
|
||||
| `audita_llm_proposal_base_url` | `null` | `llm.proposal.base_url` |
|
||||
| `audita_llm_proposal_model` | `null` | `llm.proposal.model` |
|
||||
| `audita_llm_proposal_api_key_env` | `null` | `llm.proposal.api_key_env` |
|
||||
| `audita_llm_proposal_timeout` | `null` | `llm.proposal.timeout` |
|
||||
| `audita_llm_proposal_max_retries` | `null` | `llm.proposal.max_retries` |
|
||||
| `audita_llm_validation_base_url` | `null` | `llm.validation.base_url` |
|
||||
| `audita_llm_validation_model` | `null` | `llm.validation.model` |
|
||||
| `audita_llm_validation_api_key_env` | `null` | `llm.validation.api_key_env` |
|
||||
| `audita_llm_validation_timeout` | `null` | `llm.validation.timeout` |
|
||||
| `audita_llm_validation_max_retries` | `null` | `llm.validation.max_retries` |
|
||||
| `audita_concurrency_total_llm` | `null` | `concurrency.total_llm` |
|
||||
| `audita_concurrency_proposal_llm` | `null` | `concurrency.proposal_llm` |
|
||||
| `audita_concurrency_validation_llm` | `null` | `concurrency.validation_llm` |
|
||||
| `audita_chunking_target_sections` | `null` | `chunking.target_sections` |
|
||||
| `audita_chunking_max_section_tokens` | `null` | `chunking.max_section_tokens` |
|
||||
| `audita_chunking_min_section_tokens` | `null` | `chunking.min_section_tokens` |
|
||||
| `audita_normalization_max_segment_gap` | `null` | `normalization.max_segment_gap` |
|
||||
| `audita_normalization_ellipsis_gap` | `null` | `normalization.ellipsis_gap` |
|
||||
| `audita_normalization_max_segment_duration` | `null` | `normalization.max_segment_duration` |
|
||||
| `audita_normalization_max_segment_tokens` | `null` | `normalization.max_segment_tokens` |
|
||||
| `audita_thresholds_glossary` | `null` | `thresholds.glossary` |
|
||||
| `audita_thresholds_homophones` | `null` | `thresholds.homophones` |
|
||||
| `audita_thresholds_spoken_word` | `null` | `thresholds.spoken_word` |
|
||||
| `audita_thresholds_grammar` | `null` | `thresholds.grammar` |
|
||||
| `audita_context_description` | `null` | `context.description` |
|
||||
| `audita_diagnostics_work_dir` | `null` | `diagnostics.work_dir` |
|
||||
| `audita_diagnostics_retention` | `null` | `diagnostics.retention` |
|
||||
|
||||
The argument specification types values according to the native field shape.
|
||||
Duration-like fields accept strings or numeric seconds as supported by Audita;
|
||||
do not narrow the application contract unnecessarily.
|
||||
|
||||
## Simplest Viable Implementation
|
||||
|
||||
The expected implementation is approximately nine ordinary tasks in one
|
||||
readable task file:
|
||||
Retain the existing nine-task installation flow. Make only these production
|
||||
changes:
|
||||
|
||||
1. Assert Ubuntu 26.04 and architecture `x86_64` or `aarch64`.
|
||||
2. Install Git with `ansible.builtin.apt`, including
|
||||
`cache_valid_time: 3600`, when dependency management is enabled.
|
||||
3. Install the classic Go Snap from `audita_go_snap_channel` with
|
||||
`community.general.snap` when dependency management is enabled.
|
||||
4. Create the source, binary, and configuration parent directories with one
|
||||
`ansible.builtin.file` loop.
|
||||
5. Check out `audita_version` with `ansible.builtin.git`, `force: true`, and
|
||||
register the module result.
|
||||
6. Inspect whether `audita_binary_path` exists with `ansible.builtin.stat`.
|
||||
7. Run the upstream Go build through `audita_go_binary` when the checkout
|
||||
changed or the binary is absent.
|
||||
8. Converge recursive source ownership and binary ownership and mode with one
|
||||
item-driven `ansible.builtin.file` loop.
|
||||
9. Serialize `audita_config` as YAML and manage `audita_config_path` with
|
||||
`ansible.builtin.copy`.
|
||||
1. Replace `audita_config` in defaults and argument specifications with the
|
||||
field-specific variables above.
|
||||
2. Add `templates/config.yml.j2`, always rendering `version` and conditionally
|
||||
rendering every optional field and necessary parent mapping.
|
||||
3. Replace the final `ansible.builtin.copy` task with one
|
||||
`ansible.builtin.template` task using the existing destination, ownership,
|
||||
and mode.
|
||||
|
||||
Apply task-level privilege escalation only to tasks that require it. Use
|
||||
`argv` for the build command, and put its two conditions directly on the build
|
||||
task. Do not add a rebuild fact, handler, handler flush, executable discovery,
|
||||
compiler interrogation, configuration preflight, or post-operation validation
|
||||
to production tasks.
|
||||
Do not add configuration assembly facts, nested merge filters, validation
|
||||
commands, preliminary file probes, or multiple configuration tasks. The
|
||||
template is the direct expression of the selected configuration state.
|
||||
|
||||
## Rationale and Alternatives
|
||||
|
||||
Audita's installation mechanics are intentionally the same as Seriatim's:
|
||||
declarative dependency and checkout management surrounding one imperative
|
||||
build command. The binary existence probe is justified because Ansible cannot
|
||||
infer whether that command's output exists; no other build-state model is
|
||||
needed.
|
||||
Field-specific variables are the ordinary ergonomic interface for inventory
|
||||
and composing roles. Nullable defaults make that interface discoverable and
|
||||
typed without freezing a duplicate copy of Audita's application defaults into
|
||||
Ansible. Conditional rendering also preserves the distinction between an
|
||||
unset field and a caller intentionally supplying a falsey value.
|
||||
|
||||
A single configuration mapping is smaller and more durable than duplicating
|
||||
Audita's evolving schema as dozens of role variables. A minimal default mapping
|
||||
produces a valid configuration while preserving upstream defaults. The future
|
||||
suite role can supply its complete D&D-specific mapping without coupling the
|
||||
standalone role to one deployment.
|
||||
|
||||
Managing the preferred `/usr/local/etc` path follows the application's own
|
||||
discovery order and keeps locally installed software and its configuration
|
||||
together. `/etc/audita/config.yml` remains an unmanaged application fallback.
|
||||
Leaving variables entirely undefined would produce the same file but weaken
|
||||
interface documentation and argument validation. Section-level dictionaries
|
||||
would shorten the template but require callers to understand more of the
|
||||
native nested schema. Retaining `audita_config` beside field variables would
|
||||
require unneeded merge and precedence semantics. None is preferable to the
|
||||
single field-specific interface.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- Unsupported distributions, Ubuntu releases, and architectures fail before
|
||||
application state is modified.
|
||||
- Default execution on the local Ubuntu 26.04 host installs or confirms Git
|
||||
and Go and checks out Audita tag `v0.9.1` at commit
|
||||
`a84941d68168a1ed9ea7423b6477ae8218be73f9`.
|
||||
- The role builds with the fixed upstream contract and installs
|
||||
`/usr/local/bin/audita` as `root:root` mode `0755`.
|
||||
- The managed source checkout is recursively owned by `root:root`.
|
||||
- The default configuration is a valid schema-version `1` document at
|
||||
`/usr/local/etc/audita/config.yml`, owned by `root:root` with mode `0644`.
|
||||
- Repository-local tests successfully execute the installed CLI and receive
|
||||
`config is valid` when validating the managed configuration.
|
||||
- An immediate second role run reports no changes.
|
||||
- A missing binary causes one rebuild followed by an unchanged run.
|
||||
- A changed checkout causes one rebuild followed by an unchanged run.
|
||||
- A configuration change updates only configuration state and does not rebuild
|
||||
the binary.
|
||||
- Dependency opt-out accepts a caller-supplied `audita_go_binary`.
|
||||
- A play connecting as an ordinary sudo-capable user can apply the role without
|
||||
play-level privilege escalation.
|
||||
- Defaults and argument specifications contain exactly the nine variables in
|
||||
the Fixed Public Interface.
|
||||
- The implementation contains no production CLI validation, fingerprints,
|
||||
checksums, sidecar build state, manual Git reset or clean commands, or probes
|
||||
before state already managed by APT, Snap, `file`, `git`, or `copy`.
|
||||
- Syntax checking, production-profile ansible-lint, focused local convergence,
|
||||
configuration validation, and clean repeated runs pass.
|
||||
- Role documentation describes the actual behavior, dependency opt-out,
|
||||
complete configuration mapping, privilege use, and local test effects.
|
||||
- No repository other than `ansible-role-audita` and the workspace control
|
||||
repository is modified.
|
||||
- All existing source-installation and platform acceptance criteria continue
|
||||
to pass without production task-flow expansion.
|
||||
- Defaults and argument specifications contain exactly the eight installation
|
||||
variables and thirty configuration variables in the Fixed Public Interface.
|
||||
- No `audita_config` compatibility variable remains.
|
||||
- Default convergence writes a YAML mapping containing exactly `version: 1`.
|
||||
- Every optional field is absent when its variable is null.
|
||||
- Setting a representative value in every configuration section renders the
|
||||
correct nested native fields and passes `audita config validate`.
|
||||
- Explicit falsey non-null values are rendered rather than omitted; semantic
|
||||
validity remains Audita's responsibility.
|
||||
- Configuration changes run the template task but not the build task and
|
||||
reach an unchanged immediate repeat.
|
||||
- The installed configuration remains a regular file owned by `root:root`
|
||||
with mode `0644`.
|
||||
- Production tasks do not invoke Audita, inspect the existing configuration,
|
||||
or construct intermediate configuration state.
|
||||
- The README documents each variable, null-as-unmanaged behavior, safe secret
|
||||
environment-variable naming, and the distinction between application and
|
||||
suite defaults.
|
||||
- Syntax checking, production-profile ansible-lint, complete integration
|
||||
testing, native minimal and representative configuration validation, and
|
||||
clean repeated runs pass.
|
||||
- Only `ansible-role-audita` and the workspace control repository change.
|
||||
|
||||
## Dependencies and Follow-up Work
|
||||
|
||||
The managed host requires access to the Audita Git repository, Ubuntu Snap
|
||||
infrastructure, and Go module sources. Runtime processing also requires a
|
||||
glossary, transcript inputs, LLM endpoints, and secret environment variables;
|
||||
those are consumers' or later suite-level features, not installation
|
||||
dependencies.
|
||||
The existing Audita role through commit `3a8c21f` is the implementation
|
||||
baseline. The managed host and test prerequisites are unchanged.
|
||||
|
||||
Implementation and focused integration coverage were completed in
|
||||
`ansible-role-audita` commits `47f1852`, `d37f590`, and `3a8c21f`. The D&D
|
||||
pipeline role can now select concrete `audita_config` values through the
|
||||
standalone role's complete-configuration interface.
|
||||
The configuration amendment was completed in `ansible-role-audita` commits
|
||||
`e61f02f` and `847c4c3` and validated by its complete integration suite. The
|
||||
proposed Notarius roadmap should use the same nullable field-specific approach
|
||||
where appropriate.
|
||||
|
||||
## Potential Future Hardening
|
||||
|
||||
- Build into a temporary path before replacing the installed executable.
|
||||
- Verify source signatures or release checksums.
|
||||
- Detect compiler, build-command, or out-of-band binary changes.
|
||||
- Validate configuration during production convergence.
|
||||
- Manage a dedicated runtime account, secret environment, diagnostics path,
|
||||
service, or schedule if later operating requirements select them.
|
||||
- Add dedicated Ubuntu release and architecture test matrices.
|
||||
- Validate configuration during production convergence if later operating
|
||||
requirements explicitly select that behavior.
|
||||
- Manage secret environment delivery, diagnostics paths, runtime accounts, or
|
||||
services as separate suite-level or application-level features.
|
||||
- Detect source signatures, compiler drift, or out-of-band binary changes if
|
||||
the threat model changes.
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
# Feature 0003: Notarius Source Installation and Configuration
|
||||
|
||||
Status: done
|
||||
|
||||
## Summary
|
||||
|
||||
Provide a small, independently usable `rakestraw.notarius` role that installs
|
||||
Notarius from a pinned Git tag, builds its executable on the managed host, and
|
||||
manages its versioned YAML configuration. Reuse the established module-driven
|
||||
application-role pattern while leaving D&D pipeline policy to the suite-level
|
||||
role.
|
||||
|
||||
## Problem or Opportunity
|
||||
|
||||
At feature selection, the `ansible-role-notarius` repository contained only
|
||||
its initial placeholder files. Notarius is one of the five required pipeline
|
||||
applications and needed an independently usable installation and
|
||||
native-configuration role before the suite role could compose it with
|
||||
Seriatim, Audita, and the remaining applications.
|
||||
|
||||
Seriatim and Audita have established the preferred source-build architecture.
|
||||
Notarius can use the same concise task flow, with only its native configuration
|
||||
and build contract differing.
|
||||
|
||||
## Governing Policies
|
||||
|
||||
- [The Ansible house style](../../ansible.md) governs the role implementation,
|
||||
its public configuration variables, and its template behavior.
|
||||
- [The testing house style](../../testing.md) governs repository-local
|
||||
validation. Tests exercise role-owned behavior through the public interface
|
||||
without snapshotting current defaults, tracing task implementation, or
|
||||
rechecking postconditions owned by trusted Ansible modules.
|
||||
|
||||
## Scope
|
||||
|
||||
- Implement `ansible-role-notarius` as a conventional standalone role.
|
||||
- Support Ubuntu 26.04 on native `amd64` and `arm64` hosts.
|
||||
- Install Git and the official Go Snap with classic confinement when build
|
||||
dependency management is enabled.
|
||||
- Default the Go Snap channel to `1.26/stable`.
|
||||
- Check out immutable Notarius tag `v0.6.0` by default under the root-owned
|
||||
path `/usr/local/src/notarius`.
|
||||
- Build Notarius with its upstream release build contract and install the
|
||||
native executable at `/usr/local/bin/notarius`.
|
||||
- Rebuild when the Git checkout changes or the binary is absent.
|
||||
- Converge the installed binary to `root:root` ownership and mode `0755`.
|
||||
- Manage a versioned Notarius YAML configuration at
|
||||
`/usr/local/etc/notarius/config.yml`, owned by `root:root` with mode `0644`.
|
||||
- Default the managed configuration to the minimal valid mapping
|
||||
`{"version": 4}`, allowing Notarius's built-in defaults to govern behavior.
|
||||
- Expose native configuration through field-specific role variables. Give the
|
||||
required schema version a concrete default and make every optional setting
|
||||
nullable so omitted settings remain owned by Notarius.
|
||||
- Keep defaults, argument specifications, README, metadata, dependency
|
||||
declaration, and focused local tests consistent with this contract.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- A D&D pipeline definition, module selection, LLM profile, concurrency
|
||||
policy, output paths, cache policy, or other suite-specific configuration.
|
||||
- A raw mapping for the complete configuration document, a template override,
|
||||
or competing configuration interfaces.
|
||||
- Role defaults copied from Notarius merely to reproduce the application's
|
||||
built-in defaults in YAML.
|
||||
- Decomposing the open-ended `pipelines` map into role variables for every
|
||||
possible pipeline, step, lane, binding, validator, option, or reference.
|
||||
- API keys, secret values, environment files, or another secret-delivery
|
||||
mechanism.
|
||||
- PromptKit profiles or other externally maintained prompt content.
|
||||
- Creation or management of the `narratio` account, operator groups, campaign
|
||||
data, runtime output, debug, cache, checkpoint, or transcript directories.
|
||||
- Installation or configuration of another pipeline application.
|
||||
- Services, scheduling, removal behavior, or pipeline composition.
|
||||
- Prebuilt release artifacts or cross-compilation.
|
||||
- Production execution of Notarius to validate the build or configuration.
|
||||
- Detection of out-of-band binary modification, compiler changes, or fixed
|
||||
build-command changes.
|
||||
- Build fingerprints, checksums, sidecar state, staged replacement, manual Git
|
||||
cleanup, or special recovery for malformed or adversarial host state.
|
||||
- A shared build helper role or dedicated platform-matrix infrastructure.
|
||||
|
||||
## Target End State
|
||||
|
||||
On an Ubuntu 26.04 `amd64` or `arm64` host, applying the role with defaults
|
||||
installs or confirms Git and Go, checks out Notarius `v0.6.0` at
|
||||
`/usr/local/src/notarius`, builds `/usr/local/bin/notarius`, and writes
|
||||
`/usr/local/etc/notarius/config.yml`. Source and installed files have the
|
||||
stated root ownership and permissions, and the configuration contains
|
||||
`version: 4`.
|
||||
|
||||
When a caller sets an optional configuration variable, the corresponding
|
||||
native field appears in the correct YAML section. Null fields are absent, as
|
||||
are parent sections with no selected descendants. Explicit false, zero, empty
|
||||
string, empty collection, and other non-null values are rendered and left to
|
||||
Notarius's native validation. `notarius_pipelines` represents the native
|
||||
open-ended `pipelines` field as one mapping rather than attempting to mirror
|
||||
its extensible internal schema in Ansible variables. Callers may define
|
||||
pipeline-map fragments in separate inventory files and compose them into the
|
||||
final value with ordinary Ansible/Jinja expressions.
|
||||
|
||||
An immediate second application reports no changes. A changed Git checkout or
|
||||
missing binary causes one build; configuration changes converge independently
|
||||
through the ordinary `ansible.builtin.template` operation.
|
||||
|
||||
Repository-local tests exercise the real role through its public variables.
|
||||
They use the default invocation only as a smoke test, explicitly select
|
||||
immutable `v0.5.0` to prove version selection, exercise missing-binary recovery
|
||||
with a caller-supplied Go executable, and render one representative
|
||||
configuration covering null omission, intentional falsey values, and
|
||||
caller-side pipeline composition. Application-native commands verify the
|
||||
selected release and configuration validity, and immediate repeated
|
||||
applications verify convergence.
|
||||
|
||||
## Repository Ownership
|
||||
|
||||
- `ansible-role-notarius` owns the role implementation, public interface,
|
||||
configuration serialization, metadata, dependency declaration, README, and
|
||||
repository-local validation.
|
||||
- `../notarius` is the read-only authority for build, CLI, and configuration
|
||||
contracts.
|
||||
- `rakestraw-ansible` is a read-only style and deployment-policy reference.
|
||||
- `ansible-role-dnd-pipeline` will later own the D&D-specific configuration
|
||||
supplied through the standalone role's field-specific variables.
|
||||
- `ansible-workspace-dnd` owns this roadmap, the eventual staged plan, and
|
||||
aggregate status.
|
||||
- All other repositories remain unchanged.
|
||||
|
||||
## Constraints and Settled Decisions
|
||||
|
||||
- The selected release is tag `v0.6.0`, which resolves to commit
|
||||
`77ae132e5609916da40dcd4fcc749c000a63cbac`.
|
||||
- The release declares Go 1.25.5. The suite-standard Go Snap channel remains
|
||||
`1.26/stable` and satisfies that requirement.
|
||||
- The upstream release build uses package `./cmd/notarius`, `CGO_ENABLED=0`,
|
||||
`GOWORK=off`, `GOTOOLCHAIN=local`, `-trimpath`, and linker flag
|
||||
`-X gitea.maximumdirect.net/eric/notarius/internal/buildinfo.Override=<version>`.
|
||||
- `notarius --version` prints `notarius <version>`. This is test evidence, not
|
||||
an additional production rebuild trigger or post-build convergence task.
|
||||
- Notarius configuration schema version 4 explicitly supports a document
|
||||
containing only `version: 4`, with omitted values supplied by application
|
||||
defaults.
|
||||
- `notarius_config_version` names the schema version so `notarius_version`
|
||||
remains unambiguously the selected application release.
|
||||
- Optional configuration variables are declared with YAML null defaults.
|
||||
Template conditions use `is not none`, and parent mappings are emitted only
|
||||
when at least one descendant is non-null.
|
||||
- The native `pipelines` field is exposed as the nullable
|
||||
`notarius_pipelines` mapping. It is one field-specific variable, not a raw
|
||||
mapping for the complete document; the role serializes its value without
|
||||
defining a parallel schema for pipeline internals.
|
||||
- Pipeline composition belongs to the caller. For example, inventory may
|
||||
define `notarius_pipeline_group_one` and `notarius_pipeline_group_two` as
|
||||
mappings and set `notarius_pipelines` to
|
||||
`{{ notarius_pipeline_group_one | combine(notarius_pipeline_group_two) }}`.
|
||||
The role accepts and renders the resulting mapping without its own merge or
|
||||
precedence mechanism.
|
||||
- Strings and mappings are serialized with Ansible or Jinja filters rather
|
||||
than hand-written YAML quoting.
|
||||
- `notarius config validate --config <path>` validates a managed configuration
|
||||
without requiring a pipeline selection. It is used only by tests.
|
||||
- Configuration discovery uses an explicit CLI path, then `NOTARIUS_CONFIG`,
|
||||
then `/usr/local/etc/notarius/config.yml`; the role manages the installed
|
||||
default path.
|
||||
- Configuration contains no secrets by default. Consumers arrange any secret
|
||||
environment variables outside this feature.
|
||||
- Tasks that install dependencies or manage root-owned state use task-level
|
||||
`become: true`.
|
||||
- `community.general` supplies Snap management and is pinned to version
|
||||
`13.3.0` in the role's collection requirements.
|
||||
- Tag `v0.5.0` remains buildable with the same Go requirement, package, linker
|
||||
symbol, and configuration schema and is the explicit immutable release used
|
||||
for focused native version-selection coverage.
|
||||
|
||||
## Fixed Public Interface
|
||||
|
||||
Provide these installation variables:
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `notarius_version` | `v0.6.0` | Git revision and release value supplied to the build |
|
||||
| `notarius_repository_url` | `https://gitea.maximumdirect.net/eric/notarius.git` | Source repository |
|
||||
| `notarius_source_dir` | `/usr/local/src/notarius` | Managed source checkout |
|
||||
| `notarius_binary_path` | `/usr/local/bin/notarius` | Installed executable |
|
||||
| `notarius_manage_build_dependencies` | `true` | Whether to install Git and Go |
|
||||
| `notarius_go_snap_channel` | `1.26/stable` | Go Snap channel |
|
||||
| `notarius_go_binary` | `/snap/bin/go` | Go executable used for the build |
|
||||
| `notarius_config_path` | `/usr/local/etc/notarius/config.yml` | Managed configuration file |
|
||||
|
||||
Provide these configuration variables:
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `notarius_config_version` | `4` | `version` |
|
||||
| `notarius_promptkit_profile_dir` | `null` | `promptkit.profile_dir` |
|
||||
| `notarius_promptkit_profile_file` | `null` | `promptkit.profile_file` |
|
||||
| `notarius_promptkit_local_backend_endpoint` | `null` | `promptkit.local_backend.endpoint` |
|
||||
| `notarius_promptkit_local_backend_concurrency_limit` | `null` | `promptkit.local_backend.concurrency_limit` |
|
||||
| `notarius_pipelines` | `null` | `pipelines` |
|
||||
| `notarius_concurrency_total_llm` | `null` | `concurrency.total_llm` |
|
||||
| `notarius_concurrency_stage_workers_extract` | `null` | `concurrency.stage_workers.extract` |
|
||||
| `notarius_output_directory` | `null` | `output.directory` |
|
||||
| `notarius_cache_chunk_plans_mode` | `null` | `cache.chunk_plans.mode` |
|
||||
| `notarius_cache_chunk_plans_directory` | `null` | `cache.chunk_plans.directory` |
|
||||
| `notarius_cache_checkpoints_enabled` | `null` | `cache.checkpoints.enabled` |
|
||||
| `notarius_cache_checkpoints_directory` | `null` | `cache.checkpoints.directory` |
|
||||
| `notarius_debug_directory` | `null` | `debug.directory` |
|
||||
|
||||
The package, build flags, linker symbol, environment values, file ownership,
|
||||
and modes are fixed implementation details. The selected version is both the
|
||||
Git revision and the value supplied to the upstream linker flag.
|
||||
|
||||
Argument specifications type each value according to its native shape. The
|
||||
role does not reproduce semantic relationships such as the mutual exclusion
|
||||
of PromptKit profile sources or the requirement for a local-backend endpoint;
|
||||
Notarius owns those constraints. The `notarius_pipelines` value is a mapping
|
||||
whose nested structure is governed by Notarius's versioned configuration
|
||||
contract.
|
||||
|
||||
## Simplest Viable Implementation
|
||||
|
||||
The expected implementation is approximately nine ordinary tasks in one
|
||||
readable task file:
|
||||
|
||||
1. Assert Ubuntu 26.04 and architecture `x86_64` or `aarch64`.
|
||||
2. Install Git with `ansible.builtin.apt`, including
|
||||
`cache_valid_time: 3600`, when dependency management is enabled.
|
||||
3. Install the classic Go Snap from `notarius_go_snap_channel` with
|
||||
`community.general.snap` when dependency management is enabled.
|
||||
4. Create source, binary, and configuration parent directories with one
|
||||
`ansible.builtin.file` loop.
|
||||
5. Check out `notarius_version` with `ansible.builtin.git`, `force: true`, and
|
||||
register the module result.
|
||||
6. Inspect whether `notarius_binary_path` exists with
|
||||
`ansible.builtin.stat`.
|
||||
7. Run the upstream Go build through `notarius_go_binary` when the checkout
|
||||
changed or the binary is absent.
|
||||
8. Converge recursive source ownership and binary ownership and mode with one
|
||||
item-driven `ansible.builtin.file` loop.
|
||||
9. Render the field-specific configuration with one
|
||||
`ansible.builtin.template` task, conditionally emitting optional fields and
|
||||
parent sections at `notarius_config_path`.
|
||||
|
||||
Apply task-level privilege escalation only where required. Use `argv` for the
|
||||
build command and put its two conditions directly on the build task. Do not
|
||||
add a rebuild fact, handler, handler flush, executable discovery, compiler or
|
||||
version interrogation, configuration assembly facts, preliminary
|
||||
configuration probes, or post-operation validation to production tasks.
|
||||
|
||||
## Rationale and Alternatives
|
||||
|
||||
Notarius has the same installation mechanics as the completed Seriatim and
|
||||
Audita roles: declarative dependency and checkout management surrounding one
|
||||
imperative build command. Binary existence is the only state probe Ansible
|
||||
needs because it controls whether that command must run.
|
||||
|
||||
Field-specific variables are the ordinary ergonomic interface for inventory
|
||||
and composing roles. Nullable defaults expose and type that interface without
|
||||
freezing Notarius's built-in defaults into Ansible. Conditional rendering
|
||||
preserves the distinction between omission and an intentionally falsey value.
|
||||
|
||||
The pipeline definitions are the deliberate exception to leaf-level
|
||||
variables. `pipelines` is itself an open-ended map whose nested keys depend on
|
||||
registered modules and evolve with the application's native schema. Exposing
|
||||
that native field as one nullable mapping keeps the interface practical while
|
||||
still avoiding a raw complete-document mapping or merge semantics. The suite
|
||||
role can later supply its maintained D&D pipeline through
|
||||
`notarius_pipelines` and supply operating policy through the other variables.
|
||||
|
||||
This boundary also supports modular inventory. A consumer can keep one or
|
||||
more pipeline mappings in separate `host_vars`, `group_vars`, or included
|
||||
variable files and combine them when assigning `notarius_pipelines`. Because
|
||||
the native value is a mapping keyed by pipeline ID, dictionary composition
|
||||
uses Ansible's `combine` filter; list concatenation with `+` applies only to
|
||||
list-valued data. The role receives the already composed native mapping and
|
||||
does not need custom loading, merging, or precedence behavior.
|
||||
|
||||
Leaving optional variables undefined would produce the same minimal file but
|
||||
would weaken interface documentation and argument validation. Section-level
|
||||
dictionaries would be less ergonomic for ordinary inventory values. A raw
|
||||
complete configuration mapping would force consumers to replace the required
|
||||
version and unrelated sections together and would conflict with the workspace
|
||||
convention of one field-specific interface.
|
||||
|
||||
Managing `/usr/local/etc/notarius/config.yml` follows the application's own
|
||||
configuration discovery contract and aligns locally installed software with
|
||||
its configuration.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Required Role Behavior
|
||||
|
||||
- The role rejects unsupported distributions, Ubuntu releases, and
|
||||
architectures before modifying application state.
|
||||
- On a supported host, the role installs the selected Notarius source release
|
||||
with its upstream build contract. The default selection for this feature is
|
||||
tag `v0.6.0`, resolving to commit
|
||||
`77ae132e5609916da40dcd4fcc749c000a63cbac`.
|
||||
- The role converges the source tree, binary, and configuration to the paths,
|
||||
ownership, and modes defined above using the responsible Ansible modules.
|
||||
- The default template renders the minimal valid configuration containing the
|
||||
required schema version and leaves optional policy to Notarius.
|
||||
- A non-null optional variable renders its corresponding native field. Null
|
||||
values and parent sections without a selected descendant are omitted;
|
||||
intentional falsey values are preserved.
|
||||
- Independently defined inventory mappings can be combined into
|
||||
`notarius_pipelines`, and the resulting pipeline IDs and definitions are
|
||||
rendered without structural rewriting by the role.
|
||||
- A changed checkout or missing binary causes the imperative build to run. An
|
||||
immediate repeated application with unchanged inputs reports no changes.
|
||||
- Dependency opt-out accepts a caller-supplied `notarius_go_binary`.
|
||||
- Tasks requiring elevated access use task-level privilege escalation, so the
|
||||
role does not require play-level escalation.
|
||||
- Defaults, argument specifications, template behavior, and documentation
|
||||
remain aligned with the public interface without introducing a parallel raw
|
||||
configuration or template-override interface.
|
||||
- Production tasks contain no role-private build state, redundant probes,
|
||||
application self-tests, or other behavior outside the selected invariants.
|
||||
- No repository other than `ansible-role-notarius` and the workspace control
|
||||
repository is modified.
|
||||
|
||||
### Required Validation
|
||||
|
||||
- Syntax checking and production-profile ansible-lint pass.
|
||||
- A default invocation provides a smoke test through the installed CLI and
|
||||
native configuration validator, followed immediately by a role application
|
||||
reporting no changes. The test does not assert that the role's current
|
||||
default release or complete default document remains unchanged.
|
||||
- A focused version-selection case explicitly requests immutable tag `v0.5.0`
|
||||
and verifies that the installed CLI reports `notarius v0.5.0`.
|
||||
- One recovery case removes the binary, disables dependency management,
|
||||
supplies a caller-selected Go executable, confirms that executable is used,
|
||||
and finishes with a clean repeated application.
|
||||
- One representative configuration case verifies selected rendered values,
|
||||
selected omissions, intentional falsey values, and caller-side composition
|
||||
of two pipeline mappings. The native Notarius validator accepts the result,
|
||||
and an immediate repeated application reports no changes.
|
||||
- Tests do not assert task names or order, individual task results, exact
|
||||
current defaults, complete configuration snapshots, public-variable counts,
|
||||
trusted-module file or package postconditions, or an exhaustive negative
|
||||
platform matrix.
|
||||
|
||||
## Dependencies and Follow-up Work
|
||||
|
||||
The managed host requires access to the Notarius Git repository, Ubuntu Snap
|
||||
infrastructure, and Go module sources. Actual transcript processing also needs
|
||||
a configured pipeline, input artifacts, PromptKit assets and endpoints, and
|
||||
secret environment variables; those belong to consumers or later suite-level
|
||||
work.
|
||||
|
||||
The role was implemented in `ansible-role-notarius` commits `287fc4a` and
|
||||
`733a194`, then finalized by remediation commit `eb4f511`. Its complete
|
||||
integration suite passes. The pipeline role can now supply its D&D definitions
|
||||
through `notarius_pipelines` and select the other field-specific values.
|
||||
|
||||
## Potential Future Hardening
|
||||
|
||||
- Build into a temporary path before replacing the installed executable.
|
||||
- Verify source signatures or release checksums.
|
||||
- Detect compiler, build-command, or out-of-band binary changes.
|
||||
- Validate configuration during production convergence.
|
||||
- Manage a dedicated runtime account, secret environment, state paths,
|
||||
service, or schedule if later operating requirements select them.
|
||||
- Add broader Ubuntu release and architecture test coverage only if future
|
||||
platform behavior warrants it.
|
||||
@@ -0,0 +1,335 @@
|
||||
# Feature 0004: Scriptorium Source Installation and Configuration
|
||||
|
||||
Status: done
|
||||
|
||||
## Summary
|
||||
|
||||
Provide a small, independently usable `rakestraw.scriptorium` role that
|
||||
installs Scriptorium from a pinned Git tag, builds its executable on the
|
||||
managed host, and manages its native YAML configuration. Preserve
|
||||
Scriptorium's usefulness inside and outside the D&D transcript pipeline by
|
||||
keeping application configuration in the standalone role and leaving prompt
|
||||
library content and suite policy to their eventual owners.
|
||||
|
||||
## Problem or Opportunity
|
||||
|
||||
The `ansible-role-scriptorium` repository contains only its initial README and
|
||||
license. Scriptorium is one of the five applications required by the pipeline,
|
||||
but it is also a generally useful Promptkit-based application with independent
|
||||
consumers. It needs a complete standalone installation and configuration role
|
||||
before the pipeline role can compose it without owning Scriptorium-specific
|
||||
behavior.
|
||||
|
||||
The completed Seriatim, Audita, and Notarius roles establish the concise
|
||||
source-build pattern. Scriptorium can reuse that pattern while exposing its own
|
||||
configuration contract through field-specific, nullable variables.
|
||||
|
||||
## Governing Policies
|
||||
|
||||
- [The Ansible house style](../../ansible.md) governs the role implementation,
|
||||
public configuration interface, and template.
|
||||
- [The testing house style](../../testing.md) governs repository-local
|
||||
validation. Tests exercise role-owned behavior through public inputs and
|
||||
native application outcomes without snapshotting defaults, tracing tasks, or
|
||||
rechecking trusted-module postconditions.
|
||||
- [The MVP roadmap](../mvp.md) fixes the common source-build architecture,
|
||||
supported platform, filesystem layout, and standalone-role boundary.
|
||||
|
||||
## Scope
|
||||
|
||||
- Implement `ansible-role-scriptorium` as a conventional standalone role.
|
||||
- Support Ubuntu 26.04 on native `amd64` and `arm64` hosts.
|
||||
- Install Git and the official Go Snap with classic confinement when build
|
||||
dependency management is enabled.
|
||||
- Default the Go Snap channel to `1.26/stable`.
|
||||
- Check out immutable Scriptorium tag `v0.13.0` by default under
|
||||
`/usr/local/src/scriptorium`.
|
||||
- Build the native executable with Scriptorium's release build contract and
|
||||
install it at `/usr/local/bin/scriptorium`.
|
||||
- Rebuild when the Git checkout changes or the binary is absent.
|
||||
- Converge the source tree to `root:root` ownership and the installed binary to
|
||||
`root:root` ownership and mode `0755`.
|
||||
- Manage `/usr/local/etc/scriptorium/config.yml` as `root:root` with mode
|
||||
`0644` using one role-owned template.
|
||||
- Render `{}` when no application settings are selected, allowing Scriptorium
|
||||
to use its built-in defaults without copying them into Ansible.
|
||||
- Expose every application configuration field through a field-specific role
|
||||
variable. Default each field to null and omit it from the rendered document
|
||||
until a caller supplies a non-null value.
|
||||
- Expose the native open-ended `backends` mapping as one nullable variable and
|
||||
serialize the caller's mapping without inventing a second backend schema or
|
||||
merge mechanism.
|
||||
- Keep defaults, argument specifications, README, metadata, collection
|
||||
dependency declaration, template, and focused integration tests aligned with
|
||||
this contract.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- D&D-specific prompts, profiles, schemas, model choices, paths, or other
|
||||
pipeline policy.
|
||||
- Cloning, copying, or otherwise populating prompt, profile, or schema
|
||||
libraries.
|
||||
- A role-managed Scriptorium service, HTTP listener lifecycle, scheduler, or
|
||||
persistent runtime account.
|
||||
- A raw mapping for the complete configuration document, a template override,
|
||||
or parallel configuration interfaces.
|
||||
- Copying Scriptorium's documented built-in defaults into role defaults merely
|
||||
to render them back into YAML.
|
||||
- Decomposing the open-ended `backends` mapping into variables for each backend
|
||||
ID or backend-specific option.
|
||||
- Secret values, environment files, or another credential-delivery mechanism.
|
||||
- Installation or configuration of Promptkit, another pipeline application,
|
||||
or the complete D&D suite.
|
||||
- Installation from Scriptorium's published binary artifacts, cross-compiling,
|
||||
or supporting platforms outside the MVP.
|
||||
- Production execution of Scriptorium to validate its binary or configuration.
|
||||
- Detection of out-of-band binary modification, compiler changes, or fixed
|
||||
build-command changes.
|
||||
- Build fingerprints, checksums, sidecar state, staged replacement, manual Git
|
||||
cleanup, or special recovery for malformed or adversarial host state.
|
||||
|
||||
## Target End State
|
||||
|
||||
On a supported host, applying the role with defaults installs or confirms Git
|
||||
and Go, checks out Scriptorium `v0.13.0` at
|
||||
`/usr/local/src/scriptorium`, builds `/usr/local/bin/scriptorium`, and manages
|
||||
`/usr/local/etc/scriptorium/config.yml`. The managed configuration is the empty
|
||||
mapping `{}`, so Scriptorium retains ownership of all application defaults.
|
||||
|
||||
When a caller sets an optional configuration variable, the corresponding
|
||||
native YAML field appears in the correct section. Null fields are absent, as
|
||||
are parent mappings with no selected descendants. Explicit false, zero, empty
|
||||
string, empty collection, and other non-null values are serialized rather than
|
||||
silently omitted, leaving their native semantics to Scriptorium.
|
||||
`scriptorium_backends` represents the complete native `backends` field as a
|
||||
mapping keyed by backend ID; the role does not rewrite its nested definitions
|
||||
or combine fragments. Callers and composing roles may construct the final
|
||||
mapping with ordinary inventory and Jinja expressions.
|
||||
|
||||
Prompt, profile, and schema directories remain caller-provided application
|
||||
inputs. The standalone role exposes their configuration paths but does not
|
||||
populate them. A later pipeline feature will deploy the maintained prompt
|
||||
library and pass its selected locations through this public interface.
|
||||
|
||||
An immediate repeated application reports no changes. A changed checkout or a
|
||||
missing binary causes the build command to run. Configuration changes converge
|
||||
through the template without becoming build triggers.
|
||||
|
||||
## Repository Ownership
|
||||
|
||||
- `ansible-role-scriptorium` owns the role implementation, public variables,
|
||||
native configuration serialization, metadata, dependency declaration,
|
||||
documentation, and repository-local tests.
|
||||
- `../scriptorium` is the read-only authority for release, build, CLI, and
|
||||
configuration contracts.
|
||||
- `rakestraw-ansible` is a read-only style and historical deployment reference.
|
||||
- `ansible-role-dnd-pipeline` will later own D&D-specific Scriptorium values and
|
||||
prompt-library deployment through the standalone role's public interface.
|
||||
- `ansible-workspace-dnd` owns this roadmap, the eventual staged implementation
|
||||
plan, and aggregate status.
|
||||
- All other repositories remain unchanged.
|
||||
|
||||
## Constraints and Settled Decisions
|
||||
|
||||
- The selected default release is annotated tag `v0.13.0`, resolving to commit
|
||||
`f33af205242cbaeeb689c179c0465bd10beaa1a3`.
|
||||
- The release declares Go 1.25.5. The suite-standard `1.26/stable` Go Snap
|
||||
channel satisfies that requirement.
|
||||
- The native build uses package `./cmd/scriptorium`, `CGO_ENABLED=0`,
|
||||
`GOWORK=off`, `GOTOOLCHAIN=local`, `-trimpath`, and linker flags `-s -w`.
|
||||
- Scriptorium does not embed the selected application tag and does not expose a
|
||||
native application-version command. Production convergence does not add
|
||||
version interrogation, and tests do not inspect the Git checkout merely to
|
||||
manufacture version evidence.
|
||||
- Scriptorium accepts an empty configuration and resolves all omitted settings
|
||||
from built-in defaults. The role renders `{}` so the managed file is an
|
||||
explicit YAML mapping while selecting no application policy.
|
||||
- Configuration discovery checks `/usr/local/etc/scriptorium/config.yml`
|
||||
before `/etc/scriptorium/config.yml`; the role manages the first path.
|
||||
- Optional variables use YAML null defaults and template conditions use
|
||||
`is not none`. Parent mappings are emitted only when at least one descendant
|
||||
is non-null.
|
||||
- Strings and mappings are serialized with Ansible or Jinja filters rather
|
||||
than hand-written YAML quoting.
|
||||
- `scriptorium_backends` is a native open-ended mapping. Caller-side mapping
|
||||
composition is permitted, but the role supplies no merge or precedence
|
||||
behavior.
|
||||
- Backend configuration may name a credential environment variable through
|
||||
`api_key_env`; secret values themselves remain outside the role and managed
|
||||
file.
|
||||
- Tasks installing dependencies or managing root-owned state use task-level
|
||||
`become: true`.
|
||||
- `community.general` supplies Snap management and is pinned to version
|
||||
`13.3.0` in the role's collection requirements.
|
||||
|
||||
## Fixed Public Interface
|
||||
|
||||
Provide these installation variables:
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `scriptorium_version` | `v0.13.0` | Selected Git revision |
|
||||
| `scriptorium_repository_url` | `https://gitea.maximumdirect.net/eric/scriptorium.git` | Source repository |
|
||||
| `scriptorium_source_dir` | `/usr/local/src/scriptorium` | Managed source checkout |
|
||||
| `scriptorium_binary_path` | `/usr/local/bin/scriptorium` | Installed executable |
|
||||
| `scriptorium_manage_build_dependencies` | `true` | Whether to install Git and Go |
|
||||
| `scriptorium_go_snap_channel` | `1.26/stable` | Go Snap channel |
|
||||
| `scriptorium_go_binary` | `/snap/bin/go` | Go executable used for the build |
|
||||
| `scriptorium_config_path` | `/usr/local/etc/scriptorium/config.yml` | Managed configuration file |
|
||||
|
||||
Provide these nullable configuration variables:
|
||||
|
||||
| Variable | Native field |
|
||||
| --- | --- |
|
||||
| `scriptorium_prompt_dir` | `prompt_dir` |
|
||||
| `scriptorium_profile_dir` | `profile_dir` |
|
||||
| `scriptorium_schema_dir` | `schema_dir` |
|
||||
| `scriptorium_server_addr` | `server.addr` |
|
||||
| `scriptorium_server_artifact_root` | `server.artifact_root` |
|
||||
| `scriptorium_server_max_request_bytes` | `server.max_request_bytes` |
|
||||
| `scriptorium_server_max_artifact_bytes` | `server.max_artifact_bytes` |
|
||||
| `scriptorium_server_max_response_bytes` | `server.max_response_bytes` |
|
||||
| `scriptorium_defaults_render_format` | `defaults.render_format` |
|
||||
| `scriptorium_backends` | `backends` |
|
||||
|
||||
Argument specifications type paths and strings according to their native
|
||||
shape, the three server limits as integers, and `scriptorium_backends` as a
|
||||
mapping. They do not reproduce semantic validation owned by Scriptorium. The
|
||||
role preserves non-null values while the application decides whether a
|
||||
selected value is valid or effective.
|
||||
|
||||
## Simplest Viable Implementation
|
||||
|
||||
The expected production implementation is approximately nine ordinary tasks
|
||||
in one readable task file:
|
||||
|
||||
1. Assert Ubuntu 26.04 and architecture `x86_64` or `aarch64`.
|
||||
2. Install Git with `ansible.builtin.apt`, including
|
||||
`cache_valid_time: 3600`, when dependency management is enabled.
|
||||
3. Install the classic Go Snap from `scriptorium_go_snap_channel` with
|
||||
`community.general.snap` when dependency management is enabled.
|
||||
4. Create the source, binary, and configuration parent directories with one
|
||||
`ansible.builtin.file` loop.
|
||||
5. Check out `scriptorium_version` with `ansible.builtin.git`, `force: true`,
|
||||
and register the module result.
|
||||
6. Inspect whether `scriptorium_binary_path` exists with
|
||||
`ansible.builtin.stat`.
|
||||
7. Run the native Go build through `scriptorium_go_binary` when the checkout
|
||||
changed or the binary is absent.
|
||||
8. Converge recursive source ownership and binary ownership and mode with one
|
||||
item-driven `ansible.builtin.file` loop.
|
||||
9. Render the field-specific configuration with one
|
||||
`ansible.builtin.template` task.
|
||||
|
||||
Use `argv` for the build command, declare its change semantics, and put its two
|
||||
conditions directly on the task. Do not add a rebuild fact, handler, executable
|
||||
discovery, compiler or application interrogation, configuration assembly facts,
|
||||
preliminary configuration probes, or post-operation validation to production
|
||||
tasks.
|
||||
|
||||
## Rationale and Alternatives
|
||||
|
||||
A standalone role is valuable beyond the D&D pipeline and prevents the suite
|
||||
role from becoming the owner of Scriptorium's native application interface.
|
||||
The suite can later provide opinionated directory paths and backend choices
|
||||
without reducing the role's usefulness to independent consumers.
|
||||
|
||||
Field-specific nullable variables preserve a documented and typed inventory
|
||||
interface while allowing upstream defaults to evolve. Rendering `{}` is
|
||||
preferable to copying those defaults into Ansible and is more explicit than an
|
||||
empty file. Conditional sections distinguish omission from intentional falsey
|
||||
values.
|
||||
|
||||
The `backends` mapping is the deliberate exception to leaf-level variables.
|
||||
Its keys are caller-defined backend IDs and its values follow an extensible
|
||||
native schema. Passing that one native field through as a mapping is simpler
|
||||
and more useful than inventing variables for arbitrary IDs, while still
|
||||
avoiding a raw mapping for the complete configuration document.
|
||||
|
||||
The role exposes server configuration because it is part of Scriptorium's
|
||||
native interface, but it does not infer that callers want a managed service.
|
||||
Consumers may invoke the CLI directly or arrange their own process lifecycle.
|
||||
|
||||
Scriptorium now publishes binary release artifacts, but the MVP deliberately
|
||||
uses the common source-build model across all five applications. Artifact-based
|
||||
installation remains a later cross-suite decision.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Required Role Behavior
|
||||
|
||||
- The role rejects unsupported platforms before modifying application state.
|
||||
- On a supported host, it installs the selected Scriptorium source release and
|
||||
builds the binary with the upstream release contract.
|
||||
- Source, binary, and configuration state converge to the paths, ownership,
|
||||
and modes selected above through the responsible Ansible modules.
|
||||
- With no configuration variables selected, the template renders `{}` and
|
||||
Scriptorium accepts the managed file while retaining its built-in defaults.
|
||||
- Each non-null configuration variable renders its corresponding native field.
|
||||
Null fields and empty parent sections are omitted, while intentional falsey
|
||||
values are retained.
|
||||
- A caller-supplied backend mapping is rendered without structural rewriting,
|
||||
and independently defined mappings can be composed before assignment.
|
||||
- A changed checkout or missing binary causes the imperative build to run. An
|
||||
immediate repeated application with unchanged inputs reports no changes.
|
||||
- Dependency opt-out accepts a caller-supplied `scriptorium_go_binary`.
|
||||
- Root-owned operations use task-level privilege escalation; play-level
|
||||
escalation is not required.
|
||||
- Defaults, argument specifications, template behavior, README, and metadata
|
||||
remain aligned with the public interface.
|
||||
- Production tasks contain no role-private state, redundant probes,
|
||||
application self-tests, or speculative guarantees.
|
||||
- No repository other than `ansible-role-scriptorium` and the workspace control
|
||||
repository is modified.
|
||||
|
||||
### Required Validation
|
||||
|
||||
- Syntax checking and production-profile ansible-lint pass.
|
||||
- A default invocation exercises the installed application with the managed
|
||||
configuration, followed immediately by a role application reporting no
|
||||
changes. It does not snapshot the role's current default tag or complete
|
||||
default document.
|
||||
- One recovery case removes the binary, disables dependency management,
|
||||
supplies a caller-selected Go executable, confirms that executable is used,
|
||||
and finishes with a clean repeated application.
|
||||
- One representative configuration case verifies selected scalar and nested
|
||||
values, selected omissions, intentional zero values, and a caller-supplied
|
||||
backend mapping. An offline native Scriptorium command accepts and uses the
|
||||
managed configuration, and an immediate repeated application reports no
|
||||
changes.
|
||||
- Tests do not assert task names or order, individual task results, exact
|
||||
current defaults, complete configuration snapshots, public-variable counts,
|
||||
trusted-module file or package postconditions, or an exhaustive negative
|
||||
platform matrix.
|
||||
- Because Scriptorium exposes no native application release identity, the test
|
||||
suite does not substitute a Git-checkout assertion or version-specific
|
||||
behavior snapshot for a native version-selection test.
|
||||
|
||||
## Dependencies and Follow-up Work
|
||||
|
||||
The managed host requires access to the Scriptorium Git repository, Ubuntu
|
||||
Snap infrastructure, and Go module sources. Useful prompt execution also needs
|
||||
prompt definitions and, depending on the chosen configuration, profiles,
|
||||
schemas, backend endpoints, and credential environment variables. Those inputs
|
||||
remain caller responsibilities for this standalone feature.
|
||||
|
||||
With this feature complete, the Narratio standalone role can be designed
|
||||
against all four downstream application-role interfaces. The later pipeline
|
||||
role will install maintained prompt-library content and supply D&D-specific
|
||||
Scriptorium configuration through this role.
|
||||
|
||||
The role was implemented in `ansible-role-scriptorium` commits `90d7f45` and
|
||||
`5944eac`, then finalized after independent review by remediation commit
|
||||
`8f47aa8`. Its complete integration suite passes.
|
||||
|
||||
## Potential Future Hardening
|
||||
|
||||
- Build into a temporary path before replacing the installed executable.
|
||||
- Verify source signatures or release artifacts.
|
||||
- Detect compiler, build-command, or out-of-band binary changes.
|
||||
- Validate configuration during production convergence.
|
||||
- Manage a service, runtime account, secret environment, or network controls if
|
||||
later operating requirements select them.
|
||||
- Support Scriptorium's published binary artifacts as part of a future
|
||||
suite-wide installation-model change.
|
||||
- Add broader platform coverage only when supported-platform behavior expands.
|
||||
@@ -0,0 +1,465 @@
|
||||
# Feature 0005: Narratio Source Installation and Configuration
|
||||
|
||||
Status: done
|
||||
|
||||
## Summary
|
||||
|
||||
Provide a small, independently usable `rakestraw.narratio` role that installs
|
||||
Narratio from a pinned Git tag, builds its executable on the managed host,
|
||||
creates the application account and runtime directories, and manages its
|
||||
native pipeline configuration. Keep the role application-specific so the
|
||||
later suite role can supply D&D policy through its public interface without
|
||||
making the Narratio role responsible for the other applications or campaign
|
||||
content.
|
||||
|
||||
## Problem or Opportunity
|
||||
|
||||
The `ansible-role-narratio` repository contains only its initial README and
|
||||
license. Narratio is the command-line orchestrator for the transcript pipeline,
|
||||
so the complete suite cannot be composed until Narratio has an independently
|
||||
usable installation and configuration role.
|
||||
|
||||
The four completed downstream application roles establish the concise
|
||||
source-build pattern. Narratio can reuse that pattern, but its native contract
|
||||
also requires a deployment account, shared writable runtime areas, a campaign
|
||||
registry root, and a substantially larger pipeline configuration interface.
|
||||
This feature fixes those boundaries before suite composition begins.
|
||||
|
||||
## Governing Policies
|
||||
|
||||
- [The Ansible house style](../../ansible.md) governs the role implementation,
|
||||
public configuration interface, and template.
|
||||
- [The testing house style](../../testing.md) governs repository-local
|
||||
validation. Tests exercise role-owned behavior through public inputs and
|
||||
native application outcomes without snapshotting defaults, tracing tasks, or
|
||||
rechecking trusted-module postconditions.
|
||||
- [The MVP roadmap](../mvp.md) fixes the common source-build architecture,
|
||||
supported platform, filesystem layout, and standalone-role boundary.
|
||||
|
||||
## Scope
|
||||
|
||||
- Implement `ansible-role-narratio` as a conventional standalone role.
|
||||
- Support Ubuntu 26.04 on native `amd64` and `arm64` hosts.
|
||||
- Install Git and the official Go Snap with classic confinement when build
|
||||
dependency management is enabled.
|
||||
- Default the Go Snap channel to `1.26/stable`.
|
||||
- Check out immutable Narratio tag `v2.0.0` by default under
|
||||
`/usr/local/src/narratio`.
|
||||
- Build the native executable with Narratio's release build contract and
|
||||
install it at `/usr/local/bin/narratio`.
|
||||
- Rebuild when the Git checkout changes or the binary is absent.
|
||||
- Converge the source tree and installed binary to root ownership, with the
|
||||
binary at mode `0755`.
|
||||
- Create the `narratio` system group and system account with
|
||||
`/var/lib/narratio` as its home and a non-login shell.
|
||||
- Create the workspace, spool, and cache roots as group-writable,
|
||||
setgid directories owned by `narratio:narratio`.
|
||||
- Create the campaign registry as a root-managed, operator-readable content
|
||||
root; leave its contents to the suite role or another caller.
|
||||
- Manage `/usr/local/etc/narratio/pipeline.yml` as `root:narratio` with mode
|
||||
`0640` using one role-owned template.
|
||||
- Require the caller to supply the deployment-specific WhisperX transcription
|
||||
URL because Narratio has no valid universal value for this required field.
|
||||
- Give filesystem roots concrete role-owned defaults. Default other optional
|
||||
application settings to null and omit them until a caller supplies a
|
||||
non-null value, allowing Narratio to retain ownership of its built-in
|
||||
defaults.
|
||||
- Expose scalar fields individually. Expose native open-ended collections as
|
||||
one variable each, including publish outputs, Notarius references and
|
||||
outputs, and Scriptorium artifacts and artifact families.
|
||||
- Permit callers to compose those collection variables in inventory before
|
||||
assigning the final value; do not add role-owned merge or precedence logic.
|
||||
- Expose ConfigKit's explicit import list in the root document without taking
|
||||
ownership of the imported fragments or named profile overlays.
|
||||
- Keep defaults, argument specifications, README, metadata, collection
|
||||
dependency declaration, template, and focused integration tests aligned
|
||||
with this contract.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Installing or configuring Audita, Notarius, Seriatim, Scriptorium, WhisperX,
|
||||
or the complete D&D suite.
|
||||
- Populating campaign data, prompt libraries, profiles, schemas, or session
|
||||
documents.
|
||||
- Selecting D&D-specific pipelines, campaigns, models, prompts, artifacts,
|
||||
extraction lanes, publish rules, storage providers, or application paths.
|
||||
- Managing ConfigKit import fragments or named profile overlay files.
|
||||
- Managing credentials, secret values, a secrets directory, environment
|
||||
injection, or the pipeline-wide secret-delivery policy.
|
||||
- Adding human operator accounts to the `narratio` group; the suite role owns
|
||||
operator selection and membership.
|
||||
- A Narratio daemon, service unit, scheduler, or timer.
|
||||
- A raw mapping for the complete pipeline document, a template override, or a
|
||||
second parallel configuration interface.
|
||||
- Copying Narratio's built-in defaults into role defaults merely to render
|
||||
them back into YAML.
|
||||
- Decomposing open-ended artifact, artifact-family, reference, or output maps
|
||||
into variables for caller-defined keys.
|
||||
- Installing from published binary artifacts, cross-compiling, or supporting
|
||||
platforms outside the MVP.
|
||||
- Production execution of Narratio to validate its binary or configuration.
|
||||
- Detection of out-of-band binary modification, compiler changes, or fixed
|
||||
build-command changes.
|
||||
- Build fingerprints, checksums, sidecar state, staged replacement, manual Git
|
||||
cleanup, or special recovery for malformed or adversarial host state.
|
||||
|
||||
## Target End State
|
||||
|
||||
On a supported host, applying the role with the required
|
||||
`narratio_whisperx_transcribe_url` installs or confirms Git and Go, creates the
|
||||
Narratio account and filesystem roots, checks out Narratio `v2.0.0` at
|
||||
`/usr/local/src/narratio`, builds `/usr/local/bin/narratio`, and manages
|
||||
`/usr/local/etc/narratio/pipeline.yml`.
|
||||
|
||||
The baseline managed pipeline document contains only the caller's required
|
||||
WhisperX URL and the filesystem roots the role deliberately owns. Narratio
|
||||
continues to supply all other application defaults. When a caller sets an
|
||||
optional configuration variable, the corresponding native YAML field appears
|
||||
in the correct section. Null fields and parent mappings with no selected
|
||||
descendants are absent. Explicit false, zero, empty string, empty list, empty
|
||||
mapping, and other non-null values are serialized rather than silently
|
||||
omitted, leaving their native semantics to Narratio.
|
||||
|
||||
Native open-ended collections pass through without structural rewriting.
|
||||
Callers and composing roles may define fragments in separate inventory files
|
||||
and combine them with ordinary Ansible/Jinja expressions before assigning the
|
||||
final collection variable. The role does not merge fragments or define
|
||||
precedence among them.
|
||||
|
||||
The `narratio` account owns the mutable workspace, spool, and cache roots.
|
||||
Their setgid group-write permissions support later direct invocation by human
|
||||
operators whom the suite role adds to the `narratio` group. The root-managed
|
||||
campaign registry remains readable but not writable by those operators.
|
||||
|
||||
An immediate repeated application reports no changes. A changed checkout or a
|
||||
missing binary causes the build command to run. Account, directory, and
|
||||
configuration changes converge through their responsible Ansible modules and
|
||||
do not become build triggers.
|
||||
|
||||
## Repository Ownership
|
||||
|
||||
- `ansible-role-narratio` owns the role implementation, application account,
|
||||
runtime and campaign-root state, public variables, native root pipeline
|
||||
serialization, metadata, dependency declaration, documentation, and
|
||||
repository-local tests.
|
||||
- `../narratio` is the read-only authority for release, build, CLI,
|
||||
configuration, filesystem, and integration contracts.
|
||||
- `rakestraw-ansible` is a read-only style and historical deployment reference.
|
||||
- `ansible-role-dnd-pipeline` will later own compatible application versions,
|
||||
D&D-specific Narratio values, campaign and prompt content, secret delivery,
|
||||
and human operator membership through the standalone roles' public
|
||||
interfaces.
|
||||
- `ansible-workspace-dnd` owns this roadmap, the eventual staged implementation
|
||||
plan, and aggregate status.
|
||||
- All other repositories remain unchanged.
|
||||
|
||||
## Constraints and Settled Decisions
|
||||
|
||||
- The selected default release is lightweight tag `v2.0.0`, resolving to
|
||||
commit `ed4623bc415901134c765fe9cf06d59aa7891500`.
|
||||
- The release declares Go 1.26.0. The suite-standard `1.26/stable` Go Snap
|
||||
channel satisfies that requirement.
|
||||
- The native build uses package `./cmd/narratio`, `CGO_ENABLED=0`,
|
||||
`GOWORK=off`, `GOTOOLCHAIN=local`, `-trimpath`, and linker flags
|
||||
`-s -w -X gitea.maximumdirect.net/eric/narratio/internal/buildinfo.Version=<version>`.
|
||||
- `narratio version` reports the embedded selected tag and provides the native
|
||||
observable for an explicitly requested version in integration tests.
|
||||
- Narratio discovers `/usr/local/etc/narratio/pipeline.yml` before
|
||||
`/etc/narratio/pipeline.yml`; the role manages the first path by default.
|
||||
- `whisperx.transcribe_url` is the only pipeline field without an application
|
||||
default that is required for pipeline validation. The role therefore exposes
|
||||
`narratio_whisperx_transcribe_url` as a required public input rather than
|
||||
inventing a deployment endpoint.
|
||||
- Workspace, campaign, spool, and cache roots are concrete role defaults
|
||||
because the role creates and owns the corresponding filesystem state. These
|
||||
are intentional deployment policy, not a duplicate database of application
|
||||
defaults.
|
||||
- All other optional configuration variables use YAML null defaults and
|
||||
template conditions use `is not none`. Parent mappings are emitted only
|
||||
when at least one descendant is non-null.
|
||||
- Strings and collections are serialized with Ansible or Jinja filters rather
|
||||
than hand-written YAML quoting.
|
||||
- `narratio_publish_outputs`, `narratio_notarius_references`,
|
||||
`narratio_notarius_outputs`, `narratio_scriptorium_artifacts`, and
|
||||
`narratio_scriptorium_artifact_families` represent their complete native
|
||||
fields. Caller-side composition is permitted, but the role supplies no merge
|
||||
behavior.
|
||||
- Credential configuration contains environment-variable names only. Secret
|
||||
values remain outside the role and managed pipeline document.
|
||||
- The configuration directory is `root:narratio` mode `0750`; the pipeline
|
||||
file is `root:narratio` mode `0640`.
|
||||
- Mutable runtime roots are `narratio:narratio` mode `2775`. The campaign root
|
||||
is `root:narratio` mode `0755` because version-controlled content is
|
||||
populated by a separate owner and is not operator-edited on the host.
|
||||
- Tasks installing dependencies or managing privileged state use task-level
|
||||
`become: true`.
|
||||
- `community.general` supplies Snap management and is pinned to version
|
||||
`13.3.0` in the role's collection requirements.
|
||||
|
||||
## Fixed Public Interface
|
||||
|
||||
### Installation and Managed Filesystem
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `narratio_version` | `v2.0.0` | Selected Git revision and embedded build version |
|
||||
| `narratio_repository_url` | `https://gitea.maximumdirect.net/eric/narratio.git` | Source repository |
|
||||
| `narratio_source_dir` | `/usr/local/src/narratio` | Managed source checkout |
|
||||
| `narratio_binary_path` | `/usr/local/bin/narratio` | Installed executable |
|
||||
| `narratio_manage_build_dependencies` | `true` | Whether to install Git and Go |
|
||||
| `narratio_go_snap_channel` | `1.26/stable` | Go Snap channel |
|
||||
| `narratio_go_binary` | `/snap/bin/go` | Go executable used for the build |
|
||||
| `narratio_user` | `narratio` | System account owning mutable runtime state |
|
||||
| `narratio_group` | `narratio` | System group sharing mutable runtime state |
|
||||
| `narratio_config_path` | `/usr/local/etc/narratio/pipeline.yml` | Managed root pipeline document |
|
||||
| `narratio_workspace_root` | `/var/lib/narratio` | Managed workspace root and account home |
|
||||
| `narratio_campaigns_root` | `/usr/local/share/narratio/campaigns` | Managed campaign registry root |
|
||||
| `narratio_spool_root` | `/var/spool/narratio` | Managed spool root |
|
||||
| `narratio_cache_root` | `/var/cache/narratio` | Managed cache root |
|
||||
|
||||
Changing a managed root changes both its rendered pipeline value and the
|
||||
directory the role manages. The role does not infer additional arbitrary paths
|
||||
embedded inside caller-supplied open-ended collections.
|
||||
|
||||
### Pipeline Structure and Storage
|
||||
|
||||
Except where a default is shown, every variable below defaults to null and is
|
||||
omitted when null.
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `narratio_configkit_imports` | `null` | `configkit.imports` |
|
||||
| `narratio_workspace_cleanup_after_publish` | `null` | `workspace.cleanup_after_publish` |
|
||||
| `narratio_campaigns_default_campaign_id` | `null` | `campaigns.default_campaign_id` |
|
||||
| `narratio_storage_backend` | `null` | `storage.backend` |
|
||||
| `narratio_storage_s3_bucket` | `null` | `storage.s3.bucket` |
|
||||
| `narratio_storage_s3_root_prefix` | `null` | `storage.s3.root_prefix` |
|
||||
| `narratio_storage_s3_region` | `null` | `storage.s3.region` |
|
||||
| `narratio_storage_s3_endpoint` | `null` | `storage.s3.endpoint` |
|
||||
| `narratio_storage_s3_force_path_style` | `null` | `storage.s3.force_path_style` |
|
||||
| `narratio_storage_s3_access_key_id` | `null` | `storage.s3.access_key_id` environment-variable name |
|
||||
| `narratio_storage_s3_secret_access_key` | `null` | `storage.s3.secret_access_key` environment-variable name |
|
||||
| `narratio_spool_delete_audio_after_publish` | `null` | `spool.delete_audio_after_publish` |
|
||||
| `narratio_cache_s3_audio` | `null` | `cache.s3_audio` |
|
||||
| `narratio_publish_enabled` | `null` | `publish.enabled` |
|
||||
| `narratio_publish_upload_run` | `null` | `publish.upload_run` |
|
||||
| `narratio_publish_outputs` | `null` | Complete native `publish.outputs` list |
|
||||
|
||||
### WhisperX, Seriatim, and Audita
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `narratio_whisperx_transcribe_url` | required | `whisperx.transcribe_url` |
|
||||
| `narratio_whisperx_language` | `null` | `whisperx.language` |
|
||||
| `narratio_whisperx_timeout` | `null` | `whisperx.timeout` |
|
||||
| `narratio_whisperx_retries` | `null` | `whisperx.retries` |
|
||||
| `narratio_whisperx_retry_delay` | `null` | `whisperx.retry_delay` |
|
||||
| `narratio_whisperx_concurrency` | `null` | `whisperx.concurrency` |
|
||||
| `narratio_seriatim_binary` | `null` | `seriatim.binary` |
|
||||
| `narratio_seriatim_timeout` | `null` | `seriatim.timeout` |
|
||||
| `narratio_seriatim_output_schema` | `null` | `seriatim.output_schema` |
|
||||
| `narratio_seriatim_coalesce_gap` | `null` | `seriatim.coalesce_gap` |
|
||||
| `narratio_seriatim_report` | `null` | `seriatim.report` |
|
||||
| `narratio_seriatim_env_overlap_word_run_gap` | `null` | `seriatim.env.overlap_word_run_gap` |
|
||||
| `narratio_seriatim_env_overlap_word_run_reorder_window` | `null` | `seriatim.env.overlap_word_run_reorder_window` |
|
||||
| `narratio_seriatim_env_backchannel_max_duration` | `null` | `seriatim.env.backchannel_max_duration` |
|
||||
| `narratio_seriatim_env_filler_max_duration` | `null` | `seriatim.env.filler_max_duration` |
|
||||
| `narratio_audita_binary` | `null` | `audita.binary` |
|
||||
| `narratio_audita_timeout` | `null` | `audita.timeout` |
|
||||
| `narratio_audita_llm_api_key` | `null` | `audita.llm_api_key` environment-variable name |
|
||||
| `narratio_audita_modules` | `null` | `audita.modules` |
|
||||
| `narratio_audita_base_url` | `null` | `audita.base_url` |
|
||||
| `narratio_audita_model` | `null` | `audita.model` |
|
||||
| `narratio_audita_total_llm_concurrency` | `null` | `audita.total_llm_concurrency` |
|
||||
| `narratio_audita_proposal_llm_concurrency` | `null` | `audita.proposal_llm_concurrency` |
|
||||
| `narratio_audita_validation_model` | `null` | `audita.validation_model` |
|
||||
| `narratio_audita_validation_llm_concurrency` | `null` | `audita.validation_llm_concurrency` |
|
||||
| `narratio_audita_transcript_description` | `null` | `audita.transcript_description` |
|
||||
| `narratio_audita_config_path` | `null` | `audita.config_path` |
|
||||
| `narratio_audita_output_schema` | `null` | `audita.output_schema` |
|
||||
| `narratio_audita_work_dir_retention` | `null` | `audita.work_dir_retention` |
|
||||
| `narratio_audita_report` | `null` | `audita.report` |
|
||||
|
||||
### Transcript Stages and Rendering
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `narratio_normalize_output_path` | `null` | `normalize.output_path` |
|
||||
| `narratio_normalize_output_schema` | `null` | `normalize.output_schema` |
|
||||
| `narratio_normalize_report` | `null` | `normalize.report` |
|
||||
| `narratio_trim_enabled` | `null` | `trim.enabled` |
|
||||
| `narratio_trim_output_path` | `null` | `trim.output_path` |
|
||||
| `narratio_trim_bounds_prompt_id` | `null` | `trim.bounds.prompt_id` |
|
||||
| `narratio_trim_bounds_profile_id` | `null` | `trim.bounds.profile_id` |
|
||||
| `narratio_trim_bounds_transcript_input_name` | `null` | `trim.bounds.transcript_input_name` |
|
||||
| `narratio_trim_bounds_output_path` | `null` | `trim.bounds.output_path` |
|
||||
| `narratio_trim_bounds_timeout` | `null` | `trim.bounds.timeout` |
|
||||
| `narratio_trim_bounds_render_debug` | `null` | `trim.bounds.render_debug` |
|
||||
| `narratio_trim_bounds_render_output_path` | `null` | `trim.bounds.render_output_path` |
|
||||
| `narratio_trim_seriatim_report` | `null` | `trim.seriatim.report` |
|
||||
| `narratio_render_enabled` | `null` | `render.enabled` |
|
||||
| `narratio_render_format` | `null` | `render.format` |
|
||||
| `narratio_render_title` | `null` | `render.title` |
|
||||
| `narratio_render_include_timestamps` | `null` | `render.include_timestamps` |
|
||||
| `narratio_render_include_segment_ids` | `null` | `render.include_segment_ids` |
|
||||
| `narratio_render_include_metadata` | `null` | `render.include_metadata` |
|
||||
|
||||
### Scriptorium, Notarius, and Notification
|
||||
|
||||
| Variable | Default | Native field |
|
||||
| --- | --- | --- |
|
||||
| `narratio_scriptorium_binary` | `null` | `scriptorium.binary` |
|
||||
| `narratio_scriptorium_config_path` | `null` | `scriptorium.config_path` |
|
||||
| `narratio_scriptorium_timeout` | `null` | `scriptorium.timeout` |
|
||||
| `narratio_scriptorium_render_debug` | `null` | `scriptorium.render_debug` |
|
||||
| `narratio_scriptorium_artifacts` | `null` | Complete native `scriptorium.artifacts` map |
|
||||
| `narratio_scriptorium_artifact_families` | `null` | Complete native `scriptorium.artifact_families` map |
|
||||
| `narratio_notarius_enabled` | `null` | `notarius.enabled` |
|
||||
| `narratio_notarius_binary` | `null` | `notarius.binary` |
|
||||
| `narratio_notarius_config_path` | `null` | `notarius.config_path` |
|
||||
| `narratio_notarius_pipeline_id` | `null` | `notarius.pipeline_id` |
|
||||
| `narratio_notarius_timeout` | `null` | `notarius.timeout` |
|
||||
| `narratio_notarius_working_directory` | `null` | `notarius.working_directory` |
|
||||
| `narratio_notarius_references` | `null` | Complete native `notarius.references` map |
|
||||
| `narratio_notarius_outputs` | `null` | Complete native `notarius.outputs` map |
|
||||
| `narratio_notification_mode` | `null` | `notification.mode` |
|
||||
|
||||
## Simplest Viable Implementation
|
||||
|
||||
The production task flow is:
|
||||
|
||||
1. Assert the supported platform and architecture.
|
||||
2. Install Git and Go when dependency management is enabled.
|
||||
3. Create the Narratio system group and account.
|
||||
4. Create the source and configuration parent directories.
|
||||
5. Create the mutable runtime roots and read-only campaign registry root.
|
||||
6. Check out the selected Narratio revision with `ansible.builtin.git`.
|
||||
7. Inspect only whether the installed binary exists, because that result is
|
||||
needed to decide whether the imperative build command must run.
|
||||
8. Build directly to the selected binary path when the checkout changed or
|
||||
the binary is absent.
|
||||
9. Converge binary ownership and mode with `ansible.builtin.file`.
|
||||
10. Render the root pipeline document with one
|
||||
`ansible.builtin.template` task.
|
||||
|
||||
The build command uses `narratio_go_binary` and runs only under the two stated
|
||||
conditions. Ordinary modules own all other state checks. No role-private state,
|
||||
pre-build version interrogation, post-build validation, configuration
|
||||
validation, or redundant filesystem inspection belongs in production tasks.
|
||||
|
||||
The template is necessarily larger than those of the downstream roles because
|
||||
Narratio's native pipeline schema is larger. Its logic remains mechanical:
|
||||
serialize the required URL and role-owned roots, test each optional field with
|
||||
`is not none`, emit a parent section only when needed, and pass native
|
||||
collections through unchanged.
|
||||
|
||||
## Rationale and Alternatives
|
||||
|
||||
Narratio's configuration is broad, but a field-specific interface preserves
|
||||
discoverability, argument validation, stable inventory names, and a clean
|
||||
composition boundary for the suite role. A raw complete-document variable
|
||||
would make the template shorter but would discard those benefits and conflict
|
||||
with the established configuration policy. Open-ended native collections are
|
||||
kept whole because decomposing caller-defined keys would create a second schema
|
||||
and make inventory composition harder.
|
||||
|
||||
Requiring the WhisperX URL is preferable to installing a configuration that
|
||||
Narratio cannot validate or inventing an endpoint that might silently direct
|
||||
work to the wrong service. The baseline integration invocation supplies a
|
||||
non-contacted test URL; production callers supply their actual endpoint.
|
||||
|
||||
The standalone role creates the application account and directory permissions
|
||||
because those are Narratio runtime requirements. It does not select human
|
||||
operators, because membership is deployment-wide policy and belongs in the
|
||||
suite role.
|
||||
|
||||
ConfigKit imports and profiles remain available to advanced callers, but the
|
||||
role manages only the canonical root document. This avoids a parallel raw-file
|
||||
deployment subsystem. A caller that selects imports or profiles is responsible
|
||||
for installing those additional files by another role or play.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Required Role Behavior
|
||||
|
||||
- The role rejects unsupported platforms before modifying application state.
|
||||
- On a supported host, it installs the selected Narratio source release and
|
||||
builds the binary with the upstream release contract.
|
||||
- The system account, source, binary, configuration, runtime roots, and
|
||||
campaign root converge to the paths, ownership, and modes selected above
|
||||
through the responsible Ansible modules.
|
||||
- With only `narratio_whisperx_transcribe_url` supplied, the rendered pipeline
|
||||
contains that URL and the four role-owned roots, omits unselected optional
|
||||
policy, and is accepted by Narratio's native configuration validator.
|
||||
- Each non-null configuration variable renders its corresponding native field.
|
||||
Null fields and empty parent sections are omitted, while intentional falsey
|
||||
values are retained.
|
||||
- Caller-supplied open-ended collections are rendered without structural
|
||||
rewriting, and independently defined values can be composed before
|
||||
assignment.
|
||||
- A changed checkout or missing binary causes the imperative build to run. An
|
||||
immediate repeated application with unchanged inputs reports no changes.
|
||||
- Dependency opt-out accepts a caller-supplied `narratio_go_binary`.
|
||||
- Root-owned operations use task-level privilege escalation; play-level
|
||||
escalation is not required.
|
||||
- Defaults, argument specifications, template behavior, README, and metadata
|
||||
remain aligned with the public interface.
|
||||
- Production tasks contain no role-private state, redundant probes,
|
||||
application self-tests, or speculative guarantees.
|
||||
- No repository other than `ansible-role-narratio` and the workspace control
|
||||
repository is modified.
|
||||
|
||||
### Required Validation
|
||||
|
||||
- Syntax checking and production-profile ansible-lint pass.
|
||||
- A baseline invocation supplies only the required WhisperX URL, exercises the
|
||||
installed application by validating the managed pipeline as the Narratio
|
||||
account, and is followed immediately by a role application reporting no
|
||||
changes. It does not snapshot the role's current default tag or complete
|
||||
default document.
|
||||
- One explicitly selected-version case requests `v2.0.0` and verifies that
|
||||
`narratio version` reports `v2.0.0`. The assertion proves caller-controlled
|
||||
version selection, not that `v2.0.0` remains the role default.
|
||||
- One recovery case removes the binary, disables dependency management,
|
||||
supplies a caller-selected Go executable, confirms that executable is used,
|
||||
and finishes with a clean repeated application.
|
||||
- One representative configuration case verifies selected scalar and nested
|
||||
values, selected omissions, intentional falsey values, and composed
|
||||
open-ended collections. Narratio's native `config validate` accepts the
|
||||
managed pipeline, and an immediate repeated application reports no changes.
|
||||
- Tests do not assert task names or order, individual task results, exact
|
||||
current defaults, complete configuration snapshots, public-variable counts,
|
||||
trusted-module account, directory, file, package, checkout, or template
|
||||
postconditions, or an exhaustive negative platform matrix.
|
||||
|
||||
## Dependencies and Follow-up Work
|
||||
|
||||
The managed host requires access to the Narratio Git repository, Ubuntu Snap
|
||||
infrastructure, and Go module sources. Useful pipeline execution also requires
|
||||
a reachable WhisperX service, the four downstream application binaries and
|
||||
their configuration, campaign and session inputs, prompt content, and any
|
||||
selected object-storage or model credentials. Those remain caller
|
||||
responsibilities for this standalone feature.
|
||||
|
||||
With this feature complete, all five standalone application roles have stable
|
||||
public interfaces. The next unit can design the suite-level pipeline role,
|
||||
including dependency composition, compatible version selection, D&D pipeline
|
||||
policy, campaign and prompt deployment, secrets, and operator group membership.
|
||||
|
||||
The role was implemented in `ansible-role-narratio` commits `3be78d8` and
|
||||
`0e8ad9f`, then finalized after independent review by remediation commit
|
||||
`7feff47`. Its complete integration suite passes.
|
||||
|
||||
## Potential Future Hardening
|
||||
|
||||
- Build into a temporary path before replacing the installed executable.
|
||||
- Verify source signatures or release artifacts.
|
||||
- Detect compiler, build-command, or out-of-band binary changes.
|
||||
- Validate configuration during production convergence.
|
||||
- Manage imported fragments or profile overlays if a concrete standalone-role
|
||||
use case requires them.
|
||||
- Add a scheduler, service, or non-interactive execution environment if later
|
||||
operating requirements select one.
|
||||
- Support Narratio's published binary artifacts as part of a future suite-wide
|
||||
installation-model change.
|
||||
- Add broader platform coverage only when supported-platform behavior expands.
|
||||
@@ -0,0 +1,388 @@
|
||||
# Feature 0006: Pipeline Role Composition Foundation
|
||||
|
||||
Status: done
|
||||
|
||||
## Summary
|
||||
|
||||
Establish `ansible-role-dnd-pipeline` as the independently developed
|
||||
suite-level role that composes the five completed application roles. The
|
||||
feature provides a reproducible dependency manifest, a small suite-owned
|
||||
public interface, compatible application-version selection, and the native
|
||||
cross-application paths Narratio needs to find the installed tools.
|
||||
|
||||
This is the foundation of the complete D&D deployment, not the complete
|
||||
deployment itself. Campaign data, the prompt library, operator access, secret
|
||||
delivery, and opinionated D&D processing policy remain later pipeline-role
|
||||
features.
|
||||
|
||||
## Problem or Opportunity
|
||||
|
||||
The five standalone application roles are implemented, tested, and
|
||||
independently usable. The `ansible-role-dnd-pipeline` repository still contains
|
||||
only its initial README and license, so consumers must currently discover,
|
||||
install, version, and invoke every role separately and manually connect their
|
||||
paths.
|
||||
|
||||
The suite needs one composition boundary before it can add D&D-specific
|
||||
content and policy. Establishing that boundary first keeps later work focused:
|
||||
subsequent features can add suite behavior without reopening how dependencies
|
||||
are named, installed, invoked, or configured.
|
||||
|
||||
## Governing Policies
|
||||
|
||||
- [The Ansible house style](../../ansible.md) governs role composition, public
|
||||
variables, task structure, and the use of downstream role interfaces.
|
||||
- [The testing house style](../../testing.md) governs repository-local
|
||||
validation. Tests exercise the assembled role through native outcomes and
|
||||
clean repeated convergence without reproducing the standalone suites.
|
||||
- [The MVP roadmap](../mvp.md) fixes the supported platform, independently
|
||||
released application roles, Git-hosted role dependencies, source-build
|
||||
model, and suite/collection boundary.
|
||||
- [Decision 0001](../../decisions/0001-minimal-module-driven-ansible.md)
|
||||
requires the smallest direct composition and rejects supplemental state or
|
||||
verification machinery without a selected requirement.
|
||||
|
||||
## Scope
|
||||
|
||||
- Turn `ansible-role-dnd-pipeline` into a conventional standalone Ansible role
|
||||
with defaults, argument specifications, metadata, dependency manifests,
|
||||
documentation, and focused integration coverage.
|
||||
- Install the five standalone roles from their Git repositories under the
|
||||
canonical names `rakestraw.audita`, `rakestraw.narratio`,
|
||||
`rakestraw.notarius`, `rakestraw.seriatim`, and `rakestraw.scriptorium`.
|
||||
- Pin the development dependency manifest to the reviewed commits that
|
||||
completed the five standalone roles. Preserve the existing release policy
|
||||
that replaces development commits with immutable role tags before a
|
||||
released suite or collection is published.
|
||||
- Invoke all five application roles as declared role dependencies in a fixed,
|
||||
readable order.
|
||||
- Select one known-compatible default application release for each component:
|
||||
Audita `v0.9.1`, Narratio `v2.0.0`, Notarius `v0.6.0`, Seriatim `v1.5.0`,
|
||||
and Scriptorium `v0.13.0`.
|
||||
- Expose one suite-level dependency-management choice, Go Snap channel, and Go
|
||||
executable, then pass those values to every application role.
|
||||
- Require a suite-level WhisperX transcription URL and pass it to the Narratio
|
||||
role.
|
||||
- Configure Narratio with the standard binary and configuration paths managed
|
||||
by the composed roles so the orchestrator can find Seriatim, Audita,
|
||||
Notarius, and Scriptorium.
|
||||
- Keep dependency metadata, defaults, argument specifications, README, and
|
||||
focused repository-local tests aligned with the public contract.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Checking out or deploying the `campaigns` repository, including its
|
||||
revision and update policy.
|
||||
- Installing the `narratio-prompts` prompt library or selecting its filesystem
|
||||
layout.
|
||||
- Defining PromptKit profiles, Scriptorium backends, Notarius pipelines,
|
||||
Narratio artifacts, publish outputs, or detailed Audita policy.
|
||||
- Enabling Notarius in the Narratio pipeline before a usable Notarius pipeline
|
||||
definition is supplied.
|
||||
- Selecting human operators or changing their group membership.
|
||||
- Defining, storing, templating, or injecting secret values or environment
|
||||
files.
|
||||
- Running a real recording through the end-to-end D&D workflow.
|
||||
- Bundling the role into `rakestraw.dnd`; collection incorporation remains the
|
||||
next repository boundary after the standalone pipeline role is functional.
|
||||
- Publishing or tagging any role or collection release.
|
||||
- Duplicating every public variable from every application role behind a
|
||||
`dnd_pipeline_` alias.
|
||||
- Reimplementing application installation, configuration templates, account
|
||||
creation, or platform validation in the pipeline role.
|
||||
- Supporting partial component installation, per-component enable switches,
|
||||
removal, or migration from the legacy proof-of-concept role.
|
||||
- Probing downstream state, inspecting task results, or validating a
|
||||
successful downstream operation during production convergence.
|
||||
- Testing every application-role behavior again at the suite level.
|
||||
|
||||
## Target End State
|
||||
|
||||
A consumer first installs the pipeline role's declared Git role dependencies,
|
||||
then applies `rakestraw.dnd_pipeline` with a WhisperX transcription URL. The
|
||||
role invokes the five standalone roles, which install their selected sources,
|
||||
binaries, native configuration, and Narratio runtime state using their own
|
||||
public contracts.
|
||||
|
||||
The pipeline role selects the five compatible application versions as one
|
||||
set. A caller may replace an individual selection through the corresponding
|
||||
suite variable without editing the dependency declaration or addressing the
|
||||
application role directly. Shared dependency management, Go channel, and Go
|
||||
executable choices likewise flow consistently to all five roles.
|
||||
|
||||
Narratio's managed pipeline document names the installed Seriatim, Audita,
|
||||
Notarius, and Scriptorium executable paths and the managed configuration paths
|
||||
for the configured applications. Notarius remains installed but is not enabled
|
||||
as a Narratio stage by this foundation feature. All other optional application
|
||||
settings retain their standalone-role defaults unless a caller supplies the
|
||||
underlying application role variable directly.
|
||||
|
||||
The pipeline role does not own or reproduce downstream templates. It composes
|
||||
the roles through their public variables and lets each role converge its own
|
||||
state. An immediate second pipeline-role application reports no changes.
|
||||
|
||||
This intentionally minimal interface is a foundation, not the pipeline role's
|
||||
final policy surface. Later features will give the pipeline role concrete,
|
||||
opinionated D&D defaults for Audita, Narratio, Notarius, Seriatim, and
|
||||
Scriptorium through the standalone roles' existing field-specific variables.
|
||||
Those values will remain overrideable through ordinary inventory precedence.
|
||||
The suite will add only policy it deliberately owns, rather than copying every
|
||||
upstream application default.
|
||||
|
||||
## Repository Ownership
|
||||
|
||||
- `ansible-role-dnd-pipeline` owns the dependency manifest, suite public
|
||||
interface, dependency declarations, cross-application path wiring,
|
||||
repository documentation, and focused integration suite. This is the only
|
||||
implementation repository changed by the feature.
|
||||
- `ansible-role-{audita,narratio,notarius,seriatim,scriptorium}` are read-only
|
||||
dependency sources and the authorities for their respective public role
|
||||
interfaces. Their reviewed commits define the development dependency set.
|
||||
- `../{audita,narratio,notarius,seriatim,scriptorium}` remain read-only
|
||||
authorities for application behavior.
|
||||
- `rakestraw-ansible` is a read-only style and historical deployment-policy
|
||||
reference. Its monolithic installation and templating are not copied.
|
||||
- `assets/campaigns` and `assets/narratio-prompts` are read-only authorities
|
||||
for the content and layouts that later pipeline-role features will deploy.
|
||||
Their availability in the workspace does not bring content deployment into
|
||||
this composition-foundation feature.
|
||||
- `ansible-collection-dnd` remains unchanged until collection assembly is
|
||||
selected as a later feature.
|
||||
- `ansible-workspace-dnd` owns this roadmap, the eventual staged plan, the
|
||||
settled MVP decisions, and aggregate status.
|
||||
|
||||
## Constraints and Settled Decisions
|
||||
|
||||
- The standalone role is named `dnd_pipeline` in the `rakestraw` Galaxy
|
||||
namespace. It will later be incorporated into the collection under the
|
||||
shorter consumer-facing name `rakestraw.dnd.pipeline`.
|
||||
- Git dependencies are installed with these canonical role names:
|
||||
|
||||
| Role | Repository | Development revision |
|
||||
| --- | --- | --- |
|
||||
| `rakestraw.audita` | `https://gitea.maximumdirect.net/eric/ansible-role-audita.git` | `d2d0b9d00b3b491ce7613ccfc8f686f3d1fa0896` |
|
||||
| `rakestraw.narratio` | `https://gitea.maximumdirect.net/eric/ansible-role-narratio.git` | `7feff4728a5968b6b1dd87e83add9fa1a9066b18` |
|
||||
| `rakestraw.notarius` | `https://gitea.maximumdirect.net/eric/ansible-role-notarius.git` | `cfecf37261f2595d45113235c591ee102d6f181f` |
|
||||
| `rakestraw.seriatim` | `https://gitea.maximumdirect.net/eric/ansible-role-seriatim.git` | `e08c63c0b078658bdfa2d10a2e6e1e4f9372a075` |
|
||||
| `rakestraw.scriptorium` | `https://gitea.maximumdirect.net/eric/ansible-role-scriptorium.git` | `8f47aa802a5e0c9dae9c0f43a1c70b3512b2c8b2` |
|
||||
|
||||
- Commit pins are appropriate for active development because the role
|
||||
repositories do not yet publish release tags. A release must use immutable
|
||||
role tags under the policy already fixed in the MVP roadmap.
|
||||
- `requirements.yml` is the consumer and test bootstrap manifest for the five
|
||||
Git roles. `collections/requirements.yml` declares the pinned
|
||||
`community.general` dependency needed transitively by those roles.
|
||||
- `meta/main.yml` declares the five application roles as dependencies and maps
|
||||
the suite-owned inputs to their existing public variables. It does not use
|
||||
an implementation-specific loader role.
|
||||
- Dependencies execute in this order: Seriatim, Audita, Notarius,
|
||||
Scriptorium, then Narratio. The order makes the downstream tools conceptually
|
||||
available before the orchestrator, but the role does not add probes or
|
||||
runtime validation to enforce the order's postconditions.
|
||||
- Repeated Git, APT, and Snap declarations inside the five roles are accepted.
|
||||
Their modules are idempotent, and consolidating them would weaken standalone
|
||||
role ownership for no selected benefit.
|
||||
- The suite owns only choices that must be coordinated across applications or
|
||||
recorded as a compatible set. It does not alias the complete downstream
|
||||
interfaces. Unmapped application-specific variables retain their ordinary
|
||||
Ansible behavior and may be supplied directly by advanced callers.
|
||||
- The preceding boundary governs this composition foundation only; it does not
|
||||
make the finished pipeline role policy-neutral. Later D&D-configuration
|
||||
features will supply opinionated values directly through the downstream
|
||||
roles' public variables, preserving inventory overrides without introducing
|
||||
parallel templates or complete shadow interfaces.
|
||||
- The feature uses the standard application paths fixed by the MVP and current
|
||||
standalone roles:
|
||||
|
||||
| Purpose | Path |
|
||||
| --- | --- |
|
||||
| Seriatim executable | `/usr/local/bin/seriatim` |
|
||||
| Audita executable | `/usr/local/bin/audita` |
|
||||
| Audita configuration | `/usr/local/etc/audita/config.yml` |
|
||||
| Notarius executable | `/usr/local/bin/notarius` |
|
||||
| Notarius configuration | `/usr/local/etc/notarius/config.yml` |
|
||||
| Scriptorium executable | `/usr/local/bin/scriptorium` |
|
||||
| Scriptorium configuration | `/usr/local/etc/scriptorium/config.yml` |
|
||||
|
||||
- Relocating those coordinated paths is not a requirement for this feature.
|
||||
If a real deployment needs relocation, a later feature may introduce a
|
||||
small set of coherent suite path variables rather than exposing mismatched
|
||||
per-role overrides.
|
||||
- Notarius is installed because it is part of the suite, but
|
||||
`narratio_notarius_enabled` remains null until a later feature supplies a
|
||||
complete D&D Notarius pipeline and explicitly enables it.
|
||||
- Tasks requiring elevated access remain owned by the downstream roles and
|
||||
use their task-level `become: true`; the pipeline role does not require
|
||||
play-level escalation.
|
||||
|
||||
## Fixed Public Interface
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `dnd_pipeline_audita_version` | `v0.9.1` | Audita application revision selected for the compatible set |
|
||||
| `dnd_pipeline_narratio_version` | `v2.0.0` | Narratio application revision selected for the compatible set |
|
||||
| `dnd_pipeline_notarius_version` | `v0.6.0` | Notarius application revision selected for the compatible set |
|
||||
| `dnd_pipeline_seriatim_version` | `v1.5.0` | Seriatim application revision selected for the compatible set |
|
||||
| `dnd_pipeline_scriptorium_version` | `v0.13.0` | Scriptorium application revision selected for the compatible set |
|
||||
| `dnd_pipeline_manage_build_dependencies` | `true` | Whether every application role manages Git and Go |
|
||||
| `dnd_pipeline_go_snap_channel` | `1.26/stable` | Go Snap channel passed to every application role |
|
||||
| `dnd_pipeline_go_binary` | `/snap/bin/go` | Go executable passed to every application role |
|
||||
| `dnd_pipeline_whisperx_transcribe_url` | required | External WhisperX HTTP endpoint passed to Narratio |
|
||||
|
||||
Argument specifications type and document each value. The WhisperX URL is
|
||||
required because neither Narratio nor the suite has a valid universal
|
||||
endpoint. The suite version variables select application source revisions;
|
||||
they are separate from the Git revisions pinning the Ansible role
|
||||
dependencies.
|
||||
|
||||
The role intentionally has no raw map of arbitrary downstream variables and
|
||||
no parallel configuration template. Application-specific choices that are not
|
||||
part of this interface continue to use the standalone roles' documented
|
||||
variables.
|
||||
|
||||
## Simplest Viable Implementation
|
||||
|
||||
The implementation is primarily metadata:
|
||||
|
||||
1. Define the nine suite variables above in defaults and argument
|
||||
specifications, omitting a default for the required WhisperX URL.
|
||||
2. Declare the five named role dependencies in `meta/main.yml`, in the settled
|
||||
order, and pass each dependency its selected version plus the common
|
||||
dependency-management and Go values.
|
||||
3. Pass the WhisperX URL and standard downstream binary/configuration paths to
|
||||
the Narratio dependency.
|
||||
4. Add the Git-role and collection dependency manifests used by consumers and
|
||||
tests.
|
||||
5. Document installation, variables, dependency bootstrap, the boundary with
|
||||
application-specific variables, and an ordinary playbook example.
|
||||
6. Add a focused integration driver that installs dependencies in an isolated
|
||||
roles path, applies the real pipeline role, observes the assembled native
|
||||
application outcome, and requires immediate clean repeated convergence.
|
||||
|
||||
No custom tasks are required merely to prove that role dependencies ran. The
|
||||
pipeline role should not inspect downstream binaries, files, packages,
|
||||
checkouts, or registered task results during production convergence. It should
|
||||
not copy downstream defaults into facts or introduce an abstraction around
|
||||
ordinary role dependency metadata.
|
||||
|
||||
## Rationale and Alternatives
|
||||
|
||||
Using declared role dependencies reflects the actual ownership boundary: each
|
||||
application role remains responsible for its own installation and native
|
||||
configuration, while the pipeline role selects and connects them. Rewriting
|
||||
or including copies of downstream tasks would couple the suite to their
|
||||
implementations and discard the independent-release model already selected.
|
||||
|
||||
A small suite-prefixed interface makes coordinated decisions explicit without
|
||||
creating five complete shadow interfaces. Version selection belongs here
|
||||
because the suite promises a compatible application set. Build dependency and
|
||||
Go choices are common because all five roles use the same source-build model.
|
||||
The WhisperX endpoint belongs here because it is required to construct the
|
||||
Narratio configuration and is deployment-specific.
|
||||
|
||||
The standard downstream paths are suite policy rather than configurable inputs
|
||||
for this first composition feature. Exposing every source, binary, and
|
||||
configuration path would add aliases and cross-variable consistency rules
|
||||
without a demonstrated consumer need. Advanced callers can still use
|
||||
unmapped application variables where they do not conflict with coordinated
|
||||
suite policy.
|
||||
|
||||
Keeping content, operators, secrets, and D&D processing definitions out of
|
||||
this feature avoids combining several unsettled interfaces with dependency
|
||||
composition. Those features can build on a running, natively valid application
|
||||
suite and receive focused roadmaps of their own.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Required Role Behavior
|
||||
|
||||
- A documented bootstrap command installs all five standalone roles from
|
||||
`requirements.yml` under their canonical names and installs the pinned
|
||||
collection dependency.
|
||||
- Applying the pipeline role with a valid
|
||||
`dnd_pipeline_whisperx_transcribe_url` invokes all five standalone roles and
|
||||
reaches their ordinary managed end state on Ubuntu 26.04 `amd64` or `arm64`.
|
||||
- The default suite selections install Audita `v0.9.1`, Narratio `v2.0.0`,
|
||||
Notarius `v0.6.0`, Seriatim `v1.5.0`, and Scriptorium `v0.13.0` as one
|
||||
compatible development set.
|
||||
- A caller can change each application revision through its corresponding
|
||||
`dnd_pipeline_*_version` variable.
|
||||
- The common dependency-management switch, Go channel, and Go executable are
|
||||
passed to all five roles without duplicating their installation tasks.
|
||||
- Narratio receives the required WhisperX URL and the standard executable and
|
||||
configuration paths for all four downstream applications.
|
||||
- Notarius is installed but is not enabled in the Narratio pipeline by this
|
||||
feature.
|
||||
- An immediate repeated role application with unchanged inputs reports no
|
||||
changes.
|
||||
- The role contains no copied application tasks or templates, downstream state
|
||||
probes, role-private state, custom dependency loader, or production
|
||||
self-validation.
|
||||
- Defaults, argument specifications, dependency metadata, manifests, and
|
||||
README remain aligned with the fixed interface.
|
||||
- No implementation repository other than `ansible-role-dnd-pipeline` is
|
||||
modified.
|
||||
|
||||
### Required Validation
|
||||
|
||||
- YAML syntax checking and production-profile ansible-lint pass for the role
|
||||
and its test playbooks.
|
||||
- The integration driver installs the five Git dependencies into a fresh,
|
||||
isolated role path from the same manifest documented for consumers.
|
||||
- One baseline application runs the real pipeline role with a test WhisperX
|
||||
URL, exercises each installed application through a practical native smoke
|
||||
or configuration command, validates Narratio's assembled configuration
|
||||
natively, and is followed immediately by a role application reporting no
|
||||
changes.
|
||||
- One representative application explicitly selects Seriatim `v1.4.0`
|
||||
through `dnd_pipeline_seriatim_version` and observes that selection through
|
||||
Seriatim's native version interface. This proves suite forwarding without
|
||||
asserting that any release remains the default or promising that arbitrary
|
||||
component combinations are compatible.
|
||||
- Tests do not repeat the standalone roles' missing-binary, custom-Go,
|
||||
template-branch, file-metadata, package, Git, or platform matrices.
|
||||
- Tests do not assert dependency task order, exact current default values,
|
||||
role-variable counts, individual task results, or trusted-module
|
||||
postconditions.
|
||||
|
||||
## Dependencies and Follow-up Work
|
||||
|
||||
The five application-role implementations and public interfaces are complete.
|
||||
The managed host must be able to reach their application source repositories,
|
||||
Ubuntu Snap infrastructure, Go module sources, and the caller-supplied
|
||||
WhisperX service.
|
||||
|
||||
After this foundation is implemented and reviewed, later pipeline-role
|
||||
features must settle and implement:
|
||||
|
||||
- prompt-library checkout and Scriptorium integration;
|
||||
- campaign checkout, revision policy, and deployment;
|
||||
- D&D-specific Audita, Notarius, Scriptorium, and Narratio policy;
|
||||
- operator-selection and group-membership behavior;
|
||||
- pipeline-wide secret delivery; and
|
||||
- an end-to-end pipeline validation scenario.
|
||||
|
||||
Collection assembly remains a separate feature after the standalone pipeline
|
||||
role has a stable contract. Before any released dependency manifest or
|
||||
collection is published, the standalone roles must receive immutable release
|
||||
tags and the development commit pins must be replaced by those tags.
|
||||
|
||||
The D&D-policy follow-up must inspect the asset repositories and current
|
||||
application contracts, select concrete suite defaults for all five
|
||||
applications, and document how callers override them. It should reuse the
|
||||
standalone roles' field-specific variables rather than adding pipeline-owned
|
||||
configuration templates or duplicating every downstream setting behind a new
|
||||
alias.
|
||||
|
||||
The feature was implemented in `ansible-role-dnd-pipeline` commits `b515968`
|
||||
and `61869d1`, then finalized by review remediation commit `4ea4358`. The
|
||||
complete integration suite passes with fresh dependency bootstrap, native
|
||||
application validation, explicit suite-level version selection, and clean
|
||||
repeated convergence.
|
||||
|
||||
## Potential Future Hardening
|
||||
|
||||
- Verify signed role or application releases.
|
||||
- Apply an allowlist to dependency or application repository origins.
|
||||
- Add policy for hosts whose installed dependency roles differ from the
|
||||
manifest used by the controller.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
304
docs/roadmap/features/0012-collection-assembly.md
Normal file
304
docs/roadmap/features/0012-collection-assembly.md
Normal 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.
|
||||
285
docs/roadmap/features/0013-first-coordinated-suite-release.md
Normal file
285
docs/roadmap/features/0013-first-coordinated-suite-release.md
Normal 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.
|
||||
@@ -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.
|
||||
424
docs/roadmap/features/0015-dnd-s3-storage-and-publishing.md
Normal file
424
docs/roadmap/features/0015-dnd-s3-storage-and-publishing.md
Normal 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.
|
||||
@@ -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.
|
||||
199
docs/roadmap/features/0017-notarius-testing-overlay.md
Normal file
199
docs/roadmap/features/0017-notarius-testing-overlay.md
Normal 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.
|
||||
163
docs/roadmap/features/0018-scriptorium-v0-15-adoption.md
Normal file
163
docs/roadmap/features/0018-scriptorium-v0-15-adoption.md
Normal 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)
|
||||
199
docs/roadmap/features/0019-audita-v2-adoption.md
Normal file
199
docs/roadmap/features/0019-audita-v2-adoption.md
Normal 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)
|
||||
173
docs/roadmap/features/0020-notarius-v0-8-adoption.md
Normal file
173
docs/roadmap/features/0020-notarius-v0-8-adoption.md
Normal 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)
|
||||
234
docs/roadmap/features/0021-narratio-v3-adoption.md
Normal file
234
docs/roadmap/features/0021-narratio-v3-adoption.md
Normal 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)
|
||||
300
docs/roadmap/features/0022-coordinated-suite-upgrade.md
Normal file
300
docs/roadmap/features/0022-coordinated-suite-upgrade.md
Normal 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)
|
||||
206
docs/roadmap/features/0023-narratio-scriptorium-credentials.md
Normal file
206
docs/roadmap/features/0023-narratio-scriptorium-credentials.md
Normal 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)
|
||||
@@ -20,6 +20,8 @@ for scope, rationale, target end state, and acceptance criteria.
|
||||
zero-based, decimal, nested, or nonsequential stage identifiers.
|
||||
- Before each stage, confirm its preconditions and the working-tree state of
|
||||
its owning repository.
|
||||
- Before each stage, read every document listed in that stage's Required Policy
|
||||
Review. Do not rely on policy recalled from an earlier stage.
|
||||
- Preserve unrelated and pre-existing changes.
|
||||
- Do not make unresolved product or architecture decisions during execution;
|
||||
stop and report the decision required.
|
||||
@@ -52,6 +54,21 @@ for scope, rationale, target end state, and acceptance criteria.
|
||||
|
||||
State the single outcome delivered by this stage.
|
||||
|
||||
### Required Policy Review
|
||||
|
||||
Before beginning this stage, read:
|
||||
|
||||
- `AGENTS.md`
|
||||
- `docs/orientation.md`
|
||||
- `docs/conventions.md`
|
||||
- `<docs/ansible.md, docs/testing.md, and/or docs/planning.md as applicable>`
|
||||
|
||||
Replace the placeholder with every specialized policy applicable to this
|
||||
stage. Include `docs/ansible.md` for Ansible design or implementation,
|
||||
`docs/testing.md` for test work, and `docs/planning.md` for workspace planning
|
||||
or progress management. Do not list an inapplicable policy merely for
|
||||
completeness.
|
||||
|
||||
### Preconditions
|
||||
|
||||
- List facts that must be true before editing begins.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Implementation Plan
|
||||
|
||||
Status: pending
|
||||
No implementation plan is currently active.
|
||||
|
||||
No implementation plan is currently active. Feature 0002 was completed in
|
||||
`ansible-role-audita` through commit `3a8c21f`; its durable scope and rationale
|
||||
remain in
|
||||
[the Feature 0002 roadmap](features/0002-audita-source-installation-and-configuration.md),
|
||||
and its review history remains in [the remediation record](remediation.md).
|
||||
[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.
|
||||
|
||||
Select and approve the next feature roadmap 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.
|
||||
|
||||
@@ -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,10 +106,26 @@ 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
|
||||
end-to-end validation.
|
||||
- Unlike the generic standalone roles, the pipeline role deliberately supplies
|
||||
opinionated, D&D-specific defaults for all five applications. It expresses
|
||||
that policy through the standalone roles' existing field-specific variables,
|
||||
keeps those values overrideable through ordinary inventory precedence, and
|
||||
does not duplicate the application roles' templates or convergence logic.
|
||||
- Pipeline defaults represent policy deliberately selected for the D&D suite;
|
||||
they do not mirror every upstream application default. Settings for which the
|
||||
suite has selected no policy remain under the application or caller's
|
||||
control.
|
||||
- The pipeline role uses the Git-hosted standalone application roles as
|
||||
dependencies. This is an intentional choice for the controlled project
|
||||
environment despite the additional repository and dependency structure and
|
||||
@@ -116,6 +134,22 @@ role will manage the native configuration needed to connect to it.
|
||||
that installs both the collection and its standalone role dependencies; a
|
||||
plain collection installation is not assumed to resolve arbitrary Git role
|
||||
dependencies by itself.
|
||||
- The standalone application roles use the canonical installed names
|
||||
`rakestraw.audita`, `rakestraw.narratio`, `rakestraw.notarius`,
|
||||
`rakestraw.seriatim`, and `rakestraw.scriptorium`.
|
||||
- The pipeline role supplies a root `requirements.yml` bootstrap manifest for
|
||||
those Git-hosted roles and a collection requirements manifest for shared
|
||||
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
|
||||
role variable behind a parallel alias.
|
||||
|
||||
This design keeps repository ownership and change blast radius aligned with
|
||||
the independently released applications while retaining a single opinionated
|
||||
@@ -149,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
|
||||
@@ -165,29 +210,175 @@ 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 roles create a dedicated `narratio` user and `narratio` group as needed.
|
||||
- The `narratio` account owns Narratio's writable runtime directories.
|
||||
- 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 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.
|
||||
- Managed configuration should be owned by `root`, readable by the `narratio`
|
||||
group where needed, and remain under Ansible control rather than being
|
||||
routinely edited by operators on the host.
|
||||
- Shared runtime directories must grant the `narratio` group the 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 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
|
||||
|
||||
- The standalone Narratio role manages the canonical root pipeline document
|
||||
at `/usr/local/etc/narratio/pipeline.yml` through a field-specific public
|
||||
variable interface.
|
||||
- The role requires a caller-supplied WhisperX transcription URL because the
|
||||
field is required by Narratio and has no valid universal deployment value.
|
||||
- Filesystem roots managed by the role have concrete defaults and are rendered
|
||||
so application configuration agrees with managed host state. Other optional
|
||||
application fields default to null, are omitted from the rendered document,
|
||||
and inherit Narratio's built-in defaults.
|
||||
- Native open-ended collections such as publish outputs, Notarius references
|
||||
and outputs, and Scriptorium artifacts and artifact families are exposed as
|
||||
complete fields. Callers may compose their final values in inventory; the
|
||||
role does not add merge or precedence behavior.
|
||||
- The root document may name ConfigKit imports, but the standalone role does
|
||||
not manage imported fragments or profile overlays. A caller that selects
|
||||
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
|
||||
|
||||
@@ -204,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
|
||||
|
||||
@@ -225,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
|
||||
@@ -235,17 +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:
|
||||
|
||||
- Exact application repository URLs, default release tags, build commands,
|
||||
version-injection flags, and validation commands
|
||||
- Standalone role Galaxy names and the dependency-manifest/bootstrap layout
|
||||
- The mechanism used to incorporate the independently developed pipeline role
|
||||
into collection releases
|
||||
- Configuration contracts and filesystem requirements of Notarius, Audita,
|
||||
Seriatim, and Scriptorium
|
||||
- The prompt-library destination and its integration with Scriptorium
|
||||
- Secret injection and storage
|
||||
- Operator-group membership variables and directory permission details
|
||||
- Upgrade, downgrade, and removal behavior
|
||||
- Ansible dependency, validation, and test strategy
|
||||
|
||||
@@ -1,134 +1,144 @@
|
||||
# Feature 0002 Remediation Review
|
||||
# Feature 0022 Remediation Review
|
||||
|
||||
Status: resolved
|
||||
|
||||
The Audita production task flow implements the approved architecture and the
|
||||
complete integration suite passes. The following residual issues should be
|
||||
corrected before Feature 0002 is accepted.
|
||||
Reviewed on 2026-09-29:
|
||||
- Pipeline `8ea8621` and `ea8b09e`.
|
||||
- Collection subtree import through `a78c309` and assembly `3d77eb3`.
|
||||
- Consumer `f694dad`.
|
||||
|
||||
## Finding 1: Correct the Declared Role License
|
||||
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.
|
||||
|
||||
Severity: medium
|
||||
## Finding 1: New assertions freeze unconfigured suite defaults
|
||||
|
||||
`ansible-role-audita/meta/main.yml` declares `BSD-3-Clause`, but the
|
||||
repository's `LICENSE` file is CC0 1.0 Universal. Published role metadata must
|
||||
identify the license actually granted by the repository.
|
||||
Priority: P2
|
||||
Owners: pipeline role and collection tests.
|
||||
|
||||
### Required Remediation
|
||||
Locations:
|
||||
- `ansible-role-dnd-pipeline/tests/integration:172`–173.
|
||||
- `ansible-collection-dnd/tests/integration:104`–105 and 108–109.
|
||||
|
||||
- Change `galaxy_info.license` to the Galaxy-compatible SPDX identifier
|
||||
`CC0-1.0`.
|
||||
- Do not replace or otherwise alter the existing license text.
|
||||
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.
|
||||
|
||||
### Validation
|
||||
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.
|
||||
|
||||
- `meta/main.yml` and `LICENSE` identify the same license.
|
||||
- Production-profile ansible-lint passes.
|
||||
This strengthens acceptance beyond the user's state-based testing policy.
|
||||
The approved plan explicitly asked for supplied-value tests, not default
|
||||
snapshots.
|
||||
|
||||
## Finding 2: Describe All Integration-Test Host Effects
|
||||
## Finding 2: Upgrade guidance confuses configuration with session migration
|
||||
|
||||
Severity: low
|
||||
Priority: P2
|
||||
Owners: pipeline README and consumer deployment guidance.
|
||||
|
||||
`ansible-role-audita/README.md` says that the integration suite mutates only
|
||||
the three Audita paths and its private temporary directory. Default
|
||||
convergence also enables dependency management, so on a fresh supported host
|
||||
the suite may install Git through APT, refresh the APT cache, and install the
|
||||
Go Snap. The statement is therefore incomplete.
|
||||
Locations:
|
||||
- `ansible-role-dnd-pipeline/README.md:166`–168 and 337–338.
|
||||
- `rakestraw-ansible/docs/pipeline-dnd.md:86`–104.
|
||||
|
||||
### Required Remediation
|
||||
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.
|
||||
|
||||
- State that the suite may install or converge Git and the Go Snap in addition
|
||||
to managing the listed Audita paths.
|
||||
- Retain the statement that temporary test-specific files are confined to the
|
||||
private temporary directory.
|
||||
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.
|
||||
|
||||
### Validation
|
||||
This is a missing operator handoff, not a request for additional runtime code.
|
||||
|
||||
- The README accurately describes package/Snap effects and managed filesystem
|
||||
paths.
|
||||
- The description agrees with `tests/integration` and the role defaults.
|
||||
## Finding 3: Documentation makes managed secret files mandatory
|
||||
|
||||
## Finding 3: Complete Binary-Type Verification
|
||||
Priority: P2
|
||||
Owners: pipeline README and consumer deployment guidance.
|
||||
|
||||
Severity: low
|
||||
Locations:
|
||||
- `ansible-role-dnd-pipeline/README.md:160`–163.
|
||||
- `rakestraw-ansible/docs/pipeline-dnd.md:69`–71.
|
||||
|
||||
`tests/verify.yml` checks binary ownership, mode, and executability, but does
|
||||
not assert that `/usr/local/bin/audita` is a regular file. Stage 1 explicitly
|
||||
requires baseline verification of binary type and metadata. The production
|
||||
`file` task establishes this invariant, but the focused verification does not
|
||||
provide the planned evidence for it.
|
||||
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.
|
||||
|
||||
### Required Remediation
|
||||
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.
|
||||
|
||||
- Add an assertion for `audita_binary_metadata.stat.isreg` to the existing
|
||||
binary metadata check.
|
||||
- Do not add another probe or production task.
|
||||
This is an unintended documentation-level strengthening of the requirements.
|
||||
|
||||
### Validation
|
||||
## Review Validation
|
||||
|
||||
- `tests/verify.yml` confirms regular-file type, ownership, mode, and
|
||||
executability from its existing `stat` result.
|
||||
- The integration suite passes.
|
||||
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.
|
||||
|
||||
## Finding 4: Synchronize Implementation Progress Tracking
|
||||
## Remediation Boundaries
|
||||
|
||||
Severity: low
|
||||
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.
|
||||
|
||||
Both implementation stages are annotated complete in
|
||||
`docs/roadmap/implementation.md`, at role commits `47f1852` and `d37f590`, but
|
||||
the plan remains `ready`, its progress notes still say execution is ready to
|
||||
begin, and `docs/status.md` still describes execution as the current activity.
|
||||
The recorded state should show that implementation is complete and remediation
|
||||
review is in progress.
|
||||
## Resolution Evidence
|
||||
|
||||
The two workspace commits that added stage-completion annotations also diverge
|
||||
from the plan's instruction that the out-of-band executor leave workspace
|
||||
planning files unchanged. No implementation code was placed in the wrong
|
||||
repository, so this requires tracking cleanup rather than code movement.
|
||||
All three findings were addressed on 2026-09-29:
|
||||
|
||||
### Required Remediation
|
||||
|
||||
- Set the plan to `in_progress` while findings remain open and replace its
|
||||
stale progress note with both completed stage commits and the current
|
||||
remediation state.
|
||||
- Update workspace status so Feature 0002 is `in_progress`, with implementation
|
||||
complete and remediation pending, and make review/remediation the current
|
||||
focus.
|
||||
- Do not mark Feature 0002 `done` until remediation is implemented and
|
||||
reviewed.
|
||||
|
||||
### Validation
|
||||
|
||||
- The plan's status, stage annotations, and progress notes describe one
|
||||
consistent state.
|
||||
- Workspace status agrees with the implementation and remediation records.
|
||||
- `git diff --check` passes in the workspace repository.
|
||||
|
||||
## Review Validation Evidence
|
||||
|
||||
The review ran the complete `ansible-role-audita/tests/integration` suite on
|
||||
Ubuntu 26.04 with Ansible Core 2.21.3 and ansible-lint 26.8.0. It passed syntax
|
||||
checking, production-profile lint, baseline and repeated convergence,
|
||||
missing-binary rebuilding, dependency opt-out with a caller-supplied Go
|
||||
executable, metadata repair without rebuilding, configuration-only
|
||||
convergence, alternate-checkout rebuilding, default restoration, native
|
||||
configuration validation, and all three platform-rejection cases.
|
||||
|
||||
The final state was default commit
|
||||
`a84941d68168a1ed9ea7423b6477ae8218be73f9`, a `root:root` mode `0755` binary,
|
||||
a `root:root` mode `0644` configuration, and native validation output
|
||||
`config is valid`. `bash -n tests/integration` and `git diff --check` also
|
||||
passed. All nested repository working trees remained clean.
|
||||
|
||||
## Resolution
|
||||
|
||||
All four findings were implemented and validated on 2026-09-08. The role now
|
||||
declares `CC0-1.0`, its README identifies dependency-management effects, and
|
||||
its existing binary `stat` result proves regular-file type. Workspace tracking
|
||||
records the completed and accepted feature. Role remediation was committed as
|
||||
`3a8c21f`.
|
||||
|
||||
Validation passed with the complete `tests/integration` suite,
|
||||
production-profile ansible-lint, `bash -n tests/integration`, and
|
||||
`git diff --check` in both changed repositories. The production task flow was
|
||||
not changed.
|
||||
- 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.
|
||||
|
||||
282
docs/roadmap/test-suite-audit-findings.md
Normal file
282
docs/roadmap/test-suite-audit-findings.md
Normal file
@@ -0,0 +1,282 @@
|
||||
# Test Suite Audit Findings
|
||||
|
||||
Status: resolved
|
||||
|
||||
## Executive Summary
|
||||
|
||||
All three integration suites pass, and each includes the most important common
|
||||
behavioral check: an immediate repeated role application reports no changes.
|
||||
The suites also contain useful coverage of explicitly selected releases,
|
||||
caller-supplied Go executables, missing-binary recovery, configuration
|
||||
rendering, native configuration validation, and Notarius pipeline composition.
|
||||
|
||||
The suites are nevertheless substantially larger and more implementation-bound
|
||||
than the workspace testing policy permits. The recurring problems are:
|
||||
|
||||
- exact assertions about the current default release and its commit;
|
||||
- independent verification of ownership, permissions, checkout state, and
|
||||
template output already managed by trusted Ansible modules;
|
||||
- parsing Ansible output for specific task names and individual
|
||||
`changed`/`skipped` results;
|
||||
- deliberate metadata drift followed by tests of `ansible.builtin.file`;
|
||||
- three-case negative tests of self-evident platform assertions;
|
||||
- repeated clean-run assertions after nearly every scenario; and
|
||||
- duplicated final shell assertions after equivalent Ansible verifiers.
|
||||
|
||||
The appropriate remediation is subtraction and consolidation. The retained
|
||||
suites should exercise stable role-owned behavior through final application
|
||||
outcomes, with one representative case for each meaningful behavior.
|
||||
|
||||
## Baseline
|
||||
|
||||
The audit ran on Ubuntu 26.04 `x86_64` with Ansible Core 2.21.3 and
|
||||
ansible-lint 26.8.0. The role revisions were:
|
||||
|
||||
| Repository | Revision | Integration result |
|
||||
| --- | --- | --- |
|
||||
| `ansible-role-seriatim` | `fb8dc41` | Pass |
|
||||
| `ansible-role-audita` | `847c4c3` | Pass |
|
||||
| `ansible-role-notarius` | `eb4f511` | Pass |
|
||||
|
||||
The following commands all exited successfully:
|
||||
|
||||
```text
|
||||
(cd ansible-role-seriatim && tests/integration)
|
||||
(cd ansible-role-audita && tests/integration)
|
||||
(cd ansible-role-notarius && tests/integration)
|
||||
```
|
||||
|
||||
Each driver installed its pinned collection requirements into a private
|
||||
temporary directory, ran a syntax check and production-profile ansible-lint,
|
||||
executed its behavioral scenarios, and restored its default deployment during
|
||||
cleanup. The runs emitted non-fatal local-tooling warnings about Python
|
||||
interpreter discovery or an already installed duplicate collection; these did
|
||||
not affect the results or any classification below.
|
||||
|
||||
All three role repositories were clean before and after the audit. The control
|
||||
repository began dirty solely because the new testing convention, audit plan,
|
||||
and status update were awaiting commit.
|
||||
|
||||
## Test Inventory
|
||||
|
||||
| Repository | Entry point and supporting files |
|
||||
| --- | --- |
|
||||
| `ansible-role-seriatim` | `tests/integration`, `tests/inventory`, `tests/converge.yml`, `tests/verify.yml`, `tests/unsupported.yml`, `collections/requirements.yml`, and the README validation section |
|
||||
| `ansible-role-audita` | `tests/integration`, `tests/inventory`, `tests/converge.yml`, `tests/verify.yml`, `tests/verify-config.yml`, `tests/unsupported.yml`, `collections/requirements.yml`, and the README validation section |
|
||||
| `ansible-role-notarius` | `tests/integration`, `tests/inventory`, `tests/converge.yml`, `tests/verify.yml`, `tests/verify-config.yml`, `tests/unsupported.yml`, `collections/requirements.yml`, and the README validation section |
|
||||
|
||||
## Cross-Repository Findings
|
||||
|
||||
| Repository | Test or case | Behavior protected | Classification | Recommended action | Rationale |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| All three | Pinned collection installation, syntax check, and ansible-lint | Static validity and reproducible dependencies | Retain | Keep as static validation before behavioral scenarios. | These checks complement rather than duplicate behavioral testing. |
|
||||
| All three | `require_clean_recap` after an immediate repeat | Role-level repeated convergence | Retain | Keep at least one immediate clean repeat per role and repeats specifically required after missing-binary recovery. | Overall `changed=0` is a first-class public role outcome. |
|
||||
| All three | `require_changed_recap` after each mutating setup | Ansible reports some change on the first run | Remove | Stop asserting a nonzero aggregate change count except where a future requirement specifically makes reporting itself significant. | Final application state is the behavior of interest; these checks add little beyond successful convergence and make scenario sequencing brittle. |
|
||||
| All three | Greps for named build, metadata, and configuration tasks | Current task names and individual `changed` or `skipped` results | Remove | Delete all task-output parsing. | These are direct implementation traces and fail under behavior-preserving task refactors. |
|
||||
| All three | Binary/source/configuration ownership and mode assertions | Postconditions declared to `file`, `git`, and `template` | Remove | Delete independent metadata and recursive-ownership verification. | These tests re-prove trusted module behavior rather than role-authored decisions. |
|
||||
| All three | Binary mode mutation followed by convergence | `ansible.builtin.file` repairs mode drift without building | Remove | Delete the scenario. | It is a focused regression test for the built-in file module and current task arrangement. |
|
||||
| All three | Debian, old Ubuntu, and unsupported-architecture matrix | Straightforward platform assertion branches | Remove | Delete `tests/unsupported.yml` and the three-case driver loop. | The declarative assertion is self-evident and does not warrant a negative matrix. |
|
||||
| All three | Restoration of the current default followed by verification and another repeat | Test cleanup and the current default identity | Simplify | Keep one best-effort cleanup convergence, but do not treat it as another test or assert the restored release value. | Cleanup is useful; testing a mutable default and repeating already established idempotence are not. |
|
||||
| All three | Final shell assertions duplicating earlier verifiers | Current commit, metadata, version, or config state | Remove | Delete duplicate end-of-driver assertions. | They add maintenance cost without protecting a distinct behavior. |
|
||||
|
||||
## Seriatim Classification
|
||||
|
||||
| Repository | Test or case | Behavior protected | Classification | Recommended action | Rationale |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Seriatim | Default convergence | The role can be applied with its default interface | Retain | Keep as a smoke test without asserting the exact default tag, commit, or filesystem metadata. | A default invocation is useful even though the present default value is not a stable test expectation. |
|
||||
| Seriatim | Default `v1.5.0` and commit verification | Present default release identity | Remove | Remove the fixed `default_commit` and exact default-version assertions. | This is a change detector; advancing the supported default should not break unrelated tests. |
|
||||
| Seriatim | Baseline immediate repeat | Clean convergence | Retain | Keep the overall `changed=0`, `failed=0` check. | This directly expresses the agreed idempotence requirement. |
|
||||
| Seriatim | Missing binary | The imperative build runs when its output is absent and then converges | Simplify | Delete the binary, apply the role, verify the executable through `--version`, and require the next run to be clean; remove task-name greps. | The binary-existence trigger is role-authored behavior, while the current task name and status are not. |
|
||||
| Seriatim | Dependency opt-out and custom Go executable | The caller-supplied build executable is honored | Simplify | Retain the wrapper invocation evidence, preferably combined with the missing-binary scenario; remove build-task greps and fixed-default assertions. | The selected build executable is a public role choice that cannot be observed reliably from the final binary alone. |
|
||||
| Seriatim | Binary metadata repair | Built-in file convergence | Remove | Delete the complete scenario. | It tests `ansible.builtin.file`, not Seriatim-specific behavior. |
|
||||
| Seriatim | Explicit `v1.4.0` selection | A caller-selected immutable release is installed | Simplify | Retain explicit `seriatim_version: v1.4.0` and verify `seriatim version v1.4.0`; remove the expected commit and task-state assertions. | This is the stable version-selection test described by the testing convention. |
|
||||
| Seriatim | Restore `v1.5.0` default | Cleanup plus present default identity | Simplify | Reduce to cleanup only. | Exact current-default verification duplicates the harmful baseline snapshot. |
|
||||
| Seriatim | Platform failure matrix | Distribution, release, and architecture assertions | Remove | Delete the matrix and `tests/unsupported.yml`. | No plausible role regression justifies separately testing each simple assertion. |
|
||||
| Seriatim | `tests/verify.yml` installation contract | Commit, source metadata, binary metadata, and version | Replace | Replace the broad verifier with a narrow native version check used for an explicitly selected tag. | Only the application outcome is valuable; the remaining assertions repeat trusted modules. |
|
||||
| Seriatim | README validation claims | Description of the current large matrix | Replace | Describe the lean retained behaviors after remediation. | Documentation should not promise deleted implementation-trace and module tests. |
|
||||
|
||||
## Audita Classification
|
||||
|
||||
| Repository | Test or case | Behavior protected | Classification | Recommended action | Rationale |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Audita | Default convergence | The role installs and configures successfully through its default interface | Retain | Keep as a smoke test and validate the resulting configuration with Audita; do not inspect exact default identity or metadata. | Successful native validation is an application outcome and does not freeze the default document. |
|
||||
| Audita | Default commit assertion | Present default checkout identity | Remove | Delete `default_commit` and exact commit verification. | It is both a mutable-default snapshot and a re-test of `ansible.builtin.git`. |
|
||||
| Audita | Source, binary, and configuration metadata | Trusted module postconditions | Remove | Delete the ownership, permission, regular-file, and executable assertions. | The role directly declares these states with trusted modules. |
|
||||
| Audita | Exact minimal default document `{"version": 1}` | Current default rendering | Remove | Do not snapshot the complete default document. Test null omission with explicitly supplied inputs in a representative configuration case instead. | A future intentional concrete default would otherwise cause an unrelated failure. |
|
||||
| Audita | Native validation of the managed configuration | The role produces configuration Audita accepts | Retain | Keep one native validation for default smoke coverage and one for the representative explicit configuration. | This observes application behavior rather than reconstructing its schema. |
|
||||
| Audita | Baseline immediate repeat | Clean convergence | Retain | Keep one role-level clean repeat. | This is required public behavior. |
|
||||
| Audita | Missing binary | Absent build output is recreated and convergence resumes | Simplify | Retain recovery and the following clean repeat; prove usability with the Audita CLI and remove task-output greps. | The imperative build trigger is role logic, but its task name is not. |
|
||||
| Audita | Dependency opt-out and custom Go executable | Caller-selected compiler path is used | Simplify | Retain wrapper invocation evidence and combine it with missing-binary recovery; remove task greps and redundant repeat runs. | This covers a documented public choice with one representative case. |
|
||||
| Audita | Binary metadata repair | Built-in file convergence | Remove | Delete the complete scenario. | It tests Ansible's file module. |
|
||||
| Audita | Representative configuration containing nearly every field | Field-to-YAML mapping, nested sections, and native validity | Simplify | Use a smaller explicit sample spanning representative scalar, list, nested, and duration shapes. Assert only selected paths and specifically selected omissions, then run native validation. | Full-document equality across nearly every field unnecessarily ossifies the template and public interface. |
|
||||
| Audita | Explicit falsey configuration | Empty lists and strings are rendered rather than omitted | Retain | Keep representative falsey values, preferably in the same explicit configuration scenario, and assert only the affected paths. | The null-versus-falsey distinction is role-authored and easy to regress. |
|
||||
| Audita | Configuration task changed while build task skipped | Configuration changes independently of installation | Remove | Delete task-name and status inspection. Confirm the rendered application behavior and successful convergence instead. | Whether named tasks ran is an implementation detail; the ordinary `when` expressions are suitable for review and lint. |
|
||||
| Audita | Restore the minimal default configuration | Cleanup and exact current default | Simplify | Keep restoration only as cleanup and remove fixed-document, fixed-commit, task-state, and extra repeat assertions. | It does not add a distinct stable behavior. |
|
||||
| Audita | Alternate raw commit `46b7356...` | A non-default Git revision can be selected | Replace | Remove the raw-commit case. Add an explicit immutable-release test only when Audita exposes a stable native way to identify the installed application release. | A raw source commit checked with `git rev-parse` tests checkout mechanics, not the installed application's release. Audita currently has no `--version` or `version` command, and tags `v0.9.0` and `v0.9.1` both resolve to `a84941d...`, so neither tag provides a distinguishable installed outcome today. |
|
||||
| Audita | Platform failure matrix | Straightforward platform assertions | Remove | Delete the matrix and `tests/unsupported.yml`. | This is expressly outside the testing house style. |
|
||||
| Audita | Final commit, metadata, and config checks | Duplicate checkout/module/validation assertions | Remove | Delete them. | Equivalent checks already ran, and most should themselves be removed. |
|
||||
| Audita | `tests/verify.yml` broad installation contract | Commit, metadata, default document, and native config validity | Replace | Reduce it to native configuration validation; move explicit field assertions to the focused representative verifier. | Only native validity is a stable application outcome in this verifier. |
|
||||
| Audita | README validation claims | Description of default, metadata, rebuild, and platform tests | Replace | Describe only the retained static checks and behavioral scenarios. | The present prose promises low-value coverage that should be removed. |
|
||||
|
||||
### Audita Version-Coverage Gap
|
||||
|
||||
The current suite does not—and with the present application interface cannot—
|
||||
perform the useful test “select immutable release X and verify that the
|
||||
installed Audita reports X.” Running either `audita --version` or
|
||||
`audita version` fails as an unknown command. The recommended role-test
|
||||
remediation is to remove the misleading raw-commit scenario rather than
|
||||
replace it with another Git-module assertion. A native Audita release-identity
|
||||
command would enable the desired explicit-version test later, but adding that
|
||||
application feature is outside this audit and should be selected separately.
|
||||
|
||||
## Notarius Classification
|
||||
|
||||
| Repository | Test or case | Behavior protected | Classification | Recommended action | Rationale |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Notarius | Default convergence | The default public interface installs and configures successfully | Retain | Keep as a smoke test, run `notarius --version` without fixing its output to the current default, and validate the configuration natively. | This proves the default path remains usable without snapshotting its values. |
|
||||
| Notarius | Default `v0.6.0` and commit verification | Present default release identity | Remove | Delete fixed `default_commit` and exact default-version assertions. | These fail solely when the supported default advances. |
|
||||
| Notarius | Source, binary, and configuration metadata | Trusted module postconditions | Remove | Delete ownership, mode, and regular-file assertions. | They re-test `git`, `file`, and `template`. |
|
||||
| Notarius | Exact minimal default document `{"version": 4}` | Current default rendering | Remove | Do not snapshot the default document. Supply `notarius_config_version` explicitly in the representative case and make any omission assertions about explicitly null inputs. | This preserves schema-bound behavior without turning future defaults into failures. |
|
||||
| Notarius | Native version command and configuration validation | Installed CLI is usable and accepts the managed configuration | Retain | Keep both native interfaces, but assert an exact version only in the explicitly selected release scenario. | These are application-level outcomes. |
|
||||
| Notarius | Baseline immediate repeat | Clean convergence | Retain | Keep one overall clean repeat. | This directly enforces the idempotence requirement. |
|
||||
| Notarius | Missing binary | The required output is rebuilt and then converges | Simplify | Retain artifact removal, native CLI verification, and the following clean repeat; remove task greps. | Missing-output recovery is role logic needed around the imperative build. |
|
||||
| Notarius | Dependency opt-out and custom Go executable | The caller-selected build executable is honored | Simplify | Keep wrapper invocation evidence and combine with missing-binary recovery; remove task greps and redundant repetitions. | This is meaningful configurable behavior with no better final-state discriminator. |
|
||||
| Notarius | Binary metadata repair | Built-in file convergence | Remove | Delete the complete scenario. | It tests trusted module behavior. |
|
||||
| Notarius | Explicit `v0.5.0` selection | A caller-selected immutable tag becomes the installed application | Simplify | Retain `notarius_version: v0.5.0` and exact native output `notarius v0.5.0`; remove expected commit and task-state assertions. | This remains useful after the role's default changes. |
|
||||
| Notarius | Restore `v0.6.0` default | Cleanup and present default identity | Simplify | Reduce to cleanup only. | It is not a distinct stable behavioral test. |
|
||||
| Notarius | Representative configuration | Field mapping, nested sections, pipelines, and validity | Simplify | Use a smaller set of explicit values and assert only those paths plus specifically selected null omissions; retain native validation. | Exact equality for a large complete document is broader and more brittle than the behavior requires. |
|
||||
| Notarius | Separate `profile_dir` case | One simple optional leaf mapping | Remove | Do not maintain a standalone scenario; a future representative case may select one profile source if it adds value. | The direct conditional and serialization are self-evident and already represented by other optional fields. |
|
||||
| Notarius | Separate `profile_file` case | A second simple optional leaf mapping | Remove | Delete the standalone scenario. | It duplicates the shape and risk of the profile-directory case without protecting a distinct likely regression. |
|
||||
| Notarius | Explicit falsey values | Zero, false, empty mapping, and empty string survive rendering | Retain | Fold representative falsey values into the focused configuration scenario and assert only those paths. | Null-versus-falsey behavior is a deliberate role invariant. |
|
||||
| Notarius | Caller-side pipeline composition | Independently defined mappings can be combined and passed through intact | Retain | Keep composition through ordinary `combine`, assert the two resulting pipeline entries, and run native validation; fold it into the representative configuration scenario if clarity permits. | This is an expressly selected public boundary and a plausible integration regression. |
|
||||
| Notarius | Configuration task changed while build task skipped | Configuration changes without rebuilding | Remove | Delete `require_configuration_change_without_build` and all task-trace greps. Verify final configuration, CLI usability, and clean repeat instead. | Task execution is not a stable public interface. |
|
||||
| Notarius | Restore the minimal default configuration | Cleanup plus mutable default assertions | Simplify | Keep cleanup only; remove exact default document, version, commit, task-state, and extra repeat checks. | The behavioral assertions duplicate change detectors elsewhere. |
|
||||
| Notarius | Platform failure matrix | Straightforward platform assertions | Remove | Delete the matrix and `tests/unsupported.yml`. | It provides no proportionate role-specific value. |
|
||||
| Notarius | Final commit, metadata, version, and config checks | Duplicate assertions | Remove | Delete them. | They repeat earlier verification and freeze the current default. |
|
||||
| Notarius | `tests/verify.yml` broad installation contract | Commit, metadata, default document, version, and validity | Replace | Reduce to native CLI smoke and configuration validation, with exact version verification only for an explicit tag. | This retains application outcomes while removing module tests and mutable snapshots. |
|
||||
| Notarius | README validation claims | Description of the current broad suite | Replace | Rewrite after simplification to describe the retained behavior. | Documentation should match the lean suite rather than preserve obsolete coverage promises. |
|
||||
|
||||
## Proposed Lean Target Suites
|
||||
|
||||
### Seriatim
|
||||
|
||||
1. Install pinned collections, syntax-check the convergence play, and lint the
|
||||
role and retained test files.
|
||||
2. Apply the role with defaults as a smoke test and immediately require a clean
|
||||
repeat, without asserting the current default tag or commit.
|
||||
3. Select `v1.4.0` explicitly and verify native output
|
||||
`seriatim version v1.4.0`.
|
||||
4. Delete the binary, supply a wrapper through `seriatim_go_binary` with
|
||||
dependency management disabled, converge, verify that the wrapper was used
|
||||
and the installed CLI works, then require a clean repeat.
|
||||
5. Restore defaults as cleanup without treating the restored value as a test
|
||||
expectation.
|
||||
|
||||
### Audita
|
||||
|
||||
1. Install pinned collections, syntax-check the convergence play, and lint the
|
||||
role and retained test files.
|
||||
2. Apply the role with defaults, validate the managed configuration with
|
||||
Audita, and immediately require a clean repeat. Do not assert the complete
|
||||
default document or current source identity.
|
||||
3. Apply one representative explicit configuration spanning nested, list,
|
||||
scalar, duration, falsey, and explicit-null behavior. Assert only the
|
||||
selected paths and omissions, validate it with Audita, and require a clean
|
||||
repeat.
|
||||
4. Delete the binary, supply a logging wrapper through `audita_go_binary` with
|
||||
dependency management disabled, converge, verify wrapper use and CLI
|
||||
usability, then require a clean repeat.
|
||||
5. Omit version-selection coverage until Audita exposes a native release
|
||||
identity; do not substitute a raw-commit checkout test.
|
||||
6. Restore defaults as cleanup only.
|
||||
|
||||
### Notarius
|
||||
|
||||
1. Install pinned collections, syntax-check the convergence play, and lint the
|
||||
role and retained test files.
|
||||
2. Apply the role with defaults, exercise `notarius --version`, validate the
|
||||
managed configuration, and immediately require a clean repeat without
|
||||
asserting the current default values.
|
||||
3. Select `v0.5.0` explicitly and verify native output `notarius v0.5.0`.
|
||||
4. Delete the binary, supply a logging wrapper through `notarius_go_binary`
|
||||
with dependency management disabled, converge, verify wrapper use and CLI
|
||||
usability, then require a clean repeat.
|
||||
5. Apply one representative explicit configuration that includes selected
|
||||
nested values, explicit falsey and null values, and two caller-composed
|
||||
pipeline mappings. Assert only those behaviors, validate the file with
|
||||
Notarius, and require a clean repeat.
|
||||
6. Restore defaults as cleanup only.
|
||||
|
||||
## Documentation Follow-up
|
||||
|
||||
The README validation sections in all three role repositories should be
|
||||
rewritten with their test harnesses. They currently advertise current-default,
|
||||
metadata, task-arrangement, and platform-guard coverage recommended for
|
||||
removal.
|
||||
|
||||
The durable feature roadmaps may continue to record the selected default tags,
|
||||
paths, ownership, permissions, and platform support as feature requirements.
|
||||
Those requirements need not each have a dedicated integration assertion.
|
||||
Test-specific roadmap language should, however, be corrected as follows:
|
||||
|
||||
- Feature 0001 and Feature 0003 should describe exact native version checks as
|
||||
checks of an explicitly selected immutable tag, not the current default.
|
||||
- Feature 0002 currently says repository-local tests execute Audita to verify
|
||||
its installed version. That is not implementable with Audita's current CLI
|
||||
and should be replaced with the limitation and follow-up described above.
|
||||
- Platform support remains part of each role contract, but the roadmaps should
|
||||
not imply that each straightforward assertion requires a negative matrix.
|
||||
|
||||
## Recommended Remediation Order
|
||||
|
||||
1. Simplify the Seriatim driver and verifier, remove its unsupported-platform
|
||||
playbook, and update its README.
|
||||
2. Simplify Audita's driver and verifiers, consolidate its configuration case,
|
||||
remove its unsupported-platform playbook, and update its README.
|
||||
3. Simplify Notarius's driver and verifiers, consolidate configuration and
|
||||
pipeline coverage, remove its unsupported-platform playbook, and update its
|
||||
README.
|
||||
4. Correct the test-specific language in the three feature roadmaps.
|
||||
5. Run all three complete integration entry points and confirm every role
|
||||
repository remains clean after its cleanup path.
|
||||
|
||||
No shared test abstraction is recommended. The three shell drivers have
|
||||
similar mechanics, but keeping each suite local and readable is worth the
|
||||
small amount of duplication, and a shared helper would create cross-repository
|
||||
coupling for little present benefit.
|
||||
|
||||
## Audit Completion
|
||||
|
||||
Every materially distinct implemented scenario has been classified above. The
|
||||
recommended removals either duplicate retained application-level coverage or
|
||||
exercise behavior owned by trusted Ansible modules or straightforward
|
||||
assertions. The lean targets retain default smoke coverage, immediate clean
|
||||
convergence, imperative missing-output recovery, caller-supplied build tooling,
|
||||
explicit release selection where natively observable, and representative
|
||||
configuration behavior.
|
||||
|
||||
The audit made no changes to production roles or test implementations.
|
||||
|
||||
## Remediation Status
|
||||
|
||||
The recommended remediation was implemented and independently reviewed. No
|
||||
production role behavior changed. The role commits are:
|
||||
|
||||
| Repository | Remediation commit | Final integration result |
|
||||
| --- | --- | --- |
|
||||
| `ansible-role-seriatim` | `e08c63c` | Pass |
|
||||
| `ansible-role-audita` | `d2d0b9d` | Pass |
|
||||
| `ansible-role-notarius` | `cfecf37` | Pass |
|
||||
|
||||
Final sequential validation on the approved Ubuntu 26.04 `x86_64` proxy ran
|
||||
each repository's `tests/integration` entry point successfully. Each cleanup
|
||||
path restored the default deployment, and the role repositories were clean
|
||||
after their remediation commits. The existing classifications remain the
|
||||
authoritative rationale for this implemented suite shape.
|
||||
|
||||
Independent review found no remaining code-quality issues or implementation
|
||||
gaps. The three complete integration entry points passed again sequentially;
|
||||
Bash syntax validation and `git diff --check` passed; native application checks
|
||||
confirmed that cleanup restored usable default deployments; and every
|
||||
repository in the workspace remained clean. No additional remediation record
|
||||
was required.
|
||||
192
docs/roadmap/test-suite-audit.md
Normal file
192
docs/roadmap/test-suite-audit.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Test Suite Audit Plan
|
||||
|
||||
Status: complete
|
||||
|
||||
## Objective
|
||||
|
||||
Audit the implemented integration tests for the three completed standalone
|
||||
roles against the workspace's classical, state-based testing policy. The audit
|
||||
will identify tests that protect stable role-owned behavior, tests that should
|
||||
be simplified or replaced, and tests whose maintenance cost exceeds their
|
||||
value.
|
||||
|
||||
This is a review plan, not authorization to change role code or test suites.
|
||||
Any proposed remediation will be reviewed before a separate implementation
|
||||
plan is prepared.
|
||||
|
||||
## Scope
|
||||
|
||||
The audit covers the test harnesses, playbooks, fixtures, inventories, and
|
||||
test-related documentation in:
|
||||
|
||||
- `ansible-role-seriatim`
|
||||
- `ansible-role-audita`
|
||||
- `ansible-role-notarius`
|
||||
|
||||
Production role tasks, defaults, templates, and metadata may be inspected when
|
||||
needed to determine whether a test protects public role behavior or merely
|
||||
repeats an implementation detail. They are not remediation targets during the
|
||||
audit.
|
||||
|
||||
The audit does not cover the proof-of-concept `rakestraw-ansible` role, the
|
||||
suite-level role, or the collection. Those projects do not form part of the
|
||||
three completed standalone-role test suites.
|
||||
|
||||
## Governing Standard
|
||||
|
||||
Apply the normative testing house style in `docs/testing.md`. In
|
||||
particular, the audit will favor tests that exercise the role through its
|
||||
public variables and inspect meaningful final application behavior. It will
|
||||
disfavor tests that:
|
||||
|
||||
- freeze current defaults or other intentionally changeable values;
|
||||
- assert task names, order, individual task status, or other execution traces;
|
||||
- independently re-prove the documented postconditions of trusted Ansible
|
||||
modules;
|
||||
- exhaustively exercise self-evident assertions or equivalent low-value
|
||||
combinations; or
|
||||
- duplicate another test without protecting a distinct requirement or
|
||||
plausible regression.
|
||||
|
||||
An immediate second convergence with no reported changes remains required for
|
||||
each role. An explicitly selected version may be verified through the
|
||||
application's native interface; the role's current default version may not be
|
||||
treated as a permanent expected value.
|
||||
|
||||
## Classification Rubric
|
||||
|
||||
Classify every behavioral test case, including each materially distinct case
|
||||
embedded in a shared playbook or shell harness, as one of the following:
|
||||
|
||||
- **Retain:** protects stable, role-owned behavior through an externally
|
||||
meaningful outcome.
|
||||
- **Simplify:** protects useful behavior but includes redundant assertions,
|
||||
duplicated setup, or implementation coupling that can be removed.
|
||||
- **Replace:** addresses a valid requirement through an unstable or indirect
|
||||
assertion and should be expressed as a state-based outcome instead.
|
||||
- **Remove:** tests a mutable default, trusted module behavior, an
|
||||
implementation trace, or behavior without a stated requirement or plausible
|
||||
regression.
|
||||
- **Add:** identifies a material role-owned behavior that currently lacks
|
||||
representative coverage.
|
||||
|
||||
Each classification must state the behavior at issue and the reason for the
|
||||
recommended action. File length, test count, and aesthetic preference are not
|
||||
sufficient reasons by themselves.
|
||||
|
||||
## Audit Record
|
||||
|
||||
Write the completed review to
|
||||
`docs/roadmap/test-suite-audit-findings.md`. Record each finding in a table with
|
||||
these fields:
|
||||
|
||||
| Repository | Test or case | Behavior protected | Classification | Recommended action | Rationale |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
|
||||
The report must also provide a proposed lean target suite for each role and
|
||||
identify any shared harness behavior that should be made consistent across the
|
||||
three repositories. Recommendations to remove coverage must state whether the
|
||||
behavior remains covered elsewhere or why it does not warrant coverage.
|
||||
|
||||
## Stage 1: Establish the Baseline
|
||||
|
||||
1. Confirm that the workspace and all three role repositories begin clean.
|
||||
2. Inventory every test entry point, playbook, fixture, inventory, helper, and
|
||||
test-related README statement in scope.
|
||||
3. Run each existing integration entry point without modification:
|
||||
|
||||
```text
|
||||
(cd ansible-role-seriatim && tests/integration)
|
||||
(cd ansible-role-audita && tests/integration)
|
||||
(cd ansible-role-notarius && tests/integration)
|
||||
```
|
||||
|
||||
4. Record success or failure, the scenarios exercised, and any environmental
|
||||
assumptions needed to reproduce the result. A pre-existing failure is audit
|
||||
evidence, not permission to repair it during this stage.
|
||||
|
||||
Completion criterion: the report contains a reproducible baseline and a
|
||||
complete test inventory for all three roles.
|
||||
|
||||
## Stage 2: Audit Seriatim
|
||||
|
||||
1. Map every Seriatim test case to a documented public behavior or classify it
|
||||
as lacking one.
|
||||
2. Review version selection, caller-supplied build tooling, rebuild behavior,
|
||||
metadata handling, platform validation, and repeat convergence using the
|
||||
common rubric.
|
||||
3. Identify assertions that inspect Ansible execution details or separately
|
||||
verify state already owned by trusted modules.
|
||||
4. Propose the smallest representative Seriatim suite that preserves valuable
|
||||
regression protection.
|
||||
|
||||
Completion criterion: every Seriatim case is classified and the report states
|
||||
the proposed retained, revised, removed, and missing coverage.
|
||||
|
||||
## Stage 3: Audit Audita
|
||||
|
||||
1. Map every Audita test case to a documented public behavior or classify it
|
||||
as lacking one.
|
||||
2. Review explicit version selection, native application verification,
|
||||
configuration rendering, omission of null settings, preservation of falsey
|
||||
values, platform validation, and repeat convergence.
|
||||
3. Distinguish tests of the role's configuration decisions from tests that
|
||||
merely repeat `template`, `file`, `git`, or package-module guarantees.
|
||||
4. Propose the smallest representative Audita suite that preserves valuable
|
||||
regression protection.
|
||||
|
||||
Completion criterion: every Audita case is classified and the report states
|
||||
the proposed retained, revised, removed, and missing coverage.
|
||||
|
||||
## Stage 4: Audit Notarius
|
||||
|
||||
1. Map every Notarius test case to a documented public behavior or classify it
|
||||
as lacking one.
|
||||
2. Review explicit version selection, native application verification,
|
||||
optional configuration rendering, falsey values, caller-composed pipeline
|
||||
mappings, platform validation, and repeat convergence.
|
||||
3. Distinguish tests of role-authored mapping and rendering behavior from
|
||||
assertions about trusted module mechanics or the current implementation
|
||||
layout.
|
||||
4. Propose the smallest representative Notarius suite that preserves valuable
|
||||
regression protection.
|
||||
|
||||
Completion criterion: every Notarius case is classified and the report states
|
||||
the proposed retained, revised, removed, and missing coverage.
|
||||
|
||||
## Stage 5: Reconcile the Three Suites
|
||||
|
||||
1. Compare classifications across roles so equivalent patterns receive
|
||||
equivalent treatment, while preserving genuine application differences.
|
||||
2. Identify duplicated harness machinery, inconsistent terminology, and
|
||||
documentation that describes implementation details or mutable defaults as
|
||||
promised test behavior.
|
||||
3. Separate static validation such as syntax checking and linting from
|
||||
behavioral integration coverage.
|
||||
4. Produce a repository-by-repository remediation proposal ordered by value
|
||||
and dependency. Do not propose a shared abstraction unless it removes
|
||||
demonstrated duplication without obscuring the individual role suites.
|
||||
5. Confirm that the proposed target for every role still includes a default or
|
||||
representative convergence, an immediate clean second convergence, and
|
||||
focused coverage of each retained role-owned behavior.
|
||||
|
||||
Completion criterion: the findings report is internally consistent, gives a
|
||||
lean target suite for each repository, and contains enough detail to support a
|
||||
later implementation plan without leaving test-policy decisions to the
|
||||
executor.
|
||||
|
||||
## Audit Completion Criteria
|
||||
|
||||
The audit is complete when:
|
||||
|
||||
- every implemented behavioral case across all three repositories has an
|
||||
explicit classification and rationale;
|
||||
- baseline results and reproduction commands are recorded;
|
||||
- proposed removals do not silently discard coverage of a required public
|
||||
behavior;
|
||||
- proposed additions are limited to material role-owned behavior;
|
||||
- README and harness-documentation corrections are identified alongside test
|
||||
changes;
|
||||
- no production or test implementation has been changed during the audit; and
|
||||
- the findings have been reviewed before any remediation plan is written to
|
||||
`docs/roadmap/implementation.md`.
|
||||
@@ -1,10 +1,18 @@
|
||||
# Workspace Status
|
||||
|
||||
Last updated: 2026-09-08
|
||||
Last updated: 2026-09-29
|
||||
|
||||
Current milestone: MVP standalone application roles
|
||||
Current milestone: Operational D&D pipeline deployment
|
||||
|
||||
Current focus: Select and define the next unit of work.
|
||||
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 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
@@ -13,12 +21,35 @@ Current focus: Select and define the next unit of work.
|
||||
| M0-03 | Tracked MVP roadmap | workspace | done | `docs/roadmap/mvp.md` established |
|
||||
| M0-04 | Aggregate repository status | workspace | done | `scripts/status` created |
|
||||
| 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 | ready | Select the next design topic or application role |
|
||||
| M1-02 | Standalone application roles | role repositories | in_progress | Select the next standalone application role |
|
||||
| M1-03 | Suite-level pipeline role | ansible-role-dnd-pipeline | proposed | Begin after standalone role interfaces stabilize |
|
||||
| M1-04 | Collection assembly | ansible-collection-dnd | proposed | Select and implement the pipeline-role incorporation mechanism |
|
||||
| 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 | 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 | Implementation and remediation completed through `3a8c21f`; full integration suite passed |
|
||||
| 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
|
||||
|
||||
|
||||
47
docs/testing.md
Normal file
47
docs/testing.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Testing House Style
|
||||
|
||||
This policy is normative for creating, changing, reviewing, and auditing tests
|
||||
in this workspace.
|
||||
|
||||
- Use a classical state-based approach, also commonly described as Chicago or
|
||||
Detroit style. Exercise the real role through its public interface and
|
||||
observe the resulting deployed system.
|
||||
- Test behavior owned by the role, not the current arrangement of tasks that
|
||||
implements it. A useful test should normally remain valid after an internal
|
||||
refactor that preserves the same public behavior.
|
||||
- Require an immediate second role application to report no changes. Clean
|
||||
repeated convergence is a first-class role outcome, not a test of any one
|
||||
module.
|
||||
- Distinguish configurable behavior from current defaults. To prove version
|
||||
selection, explicitly request a version and verify that the application
|
||||
reports that version. Do not assert that the same version remains the role's
|
||||
default. For example, a useful test sets `audita_version: v0.9.0` and verifies
|
||||
that the installed Audita reports `v0.9.0`; a harmful test asserts that
|
||||
`v0.9.0` is the role's current default. The former continues to prove version
|
||||
selection after the default advances to `v0.10.0`, while the latter fails
|
||||
merely because of the intended update.
|
||||
- Use a default invocation as a smoke test when useful, but do not snapshot
|
||||
exact default values, selected commits, complete default configuration
|
||||
documents, or counts of default variables. Those assertions are change
|
||||
detectors that turn intentional updates into unrelated test failures.
|
||||
- Do not assert task names, task order, individual `changed` or `skipped`
|
||||
results, or other implementation traces. Inspect the final system and the
|
||||
overall clean-repeat result instead.
|
||||
- Do not test documented behavior of `ansible.builtin`, widely used
|
||||
`community.general`, or other trusted modules. In particular, do not
|
||||
independently verify file existence, ownership, permissions, package state,
|
||||
checkout state, or template deployment merely to repeat module arguments.
|
||||
- Test role-authored decisions only when they express meaningful public
|
||||
behavior. Examples include an explicitly selected application version, a
|
||||
caller-supplied build executable, configuration rendering with representative
|
||||
non-null and falsey values, and composition of caller-supplied mappings.
|
||||
- Verify application outcomes with the application's native interface when
|
||||
practical. Prefer executing the installed application or its configuration
|
||||
validator over reconstructing its rules in Ansible assertions.
|
||||
- Self-evident declarative guards, including straightforward platform
|
||||
assertions, do not require a negative test matrix.
|
||||
- Prefer one representative case for a behavior over exhaustive combinations.
|
||||
Every additional test must protect a requirement or a plausible regression,
|
||||
not merely increase coverage.
|
||||
- Keep syntax checking and linting as static validation. They complement the
|
||||
behavioral suite but do not justify tests that freeze implementation details.
|
||||
@@ -51,6 +51,18 @@ repositories:
|
||||
category: reference
|
||||
purpose: Existing deployment repository and pipeline_dnd proof of concept
|
||||
|
||||
- name: campaigns
|
||||
path: assets/campaigns
|
||||
remote: https://gitea.maximumdirect.net/eric/campaigns.git
|
||||
category: content
|
||||
purpose: D&D campaign registry content deployed by the pipeline role
|
||||
|
||||
- name: narratio-prompts
|
||||
path: assets/narratio-prompts
|
||||
remote: https://gitea.maximumdirect.net/eric/narratio-prompts.git
|
||||
category: content
|
||||
purpose: PromptKit-compatible prompts and schemas deployed for Scriptorium
|
||||
|
||||
- name: narratio
|
||||
path: ../narratio
|
||||
remote: https://gitea.maximumdirect.net/eric/narratio.git
|
||||
@@ -80,9 +92,3 @@ repositories:
|
||||
remote: https://gitea.maximumdirect.net/eric/scriptorium.git
|
||||
category: application
|
||||
purpose: Scriptorium source and authoritative application contracts
|
||||
|
||||
- name: narratio-prompts
|
||||
path: ../narratio-prompts
|
||||
remote: https://gitea.maximumdirect.net/eric/narratio-prompts.git
|
||||
category: content
|
||||
purpose: PromptKit-compatible pipeline prompt library
|
||||
|
||||
Reference in New Issue
Block a user