diff --git a/docs/conventions.md b/docs/conventions.md index 266bc2b..119dabf 100644 --- a/docs/conventions.md +++ b/docs/conventions.md @@ -29,14 +29,23 @@ `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. -- Trust the documented contract of each Ansible module, including its - idempotence and change detection. -- Gather state only when the result controls necessary behavior that the - responsible module cannot determine. Fingerprints, checksums, sidecar state, - manual drift detection, and speculative recovery paths require an explicit - acceptance criterion and rationale. Do not precede a declarative module with - a probe or recreate its internal logic unless a concrete requirement cannot - be expressed by the module itself. +- 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. +- 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 diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index e3a3225..b661d22 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,12 +1,311 @@ -# Active Implementation Plan +# Implementation Plan 0001: Simplify Seriatim Source Installation -There is no approved implementation plan at present. +Status: proposed -Feature 0001 has been reopened with a revised, minimal specification at -`docs/roadmap/features/0001-seriatim-source-installation.md`. Prepare its -numbered staged implementation plan here only after that revised roadmap and -the workspace implementation conventions have been reviewed. +Target executor: GPT-5.6-Terra -The prior Audita plan was withdrawn because it propagated the superseded -Seriatim build-state and hardening architecture. Git history preserves that -research, but those execution instructions must not be used. +Feature roadmap: +[Feature 0001: Seriatim Source Installation](features/0001-seriatim-source-installation.md) + +## Objective + +Replace the current overengineered `ansible-role-seriatim` implementation with +the concise, module-driven role defined by Feature 0001. Preserve the useful +role metadata and supported installation outcome while removing persistent +build state, duplicated module logic, speculative recovery, and obsolete test +coverage. + +## Execution Rules + +- Execute Stage 1 and Stage 2 in numeric order. +- Before each stage, confirm its preconditions and the working-tree state of + the owning repository. +- Modify only `ansible-role-seriatim`. Treat this workspace plan, + `rakestraw-ansible`, and `../seriatim` as read-only during implementation. +- Preserve unrelated and pre-existing changes. Stop if the role repository is + not clean at a stage boundary unless its changes are the expected output of + the immediately preceding stage. +- Follow `docs/conventions.md` and the Feature 0001 task flow. Trust the + idempotence and change detection of `apt`, Snap, `file`, and `git`. +- Keep the three rebuild triggers directly on the build task. Do not create an + intermediate rebuild fact, build handlers, or a handler flush. +- Do not reintroduce fingerprints, checksums, sidecar build state, manual Git + cleanup, staged replacement, compiler inspection, or malformed-path + recovery. +- Use fully qualified collection names and `argv` for 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 the plain-English message specified below. + Do not push. +- Treat `/usr/local/src/seriatim` and `/usr/local/bin/seriatim` as disposable + role-managed state during local integration. Do not remove the obsolete + `/usr/local/src/seriatim.ansible-build-state` directory from the host; the + revised role simply stops managing it. + +## Starting State and Preconditions + +- `ansible-role-seriatim` is clean on `main` at commit `6fb1aa2` and is ten + commits ahead of its current `origin/main`. +- The workspace plan and revised feature roadmap are reviewed and committed + before out-of-band execution begins. +- The local controller and managed host are Ubuntu 26.04 `amd64`, with + passwordless privilege escalation available for the approved integration + test. +- Workspace tooling is available in `../.venv/bin` from the role repository: + Ansible Core 2.21.3 and ansible-lint 26.8.0. +- `community.general` 13.3.0 remains pinned in + `collections/requirements.yml`, and the Go Snap channel `1.26/stable` is + available. +- Upstream tag `v1.5.0` resolves to commit + `0fc92f364316c874d366b00cdc884a33e1900b25`. +- The upstream `v1.5.0` contract remains: + - Go module requirement 1.25; + - build package `./cmd/seriatim`; + - `CGO_ENABLED=0`, `GOWORK=off`, `GOTOOLCHAIN=local`, and `-trimpath`; + - linker flags `-s -w -X + gitea.maximumdirect.net/eric/seriatim/internal/buildinfo.Version=`; + - `seriatim --version` output `seriatim version `. +- Upstream tag `v1.4.0` resolves to + `9202ccddb962ab499f0772d3c01efdf2ff703077` and supports the same build and + version contracts for the selected-version integration case. + +## Repository Scope + +- `ansible-role-seriatim` owns every implementation, interface, README, and + repository-local test change in this plan. +- `ansible-workspace-dnd` owns the roadmap, this plan, and aggregate status but + remains unchanged during out-of-band implementation. +- `../seriatim` is the authoritative read-only application contract. +- `rakestraw-ansible` is a read-only style reference. +- Every other repository in `workspace.yml` remains unchanged. + +## Fixed Public Interface + +Retain exactly these public defaults: + +| Variable | Default | Purpose | +| --- | --- | --- | +| `seriatim_version` | `v1.5.0` | Git revision and version injected into the executable | +| `seriatim_repository_url` | `https://gitea.maximumdirect.net/eric/seriatim.git` | Source repository | +| `seriatim_source_dir` | `/usr/local/src/seriatim` | Managed source checkout | +| `seriatim_binary_path` | `/usr/local/bin/seriatim` | Installed executable | +| `seriatim_manage_build_dependencies` | `true` | Whether to install Git and Go | +| `seriatim_go_snap_channel` | `1.26/stable` | Go Snap channel | + +The Go executable, package, build flags, linker symbol, and build environment +are fixed implementation details. The selected version is both the Git ref and +the value injected into the binary. + +## Stage 1: Replace the Role with the Minimal Implementation + +### Objective + +Replace the existing role contract, task graph, documentation, and baseline +test harness with one coherent minimal implementation that installs and +validates the default Seriatim release idempotently. + +### Preconditions + +- The starting-state commits and upstream contracts above are unchanged. +- `ansible-role-seriatim` has no uncommitted changes. +- The default managed paths contain no data that must be preserved. + +### Owning Repository + +`ansible-role-seriatim` + +### Required Changes + +1. Reduce `defaults/main.yml` and `meta/argument_specs.yml` to the six variables + in the Fixed Public Interface. Retain useful role and Galaxy metadata in + `meta/main.yml`. +2. Replace the imported task structure with one readable `tasks/main.yml` and + remove the obsolete task files. Implement approximately this task flow: + 1. assert Ubuntu 26.04 and architecture `x86_64` or `aarch64`; + 2. install Git with `ansible.builtin.apt` when dependency management is + enabled; + 3. install the classic Go Snap from `seriatim_go_snap_channel` with + `community.general.snap` when dependency management is enabled; + 4. create the source and binary parent directories as `root:root` mode + `0755` with one `ansible.builtin.file` loop; + 5. check out `seriatim_version` with `ansible.builtin.git`, using + `seriatim_repository_url`, `seriatim_source_dir`, and `force: true`, and + register the module result; + 6. inspect `seriatim_binary_path` with `ansible.builtin.stat`; + 7. run `seriatim_binary_path --version` only when the binary exists, + registering the result without reporting change or failing the play; + 8. build directly to `seriatim_binary_path` when the Git task changed, the + binary is absent, or the version command failed or returned anything + other than `seriatim version {{ seriatim_version }}`; + 9. converge recursive `root:root` source ownership and binary + `root:root` mode `0755` with one item-driven `ansible.builtin.file` loop; + 10. validate the binary version after a build without reporting change. +3. Put the rebuild expression directly on the build command. Register the + build result for post-build validation and mark the command changed only + when it runs. +4. Invoke `/snap/bin/go build` with `argv`, the fixed package, flags, linker + value, output path, working directory, and environment from the upstream + contract. Do not turn those fixed values into defaults or facts. +5. Remove all code for Git executable discovery, Go executable and compiler + validation, manual Git status/reset/clean, resolved-commit facts, temporary + build directories, build inputs, fingerprints, checksums, sidecar state, + special path-object recovery, and transactional installation. +6. Do not add `handlers/main.yml`; the build, permission, and validation tasks + execute in normal order. +7. Rewrite the README to document the six-variable interface, privilege and + fact requirements, dependency opt-out behavior, authoritative Git checkout, + direct build contract, three rebuild triggers, installed metadata, and + validation commands. Remove every claim or example tied to deleted + variables, state files, staging, compiler invalidation, or failure + preservation. +8. Rewrite `tests/verify.yml` to check only the selected commit, recursive + source ownership, binary type and metadata, and exact version output. +9. Replace `tests/integration` with a focused baseline driver that installs the + pinned collection locally, runs syntax checking and ansible-lint, converges + the default role, runs `tests/verify.yml`, and requires `changed=0` and + `failed=0` on an immediate repeat. Keep `tests/converge.yml`, + `tests/inventory`, and the compatible platform-guard playbook concise. + +### Validation + +From `ansible-role-seriatim`, run: + +```sh +tests/integration +! rg -n \ + 'seriatim_(source_ref|build_version|build_state_dir|go_binary|go_build_flags|go_ldflags|go_package)|fingerprint|checksum' \ + defaults meta tasks tests README.md +git diff --check +git status --short +``` + +Expected result: static validation passes; the default source resolves to +`0fc92f364316c874d366b00cdc884a33e1900b25`; the binary reports +`seriatim version v1.5.0` with `root:root` ownership and mode `0755`; the +immediate repeat reports `changed=0` and `failed=0`; and only intended Stage 1 +changes remain before commit. + +### Completion Criteria + +- The public interface contains exactly six defaults and matching argument + specifications. +- The role's effective task flow matches the roadmap without intermediate + rebuild state or handlers. +- No role code or active documentation references the obsolete sidecar state + or removed variables. +- The baseline integration driver passes and proves default idempotence. +- No repository outside `ansible-role-seriatim` changed. + +### Commit + +Commit message: `Simplify the Seriatim role` + +## Stage 2: Add Focused Behavioral Coverage + +### Objective + +Extend the baseline test harness only far enough to prove the revised feature's +selected rebuild triggers, metadata convergence, platform guard, and final +default state. + +### Preconditions + +- Stage 1 is committed and the role repository is otherwise clean. +- The Stage 1 baseline integration test passes. +- Upstream tags `v1.4.0` and `v1.5.0` remain available. + +### Owning Repository + +`ansible-role-seriatim` + +### Required Changes + +1. Extend `tests/integration` using strict shell options, repository-relative + paths, a private temporary directory, and cleanup that restores the default + `v1.5.0` installation when possible. +2. Retain the baseline convergence, verification, and clean-repeat cases, then + add focused cases for: + - an absent binary causing one rebuild followed by an unchanged run; + - an executable that reports the wrong version causing one rebuild followed + by an unchanged run; + - binary ownership or mode drift being repaired by the ordinary `file` task + without requiring a rebuild, as shown by the captured Ansible task output; + - selecting `v1.4.0`, confirming its commit and version output, and reaching + an unchanged repeat; + - restoring `v1.5.0`, confirming its commit and version output, and reaching + a final unchanged repeat; + - unsupported distribution, Ubuntu release, and architecture inputs failing + before creating application state at isolated temporary paths. +3. Keep recap checks simple and fail the driver on hidden task failures or + unexpected changes during idempotence runs. +4. Keep test mutation limited to the two declared managed paths and paths below + the driver's private temporary directory. +5. Do not add cases for fingerprints, checksums, compiler changes, source-tree + dirt, staged failure preservation, custom-parent recovery, symbolic links, + malformed state, or the obsolete build-state directory. +6. Update the README test section to describe the actual focused suite and its + managed-host effects without advertising superseded behavior. + +### Validation + +From `ansible-role-seriatim`, run: + +```sh +tests/integration +git diff --check +git status --short +``` + +Then confirm the restored default installation: + +```sh +/usr/local/bin/seriatim --version +sudo git -C /usr/local/src/seriatim rev-parse HEAD +sudo stat -c '%U:%G %a' /usr/local/bin/seriatim +``` + +Expected result: the complete focused suite passes; all expected negative +platform cases are recognized; the final repeat reports `changed=0` and +`failed=0`; the restored executable reports `seriatim version v1.5.0`; the +source is at `0fc92f364316c874d366b00cdc884a33e1900b25`; binary metadata is +`root:root 755`; and only intended Stage 2 changes remain before commit. + +### Completion Criteria + +- Every Feature 0001 acceptance criterion has direct test or static evidence. +- The suite tests only the revised operational contract and contains no + superseded hardening matrix. +- The README, defaults, argument specifications, task flow, and tests agree. +- The default local installation is restored and idempotent. +- No repository outside `ansible-role-seriatim` changed. + +### Commit + +Commit message: `Focus Seriatim integration coverage` + +## Final Validation and Handoff + +After Stage 2, run: + +```sh +tests/integration +git log --oneline -2 +git status --short --branch +cd .. +./scripts/status +``` + +The implementation handoff must report: + +- the Stage 1 and Stage 2 commit hashes in order; +- the final integration result and clean-repeat recap; +- the final source commit, version output, ownership, and mode; +- any deviation from this plan or the feature roadmap; +- any remaining implementation concern or potential future hardening item. + +Do not edit workspace roadmap or status files, mark Feature 0001 `done`, or +push during out-of-band execution. Completion requires subsequent review. + +## Progress Notes + +No stages have been executed. diff --git a/docs/status.md b/docs/status.md index f051539..529414e 100644 --- a/docs/status.md +++ b/docs/status.md @@ -1,11 +1,11 @@ # Workspace Status -Last updated: 2026-09-07 +Last updated: 2026-09-08 Current milestone: MVP standalone application roles -Current focus: Review the revised Feature 0001 specification and prepare a -minimal Seriatim simplification plan. +Current focus: Review the staged implementation plan for the Feature 0001 +Seriatim simplification. | ID | Deliverable | Owner | State | Evidence or next step | | --- | --- | --- | --- | --- | @@ -18,7 +18,7 @@ minimal Seriatim simplification plan. | M1-02 | Standalone application roles | role repositories | in_progress | Simplify Seriatim before continuing to other roles | | 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 | -| F0001 | Install Seriatim from pinned source | ansible-role-seriatim | ready | Revised roadmap ready; staged simplification plan is next | +| F0001 | Install Seriatim from pinned source | ansible-role-seriatim | ready | Review `docs/roadmap/implementation.md` | | F0002 | Install and configure Audita | ansible-role-audita | proposed | Replan after the simplified Seriatim role is reviewed | ## Updating This File