diff --git a/docs/roadmap/features/0012-collection-assembly.md b/docs/roadmap/features/0012-collection-assembly.md new file mode 100644 index 0000000..0a927be --- /dev/null +++ b/docs/roadmap/features/0012-collection-assembly.md @@ -0,0 +1,304 @@ +# Feature 0012: Assemble the D&D Collection + +Status: ready + +## 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. diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 28ea5ba..d4a92ec 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,8 +1,559 @@ -# Implementation Plan +# Implementation Plan 0012: Assemble the D&D Collection -Status: pending +Status: proposed -Feature 0011 is complete. There is no active implementation plan. +Target executor: GPT-5.6-Terra -Select the next unit of work and agree on its numbered feature roadmap before -replacing this notice with a staged implementation plan. +Feature roadmap: +`docs/roadmap/features/0012-collection-assembly.md` + +Active plan location: `docs/roadmap/implementation.md` + +## Objective + +Build the initial `rakestraw.dnd` collection around the independently +maintained pipeline role. The completed source repository must build and +install as collection version `0.1.0`, expose the imported role as +`rakestraw.dnd.pipeline`, bootstrap the exact reviewed standalone role and +collection dependencies, and prove the packaged boundary through one focused +isolated integration path. The feature roadmap remains authoritative for +scope, rationale, target state, and acceptance criteria. + +## Execution Rules + +- Execute stages in numeric order. +- Number stages with consecutive integers beginning with `Stage 1`. Do not use + 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. +- Start from the feature roadmap's simplest viable implementation. Use native + Galaxy metadata, dependency manifests, collection layout, and Git subtree + behavior rather than adding wrappers, generators, synchronization scripts, + or private state. +- Do not alter pipeline behavior in the standalone repository or beneath the + imported `roles/pipeline` prefix. Any discovered behavioral defect belongs + in the standalone pipeline repository and requires a separately reviewed + change before a new subtree import. +- Do not add integrity, drift, release, publishing, signing, rollback, or + offline-installation guarantees beyond the feature roadmap. +- Keep collection tests focused on the packaging boundary. Do not copy the + standalone pipeline role's full integration matrix. +- Run every stage's validation before committing it. Stage 3 is the sole + mechanical exception: `git subtree add` necessarily creates its provenance + commit as part of the import, so run its validation immediately afterward + and do not proceed if it fails. +- Commit each completed stage when it leaves the repository in a valid state, + using the commit intent specified by that stage. Do not push any repository. +- Do not begin a dependent stage after an earlier stage fails validation. + +## Starting State and Preconditions + +- The workspace planning changes for Feature 0012, including this plan, have + been reviewed and committed before execution begins. +- `ansible-workspace-dnd`, `ansible-role-dnd-pipeline`, and + `ansible-collection-dnd` begin on `main` with clean working trees. +- The standalone pipeline role begins at `de1b191cd2b6895895d3915e7b453596994127cf`. + Stage 1 will create the new reviewed commit that Stage 3 imports. +- The collection begins at `976277b03374`. It contains no role or Galaxy + metadata yet; Feature 0012 planning files belong to the independent parent + workspace repository. +- The pipeline dependency manifests select these exact application-role + commits, which the collection bootstrap manifest must preserve: + + - `rakestraw.seriatim` at + `e08c63c0b078658bdfa2d10a2e6e1e4f9372a075` + - `rakestraw.audita` at + `66ebea9a47ce82bfdbdc5e2855f3dfaaff8e2a16` + - `rakestraw.notarius` at + `14a38e04e35ef524d6a97fa7fb5a04981a0a2161` + - `rakestraw.scriptorium` at + `8b4c86e48e7d8655e479b26dc510bf01683a0c8f` + - `rakestraw.narratio` at + `292d8669e7aad5cfe80b0c469d22b6177e8cf0f1` + +- Collection dependencies remain `ansible.posix` 2.2.0 and + `community.general` 13.3.0. +- The workspace `.venv` provides Ansible Core 2.21.3 and ansible-lint 26.8.0. + Invoke them through `.venv/bin` rather than assuming they are on `PATH`. +- Git includes the `git subtree` command. +- The local Ubuntu 26.04 proxy host supports passwordless noninteractive + `sudo`, as required by the existing role integration suites. +- Network access is available for Galaxy dependencies and the pinned Git role + sources. Local immutable `file://` inputs from `assets/campaigns` and + `assets/narratio-prompts` remain available for integration testing. + +## Repository Scope + +- `ansible-role-dnd-pipeline` may change only its README to document the two + supported consumption forms. It remains authoritative for the role. +- `ansible-collection-dnd` owns Galaxy and runtime metadata, the unified + bootstrap manifest, collection documentation, build exclusions, the + squashed pipeline-role subtree, and focused collection integration tests. +- `ansible-workspace-dnd` may change only planning and status documents during + the final handoff stage. +- The five standalone application roles, both asset repositories, all + application repositories, and `rakestraw-ansible` may be inspected but must + remain unchanged. + +## Stage 1: Document Standalone and Collection Consumption + +### Objective + +Make the authoritative pipeline role's README accurately describe both its +standalone role name and its collection FQCN before taking the collection +snapshot. + +### Required Policy Review + +Before beginning this stage, read: + +- `AGENTS.md` +- `docs/orientation.md` +- `docs/conventions.md` +- `docs/ansible.md` + +### Preconditions + +- `ansible-role-dnd-pipeline` is clean at + `de1b191cd2b6895895d3915e7b453596994127cf`. +- Feature 0012 is committed and records the standalone repository as the + authoritative role source. + +### Owning Repository + +`ansible-role-dnd-pipeline` + +### Required Changes + +1. Revise `README.md` so it no longer describes collection exposure only as a + future possibility. +2. Retain the existing standalone installation and + `rakestraw.dnd_pipeline` invocation instructions. +3. Add a concise collection-use path that names `rakestraw.dnd.pipeline` and + directs collection consumers to the collection repository's unified + bootstrap instructions. Do not duplicate the collection's complete build, + dependency, or subtree maintenance documentation here. +4. Explain that this repository remains authoritative and the collection + carries a reviewed snapshot. Do not claim that a collection release has + been published or tagged. +5. Make no changes to defaults, tasks, templates, metadata, dependency pins, + tests, or role behavior. + +### Validation + +Run from `ansible-role-dnd-pipeline`: + +```text +git diff --check +git diff -- README.md +git status --short +``` + +Expected result: the diff is limited to accurate README wording, contains no +whitespace errors, preserves the standalone instructions, and introduces no +claim of an already published collection release. + +### Completion Criteria + +- Both role names and their distinct consumption contexts are documented. +- No executable or dependency file changed. +- The repository is ready to supply the exact commit for the subtree import. + +### Commit + +Commit intent: `Document standalone and collection pipeline usage` + +## Stage 2: Establish the Collection Foundation + +### Objective + +Create the valid, buildable collection metadata, reproducible dependency +bootstrap, build policy, and operator documentation that will own the imported +role. + +### Required Policy Review + +Before beginning this stage, read: + +- `AGENTS.md` +- `docs/orientation.md` +- `docs/conventions.md` +- `docs/ansible.md` + +### Preconditions + +- Stage 1 is committed and its full pipeline-role commit hash is recorded. +- `ansible-collection-dnd` is clean at its current `main` HEAD. +- The exact application-role and collection dependency pins still match the + values in Starting State and Preconditions. Stop if a pin has changed. + +### Owning Repository + +`ansible-collection-dnd` + +### Required Changes + +1. Add `galaxy.yml` with: + + - namespace `rakestraw`, name `dnd`, and development version `0.1.0`; + - `README.md`, Eric Rakestraw as author, `license: [CC0-1.0]`, a concise D&D + pipeline description, the tags `dnd`, `pipeline`, `transcript`, and + `processing`, repository URL + `https://gitea.maximumdirect.net/eric/ansible-collection-dnd.git`, and + issue URL + `https://gitea.maximumdirect.net/eric/ansible-collection-dnd/issues`; + - exact collection dependencies `ansible.posix: 2.2.0` and + `community.general: 13.3.0`; and + - `build_ignore` entries for the collection's `tests`, root `.gitignore`, + and the imported role's `.gitignore`, `ansible.cfg`, `collections`, + `requirements.yml`, and `tests` paths. + +2. Add `meta/runtime.yml` with only the native runtime requirement + `requires_ansible: ">=2.18.0"` and the normal YAML document marker. +3. Add one root `requirements.yml` using Ansible's unified `roles:` and + `collections:` format. Copy the five Git sources, canonical installed role + names, and exact reviewed commit pins from the pipeline manifests. Include + the same exact two collection versions declared in `galaxy.yml`. +4. Replace the placeholder README with concise documentation covering: + + - purpose, Ubuntu 26.04 support, and the `rakestraw.dnd.pipeline` FQCN; + - the unified `ansible-galaxy install -r requirements.yml` bootstrap; + - collection build and local artifact installation with `--no-deps` after + bootstrap; + - a minimal FQCN play example; + - the distinction between development commit pins and future released role + tags; and + - exact `git subtree add` and `git subtree pull --squash` maintenance + examples using `roles/pipeline` and + `https://gitea.maximumdirect.net/eric/ansible-role-dnd-pipeline.git`. + +5. Make the subtree documentation explicit that role changes originate in + `ansible-role-dnd-pipeline`; collection maintainers import a reviewed commit + and do not edit the snapshot directly. +6. Extend `.gitignore` only as needed to keep locally built `*.tar.gz` + collection artifacts untracked. The documented/tested workflow should + still build into a temporary output directory. +7. Do not create a wrapper role, placeholder role, sync script, lock file, + generated manifest, release automation, or publication configuration. + +### Validation + +Run from `ansible-collection-dnd`: + +```text +build_dir=$(mktemp -d) +trap 'rm -rf -- "$build_dir"' EXIT +../.venv/bin/ansible-galaxy collection build --output-path "$build_dir" +test -f "$build_dir/rakestraw-dnd-0.1.0.tar.gz" +git diff --check +git status --short +``` + +Expected result: Ansible recognizes and builds collection version `0.1.0` +without metadata errors, the expected archive is created outside the +repository, and only the planned collection foundation files have changed. +The artifact does not yet need to contain the pipeline role. + +### Completion Criteria + +- The collection has valid Galaxy and runtime metadata. +- The root requirements file exactly reproduces both existing dependency + manifests in unified form. +- The README gives a complete source-consumer and maintainer workflow without + claiming a published release. +- No role code exists in or has been copied into the collection yet. + +### Commit + +Commit intent: `Establish the D&D collection foundation` + +## Stage 3: Import the Authoritative Pipeline Role + +### Objective + +Create the self-contained `roles/pipeline` collection role through one +provenance-bearing squashed subtree import of the Stage 1 commit. + +### Required Policy Review + +Before beginning this stage, read: + +- `AGENTS.md` +- `docs/orientation.md` +- `docs/conventions.md` +- `docs/ansible.md` + +### Preconditions + +- Stages 1 and 2 are committed and validated. +- Both `ansible-role-dnd-pipeline` and `ansible-collection-dnd` are clean. +- `roles/pipeline` does not exist. +- The exact Stage 1 pipeline commit is available from the sibling repository. + +### Owning Repository + +`ansible-collection-dnd` + +### Required Changes + +1. From the collection repository, capture and inspect the full Stage 1 + pipeline HEAD, then import exactly that commit with: + + ```text + pipeline_commit=$(git -C ../ansible-role-dnd-pipeline rev-parse HEAD) + git subtree add --prefix=roles/pipeline ../ansible-role-dnd-pipeline "$pipeline_commit" --squash + ``` + +2. Retain the standard subtree-generated provenance commit and trailers. Do + not replace the import with a manual copy, submodule, symbolic link, wrapper + role, or custom synchronization record. +3. Do not edit, remove, or reformat any file beneath `roles/pipeline`. Files + excluded from the built artifact remain in source so the imported snapshot + stays faithful to the authoritative repository. +4. Do not change collection-owned metadata merely to hide an unexpected import + result. Stop and report a mismatch between the roadmap, Stage 2 build policy, + and the actual role source. + +### Validation + +Run from `ansible-collection-dnd` immediately after the subtree command: + +```text +diff -ru --exclude=.git ../ansible-role-dnd-pipeline roles/pipeline +../.venv/bin/python -c 'import pathlib, yaml; root = yaml.safe_load(pathlib.Path("requirements.yml").read_text()); role = yaml.safe_load(pathlib.Path("roles/pipeline/requirements.yml").read_text()); collections = yaml.safe_load(pathlib.Path("roles/pipeline/collections/requirements.yml").read_text()); assert root["roles"] == role["roles"]; assert root["collections"] == collections["collections"]' +build_dir=$(mktemp -d) +trap 'rm -rf -- "$build_dir"' EXIT +../.venv/bin/ansible-galaxy collection build --output-path "$build_dir" +tar -tf "$build_dir/rakestraw-dnd-0.1.0.tar.gz" > "$build_dir/files.txt" +grep -Fx 'roles/pipeline/tasks/main.yml' "$build_dir/files.txt" +! grep -Eq '^roles/pipeline/(tests/|ansible.cfg$|collections/|requirements.yml$|\.gitignore$)' "$build_dir/files.txt" +git status --short +git log -2 --format=fuller +``` + +Expected result: source and imported role trees are byte-for-byte equivalent +apart from Git metadata; both dependency sections match their authoritative +pipeline manifests; the archive contains the pipeline task entry point but no +imported development fixtures or nested manifests; and Git records the +standard squashed subtree provenance. The collection working tree is clean +because the subtree command created the import commit. + +### Completion Criteria + +- `roles/pipeline` is an exact snapshot of the Stage 1 pipeline commit. +- The collection artifact is self-contained for the pipeline role. +- Build exclusions affect only the artifact and have not mutated the source + snapshot. +- The dependency bootstrap remains consistent with the imported role. + +### Commit + +Commit intent: retain the standard commit created by `git subtree add`; do not +create a second manual import commit. + +## Stage 4: Validate the Installed Collection Boundary + +### Objective + +Add one lean integration path that proves the built artifact, unified +dependency bootstrap, FQCN resolution, representative native configuration, +and clean repeated convergence. + +### Required Policy Review + +Before beginning this stage, read: + +- `AGENTS.md` +- `docs/orientation.md` +- `docs/conventions.md` +- `docs/ansible.md` +- `docs/testing.md` + +### Preconditions + +- Stage 3 is committed and validated. +- `ansible-collection-dnd` is clean. +- The workspace `.venv`, passwordless `sudo`, and both local asset + repositories are available. +- No developer-global Ansible installation may satisfy the test's role or + collection dependencies. + +### Owning Repository + +`ansible-collection-dnd` + +### Required Changes + +1. Add `tests/inventory` for local connection and `tests/converge.yml` whose + only role invocation is `rakestraw.dnd.pipeline`. +2. Add an executable `tests/integration` shell driver consistent with the + standalone role repositories. It must: + + - use `set -euo pipefail`, locate the repository and workspace `.venv` + without assuming the caller's working directory, and create one private + `mktemp -d` root with cleanup on exit; + - set `ANSIBLE_ROLES_PATH` and `ANSIBLE_COLLECTIONS_PATH` exclusively to + directories beneath that temporary root, without appending the workspace, + sibling repositories, or user-global paths; + - run the unified `ansible-galaxy install -r requirements.yml` with those + environment paths so both dependency sections are exercised; + - build `rakestraw-dnd-0.1.0.tar.gz` into the temporary root and install that + artifact into the isolated collection path with `--no-deps` because the + unified bootstrap has already installed its exact dependencies; + - confirm the archive includes the pipeline task entry point and excludes + the development-only subtree paths selected in `build_ignore`; + - run syntax checking and production-profile ansible-lint against + `tests/converge.yml` only after the isolated dependencies and artifact are + installed; + - derive immutable local asset revisions from `assets/campaigns` and + `assets/narratio-prompts`, pass their `file://` URLs and revisions through + the pipeline's public variables, and use the same syntactically valid + local WhisperX URL and distinctive synthetic credential values as the + standalone suite; + - apply the collection role without contacting WhisperX or any model + provider; + - use the installed applications' native interfaces for one representative + assembled validation: Seriatim reports a version, Audita validates its + configuration, Notarius validates `dnd-session`, Scriptorium resolves a + deployed prompt or profile through its configured roots, and Narratio + validates one deployed campaign; + - immediately apply the identical play and variables a second time, capture + its play recap, and require `changed=0` and `failed=0`; and + - remove only its temporary root during cleanup. + +3. Keep the test at this packaging boundary. Do not add alternate-version, + mapping-composition, invalid-secret, human-operator, ACL, profile-matrix, + or exhaustive artifact tests already owned by the standalone suite. +4. Do not assert current default values, task names or order, individual task + results, module behavior, complete rendered files, or exact manifest + contents. The small archive inclusion/exclusion check is permitted because + packaged content is behavior owned specifically by this feature. +5. Do not place real credentials in the test, logs, inventory, or repository. + Native configuration checks must remain offline. + +### Validation + +Run from the workspace root: + +```text +bash -n ansible-collection-dnd/tests/integration +ansible-collection-dnd/tests/integration +ansible-role-dnd-pipeline/tests/integration +git -C ansible-collection-dnd diff --check +git -C ansible-role-dnd-pipeline status --short +``` + +Expected result: the collection driver builds and installs only the declared +artifact and dependencies into isolated paths, resolves the FQCN, passes every +native application check, and reports a clean immediate repeat. The existing +standalone suite also passes, and the authoritative pipeline repository +remains clean after testing. + +### Completion Criteria + +- The source collection cannot accidentally satisfy its own FQCN or + dependencies through workspace or user-global Ansible paths. +- One representative installed-artifact deployment and every selected native + check pass without external service calls. +- The repeat application reports `changed=0` and `failed=0`. +- The standalone pipeline integration suite remains green. +- The test suite contains no implementation snapshots or duplicated feature + matrix. + +### Commit + +Commit intent: `Test the assembled D&D collection` + +## Stage 5: Record the Implementation Handoff + +### Objective + +Record the completed implementation stages and leave every changed repository +clean for independent review without marking the feature complete. + +### Required Policy Review + +Before beginning this stage, read: + +- `AGENTS.md` +- `docs/orientation.md` +- `docs/conventions.md` +- `docs/planning.md` + +### Preconditions + +- Stages 1 through 4 are committed and all validation has passed. +- `ansible-role-dnd-pipeline` and `ansible-collection-dnd` are clean. +- Full commit hashes for every implementation commit, including the subtree + provenance commit, have been recorded. + +### Owning Repository + +`ansible-workspace-dnd` + +### Required Changes + +1. Change Feature 0012's roadmap status from `ready` to `in_progress`; do not + mark it `done` before independent review. +2. Update `docs/status.md` so M1-04 and F0012 remain `in_progress`, the current + focus is independent implementation review, and the evidence names the + resulting pipeline and collection commit hashes. +3. Replace this document's Progress Notes placeholder with one concise entry + per completed stage, including repository and commit hash. Record any + deviation from the plan; write `none` if there were no deviations. +4. Do not create or modify `docs/roadmap/remediation.md`; independent review + owns remediation findings. + +### Validation + +Run from the workspace root: + +```text +git diff --check +./scripts/status +git status --short +git -C ansible-role-dnd-pipeline status --short +git -C ansible-collection-dnd status --short +``` + +Expected result: only the intended workspace progress documents are pending in +the parent repository; both implementation repositories are clean; status +points reviewers to concrete commits; and the feature remains `in_progress`. + +### Completion Criteria + +- Every stage and deviation is recorded concisely. +- Workspace status requests independent review and does not claim completion. +- No remediation document was preemptively created. +- The workspace change is ready for its own commit. + +### Commit + +Commit intent: `Record the Feature 0012 implementation` + +## Final Validation and Handoff + +- Confirm the successful Stage 4 logs include collection build and isolated + installation, FQCN syntax resolution, every selected native application + check, and the clean repeat recap. +- Run `./scripts/status` and confirm the workspace, + `ansible-role-dnd-pipeline`, and `ansible-collection-dnd` are clean after the + Stage 5 commit. All repositories outside those three must remain unchanged. +- Report the Stage 1 pipeline commit, the Stage 2 collection foundation commit, + the Stage 3 subtree import commit, the Stage 4 collection test commit, and + the Stage 5 workspace handoff commit. +- Summarize any deviations, unresolved findings, and deferred release work. +- Report any implementation complexity beyond native collection metadata, one + unified requirements manifest, the standard subtree import, and the focused + integration driver, together with the acceptance criterion that required it. +- Do not push commits and do not mark Feature 0012 `done`; implementation + results require independent review first. + +## Progress Notes + +No stages have been executed. diff --git a/docs/roadmap/mvp.md b/docs/roadmap/mvp.md index c2c99c4..64802eb 100644 --- a/docs/roadmap/mvp.md +++ b/docs/roadmap/mvp.md @@ -106,6 +106,13 @@ role will manage the native configuration needed to connect to it. - The collection bundles and exposes the independently developed suite-level role as `rakestraw.dnd.pipeline`, providing one opinionated interface for consumers. +- The collection incorporates the pipeline role at `roles/pipeline` as a + squashed Git subtree. The standalone pipeline repository remains + authoritative; maintainers change and validate the role there, then import + a reviewed commit into the collection rather than editing the subtree copy. +- The subtree makes the collection artifact self-contained for its bundled + role without requiring submodule initialization, symbolic links, sibling + repositories, or custom synchronization tooling. - The pipeline role owns compatible application-version selection, cross-application configuration, D&D campaign deployment, prompt-library deployment, operator access, the pipeline-wide secret-delivery policy, and @@ -135,6 +142,10 @@ role will manage the native configuration needed to connect to it. collection dependencies. During active development, the Git roles are pinned to reviewed commits; released manifests replace those commits with immutable role release tags. +- The collection supplies one consumer-facing root `requirements.yml` that + combines those same Git-hosted role pins with the shared collection + dependencies. Its Galaxy metadata separately declares the native collection + dependencies that Ansible can resolve while installing a collection. - The pipeline role composes the five roles through ordinary Ansible role dependency metadata. It exposes suite-prefixed variables for the small set of values the suite must coordinate, and does not duplicate every downstream @@ -179,6 +190,11 @@ application-role releases in one source repository. - 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 @@ -396,9 +412,5 @@ managed host. The prompt-library checkout retains its upstream `prompts/` and The following areas require investigation and decisions before implementation: -- The mechanism used to incorporate the independently developed pipeline role - into collection releases - Optional suite-level operator-selection and group-membership management - Upgrade, downgrade, and removal behavior -- Collection bootstrap and end-to-end validation details beyond the locked - dependency and testing policies above diff --git a/docs/status.md b/docs/status.md index f3da8ce..33aa958 100644 --- a/docs/status.md +++ b/docs/status.md @@ -1,10 +1,10 @@ # Workspace Status -Last updated: 2026-09-16 +Last updated: 2026-09-17 Current milestone: M1-04 collection assembly -Current focus: Select the next unit of work; collection assembly is proposed. +Current focus: Review the Feature 0012 staged implementation plan. | ID | Deliverable | Owner | State | Evidence or next step | | --- | --- | --- | --- | --- | @@ -16,7 +16,7 @@ Current focus: Select the next unit of work; collection assembly is proposed. | 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 | proposed | Select and implement the pipeline-role incorporation mechanism | +| M1-04 | Collection assembly | ansible-collection-dnd | in_progress | Review Feature 0012 and prepare its implementation plan | | F0001 | Install Seriatim from pinned source | ansible-role-seriatim | done | Implementation, integration coverage, and final remediation completed through `fb8dc41` | | F0002 | Install and configure Audita | ansible-role-audita | done | Field-specific configuration completed in `e61f02f` and `847c4c3`; full suite passed | | F0003 | Install and configure Notarius | ansible-role-notarius | done | Implemented and validated through remediation commit `eb4f511` | @@ -28,6 +28,7 @@ Current focus: Select the next unit of work; collection assembly is proposed. | 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 | ready | Review `docs/roadmap/implementation.md`, then begin the implementation sprint | | A0001 | Audit completed standalone-role test suites | workspace and standalone roles | done | Findings recorded in `docs/roadmap/test-suite-audit-findings.md` | | R0001 | Simplify completed standalone-role test suites | workspace and standalone roles | done | Role commits `e08c63c`, `d2d0b9d`, and `cfecf37` passed implementation and independent review |