19 KiB
Implementation Plan 0005: Install and Configure Narratio
Status: ready
Target executor: GPT-5.6-Terra
Feature roadmap: Feature 0005: Narratio Source Installation and Configuration
Active plan location: docs/roadmap/implementation.md
Objective
Implement the independently usable rakestraw.narratio role defined by
Feature 0005. Install Narratio from its pinned source release, build its
executable on the managed host, create its application account and managed
filesystem roots, and render its native root pipeline configuration through
the approved field-specific interface.
The feature roadmap remains authoritative for scope, rationale, target end state, public variables, ownership, modes, and acceptance criteria.
Execution Rules
- Execute Stage 1 and Stage 2 in numeric order.
- Immediately before each stage, read every document in that stage's Required Policy Review, then confirm its preconditions and the owning repository's working-tree state.
- Modify only
ansible-role-narratio. Treat this workspace,../narratio,rakestraw-ansible, and every other repository as read-only during out-of-band implementation. - Preserve unrelated changes. Stop if the role repository is unexpectedly dirty at a stage boundary.
- Start from the feature roadmap's ten-step module-driven task flow. Trust
apt, Snap,group,user,file,git, andtemplateto inspect and converge the state they own. - Inspect only whether the binary exists because that result is independently required to decide whether the imperative build command must run.
- Put checkout change and binary absence directly on the build task. Do not introduce another fact, handler, fingerprint, checksum, manifest, or role-private state.
- Do not execute Narratio from production role tasks. Native version and configuration verification belong only in the integration suite.
- Render configuration with one template task. Use
is not none, omit empty parent sections, preserve falsey non-null values, and serialize values with filters rather than manual YAML quoting. - Treat each roadmap-designated open-ended collection as one caller-supplied native value. Do not define variables for caller-selected keys or implement role-side loading, merging, or precedence.
- Require a WhisperX transcription URL. Do not invent a default endpoint or weaken the upstream requirement.
- Exercise the role through public variables and native application outcomes. Do not assert current default values, task traces, or state already guaranteed by trusted modules.
- Use fully qualified collection names and
argvfor command execution. - Run each stage's validation before committing it. Do not begin Stage 2 if Stage 1 fails validation.
- Commit each completed stage with its specified plain-English message. Do not push.
- Treat the currently absent managed source, binary, pipeline file, account, and default directory roots as disposable integration state. Never delete caller content under those roots during testing. Restore the baseline role deployment through test cleanup.
Starting State and Preconditions
ansible-role-narratiois clean onmainatb97a317f9ec9f15675e81c65af3f4a1ad8176886, trackingorigin/mainwithout divergence.- This plan, the ready Feature 0005 roadmap, and the corresponding MVP/status updates are committed before out-of-band execution begins.
/usr/local/src/narratio,/usr/local/bin/narratio,/usr/local/etc/narratio/pipeline.yml,/var/lib/narratio,/var/spool/narratio,/var/cache/narratio, and/usr/local/share/narratio/campaignsare absent before initial execution and contain no user data that must be preserved.- The local controller and managed-host proxy are Ubuntu 26.04
x86_64, with gathered facts and passwordless task-level privilege escalation available. - Workspace tooling is available in
../.venv/binfrom the role repository: Ansible Core 2.21.3 and ansible-lint 26.8.0. community.general13.3.0 and Go Snap channel1.26/stableare available.- Upstream lightweight tag
v2.0.0resolves toed4623bc415901134c765fe9cf06d59aa7891500and declares Go 1.26.0. - 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 versionreports the embedded release, andnarratio config validate --config <path>validates the root pipeline without loading a session or contacting WhisperX when the configuration contains no credential references or campaign-driven artifact families.- A pipeline requires an absolute HTTP or HTTPS WhisperX transcription URL. All other values needed by a baseline pipeline are supplied by Narratio's native defaults.
Repository Scope
Repository that changes:
ansible-role-narratio: role implementation, public interface, account and filesystem management, configuration template, metadata, dependency declaration, README, and repository-local integration suite.
Repositories that may be inspected but must remain unchanged:
ansible-workspace-dnd: authoritative roadmap, plan, policies, and status.../narratio: authoritative release, build, CLI, configuration, filesystem, and integration contracts.rakestraw-ansible: historical style and deployment reference.- Every other repository in
workspace.yml.
Stage 1: Implement the Complete Minimal Role
Objective
Create a complete standalone role that installs Narratio, creates its account and managed directories, renders the baseline native pipeline, documents its fixed public interface, and demonstrates native validity and clean repeated convergence.
Required Policy Review
Before beginning this stage, read:
AGENTS.mddocs/orientation.mddocs/conventions.mddocs/ansible.mddocs/testing.md
Preconditions
- The starting revisions and upstream contracts above remain unchanged.
ansible-role-narratiohas no uncommitted changes.- The workspace planning commit containing this plan exists.
- The managed paths listed in Starting State remain free of data that must be preserved.
Owning Repository
ansible-role-narratio
Required Changes
- Retain the existing license and add the conventional role structure:
defaults/main.yml,meta/main.yml,meta/argument_specs.yml,tasks/main.yml,templates/pipeline.yml.j2,collections/requirements.yml,ansible.cfg, and focused files undertests/. - Declare role name
narratio, namespacerakestraw, author Eric Rakestraw, licenseCC0-1.0, Ubuntu 26.04 support, Ansible Core 2.18 or newer, an empty dependency list, and the repository's canonical issue tracker. Pincommunity.generalto13.3.0. - Define every variable in the Feature 0005 Fixed Public Interface exactly
once in role defaults, except the required
narratio_whisperx_transcribe_url, which has no invented default. Keep the fourteen installation, account, and managed-filesystem defaults concrete. Give every other optional pipeline field the YAML valuenull. - Mirror the complete public interface in
meta/argument_specs.yml:- mark
narratio_whisperx_transcribe_urlas a required string; - use
pathfor source, binary, Go executable, configuration, and managed root paths; - use
bool,int,float,str,list, anddictaccording to each native field's documented shape; - require every concrete installation, account, and filesystem variable; and
- leave nullable application settings optional. Do not duplicate Narratio's semantic validation rules or deeply restate its schemas for caller-supplied collections.
- mark
- Implement one readable
tasks/main.ymlwith this flow:- assert Ubuntu 26.04 and architecture
x86_64oraarch64; - install Git with
ansible.builtin.apt, includingcache_valid_time: 3600, and install the classic Go Snap fromnarratio_go_snap_channelwhen dependency management is enabled; - create
narratio_groupas a system group andnarratio_useras a system account in that group, withnarratio_workspace_rootas its home,create_home: false, and/usr/sbin/nologinas its shell; - create source, binary, configuration, runtime, and campaign parent/root
directories with the roadmap's ownership and modes using the smallest
clear number of
ansible.builtin.filetasks and item loops; - check out
narratio_versionwithansible.builtin.git,force: true, and register its module result; - inspect only
narratio_binary_pathwithansible.builtin.stat; - build directly to
narratio_binary_pathwhen the checkout changed or the binary is absent; - converge recursive root ownership of the source tree and root ownership
plus mode
0755on the binary withansible.builtin.file; and - render
templates/pipeline.yml.j2tonarratio_config_pathasroot:{{ narratio_group }}mode0640with oneansible.builtin.templatetask.
- assert Ubuntu 26.04 and architecture
- Invoke
narratio_go_binarywithansible.builtin.commandandargvfromnarratio_source_dir. Supplybuild,-trimpath, the exact version linker flags, the configured output path, and package./cmd/narratio. SetCGO_ENABLED=0,GOWORK=off, andGOTOOLCHAIN=local. Mark the executed mutation changed as required for an imperative command. - Put
narratio_checkout.changed or not narratio_binary.stat.existsdirectly on the build task. Register only the Git and binary results needed by that expression. - Use task-level
become: truefor dependency installation, account changes, and tasks that manage privileged state. Do not require play-level privilege escalation. - Make the template always render the required WhisperX URL and the four
role-owned filesystem roots. Conditionally emit all other fields from the
roadmap interface. Use
is not nonefor every optional field, omit parent sections with no selected descendants, preserve non-null falsey values, and serialize strings and collections safely. Do not assemble a configuration dictionary in facts. - Treat ConfigKit imports, publish outputs, Notarius references and outputs, and Scriptorium artifacts and artifact families as complete native caller values. Render them without structural rewriting. Do not load external files or implement merge behavior.
- Replace the placeholder README with concise documentation covering the supported platform, fact and privilege requirements, every public variable, required WhisperX URL, dependency opt-out, build triggers, application account, managed directory ownership, configuration discovery path, null-as-omission behavior, falsey values, caller-side composition of native collections, credential-name boundary, externally managed imports and profiles, suite-role boundary, and actual integration-test effects.
- Add a baseline integration harness with one
tests/integrationentry point. Use strict shell options, repository-relative paths, a private temporary directory, pinned collection installation, syntax checking, production-profile ansible-lint, and a best-effort cleanup trap that reapplies the baseline role inputs and removes only its private temporary directory. - In the baseline scenario, explicitly supply
narratio_whisperx_transcribe_urlwith a syntactically valid local test URL that is never contacted. Converge without play-level escalation, runnarratio config validate --config <managed-path>asnarratio_user, and immediately apply the same role again with aggregatechanged=0andfailed=0. - Do not inspect account records, directory or file metadata, source commits, package state, the template task result, or the complete rendered document in tests. Those are postconditions of the modules that manage them, not additional role-authored behavior.
Validation
From ansible-role-narratio, run:
tests/integration
git diff --check
git status --short
Expected result: syntax and lint pass; baseline convergence succeeds; Narratio
validates the managed pipeline while running as its application account; the
immediate repeat reports changed=0 and failed=0; cleanup leaves a usable
baseline deployment; and only intended Stage 1 files are modified.
Completion Criteria
- The fixed public interface is present in defaults and matching argument specifications, with only the deployment-specific WhisperX URL required.
- Production tasks follow the roadmap flow without additional probes, private state, handlers, or production self-validation.
- Account and directory management implements the fixed ownership and access boundary without selecting human operators.
- The template expresses every native root-pipeline field, omits null values and empty optional parents, and preserves non-null falsey values.
- README, metadata, dependency declaration, task flow, template, and baseline test description agree.
- Baseline native configuration validation and clean repeated convergence pass.
- No repository outside
ansible-role-narratiochanges.
Commit
Commit intent: Install and configure Narratio
Stage 2: Add Focused Behavioral Coverage
Objective
Add representative coverage for caller-selected release identity, missing-binary recovery through caller-owned build tooling, and the complete configuration interface's omission, falsey-value, and composition behavior.
Required Policy Review
Before beginning this stage, read:
AGENTS.mddocs/orientation.mddocs/conventions.mddocs/ansible.mddocs/testing.md
Preconditions
- Stage 1 is committed and
ansible-role-narratiois otherwise clean. - Stage 1's complete integration entry point passes.
- The baseline managed deployment can be restored by applying the role with the test WhisperX URL and no optional application overrides.
Owning Repository
ansible-role-narratio
Required Changes
- Retain the baseline native validation and immediate clean repeat. Extend the existing driver rather than introducing another integration framework or shared cross-role test helper.
- Make the selected-version behavior explicit in one convergence by setting
narratio_version: v2.0.0, then executenarratio versionand requirenarratio v2.0.0. Do not assert or parse the role's default value and do not inspect the Git checkout. - Add one recovery scenario that combines the two related public behaviors:
- create an executable temporary wrapper that records its invocation and
then delegates to
/snap/bin/go; - remove
/usr/local/bin/narratio; - apply the role with
narratio_manage_build_dependencies: falseandnarratio_go_binaryset to that wrapper; - confirm the supplied executable was used;
- exercise the installed Narratio with
versionand native configuration validation; and - immediately repeat with the same inputs and require aggregate
changed=0andfailed=0.
- create an executable temporary wrapper that records its invocation and
then delegates to
- Add one representative configuration scenario using a small valid subset spanning direct and nested fields. Include selected zero, false, empty string, empty list, or empty mapping values where Narratio accepts them, selected null fields that must remain absent, and at least one open-ended collection assembled from independently defined inventory/play variables before assignment.
- Keep the representative pipeline independent of external services,
credentials, imported files, profile overlays, sessions, and campaigns.
Choose collection entries valid under the upstream
v2.0.0contract and avoid artifact families, which require campaign-owned party input during native validation. - Parse the rendered authoring YAML and assert only representative
role-authored mappings: selected fields are present at their correct native
paths, selected null fields and their otherwise-empty parents are absent,
intentional falsey values survive, and the composed collection retains its
caller-supplied entries. Place any decoded-document expression directly in
the assertion task's
vars; do not add a separate assembly or verification fact. - Run
narratio config validate --config <managed-path>asnarratio_userfor native acceptance without a network request. Immediately repeat the representative convergence with identical public inputs and require aggregatechanged=0andfailed=0. - Keep the cleanup trap responsible for restoring the baseline deployment on success or failure when possible. Test mutation is limited to the declared role-managed paths and the driver's private temporary directory; do not delete or replace content below a runtime or campaign root.
- Do not add a second release, task-name grep, change-count requirement for mutating runs, metadata-repair scenario, unsupported-platform matrix, service invocation, full configuration snapshot, or exhaustive case for every variable.
- Update the README validation section so it describes only the implemented static checks, baseline native validation and clean repeat, selected-version assertion, combined recovery case, and representative configuration case.
Validation
From ansible-role-narratio, run:
tests/integration
git diff --check
git status --short
Expected result: static validation and all behavioral paths pass; the selected
release reports v2.0.0; the supplied Go wrapper is observed during
missing-binary recovery; Narratio natively accepts both baseline and
representative managed pipelines as its application account; the specified
repeat runs report changed=0 and failed=0; cleanup restores a usable
baseline deployment; and only intended Stage 2 test and documentation changes
remain.
Completion Criteria
- One explicitly selected-version case proves caller-controlled source release installation through Narratio's native version output.
- One recovery scenario proves both missing-binary rebuilding and use of the caller-selected Go executable, followed by clean convergence.
- One representative configuration proves selected field mapping, null omission, falsey-value preservation, caller-side collection composition, native acceptance, application-account access, and clean convergence.
- No test snapshots mutable defaults, inspects task traces, or rechecks postconditions owned by trusted modules.
- The complete integration entry point passes and its README description is accurate.
- No repository outside
ansible-role-narratiochanges.
Commit
Commit intent: Add focused Narratio integration coverage
Final Validation and Handoff
After Stage 2, from ansible-role-narratio, run:
tests/integration
git log --oneline -2
git status --short --branch
cd ..
./scripts/status
Report both role commit hashes, static and behavioral validation results, clean-repeat evidence, the restored baseline deployment, any deviation or remaining concern, and any complexity beyond the planned task flow with the acceptance criterion that required it.
Do not edit workspace planning files, mark Feature 0005 done, or push during
out-of-band implementation. Completion requires subsequent independent review.
Progress Notes
- No stages completed.