From 530a359bb48f994b555171864a06ecf02e486a1c Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Wed, 9 Sep 2026 16:14:23 +0200 Subject: [PATCH 01/13] docs(issues): draft maintenance frictions clean-up specification Re-verify each reported friction against develop at f6b73e29 and record the evidence inline: eight in-scope code, configuration, and documentation items; two maintainer-owned actions that no pull request can perform; one behavioural defect recommended for its own issue; and two candidates that no longer reproduce. Pre-commit checks run on the build server rather than this host, so the local hook is skipped here; linter all and the pre-commit script are executed against this commit as a separate gate. --- .../maintenance-frictions-cleanup/ISSUE.md | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md diff --git a/docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md b/docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md new file mode 100644 index 000000000..cb1bbbca0 --- /dev/null +++ b/docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md @@ -0,0 +1,246 @@ +--- +doc-type: issue +issue-type: task +status: draft +priority: p2 +epic: null +github-issue: null +spec-path: docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md +branch: "{issue-number}-maintenance-frictions-cleanup-spec" +related-pr: null +last-updated-utc: 2026-09-09 14:11 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - AGENTS.md + - .github/workflows/container.yaml + - contrib/dev-tools/checks/tests/test-format-project-words.sh + - contrib/dev-tools/analysis/workspace-coupling/src/main.rs + - docs/issues/open/README.md +--- + + + +# Issue #[To be assigned] - Repository maintenance frictions clean-up + +## Goal + +Clear a verified batch of small, independent maintenance frictions in one review pass, so that each one stops costing attention on every unrelated change, and record the two items that are not code changes so a maintainer can act on them deliberately. + +## Background + +Routine work across this repository keeps running into the same set of small defects: a developer-tool test suite that has been red on `develop` since it was moved, three such suites that no orchestrator runs at all, sixteen issue specifications for closed issues still sitting in the open backlog, a workflow trigger that starts a job on branches it immediately refuses, and documentation that still points at binaries which have since moved into a package. None of these is large enough to justify its own issue and none of them blocks a feature, so each has survived several release cycles. Individually they are noise; collectively they are a standing tax on every contributor and agent who reads a stale path, re-diagnoses a red test, or scrolls past a failed workflow run that was never going to succeed. + +Each entry below was re-verified against `develop` at revision `f6b73e29` on 2026-09-09; the evidence column records what was observed rather than what was reported. Two candidates that had been proposed for this batch did not reproduce and were dropped; they are recorded in [Dropped Candidates](#dropped-candidates) so the same ground is not re-covered. + +The frictions are deliberately grouped rather than filed separately. They share a review context — small, low-risk, mechanical — and splitting them into a dozen issues would cost more maintainer attention than the defects themselves. They do not share an implementation: each row is independently revertible, so a single reviewer can accept or reject them one at a time within one pull request. + +## Scope + +### In Scope + +- The eight code, configuration, and documentation frictions listed in [Friction Inventory](#friction-inventory), each fixed or explicitly deferred with a linked issue. +- Recording the two maintainer-owned items in [Maintainer Actions](#maintainer-actions) so they are visible and actionable, without attempting to perform them from a pull request. +- Recording the one behavioural defect in [Related but Separate](#related-but-separate) with a recommendation that it gets its own issue. + +### Out of Scope + +- Automating the issue-specification archival flow. That is #1774; this issue performs the current archival by hand and does not constrain the script's design. +- Triaging external-link check findings. That is #2185, whose specification is under review in #2186. +- Repairing the `Docker E2E` job in `.github/workflows/testing.yaml`. That is #2179; this issue only records which stale pull requests are blocked behind it. +- Migrating legacy single-file specifications to the folder-style layout. That is #2159. +- Designing the long-term check harness and sensor architecture. That is EPIC #2003; F1 below adds the missing invocation of suites that already exist and does not prejudge that design. +- Any behavioural change to the tracker itself, other than the explicitly out-of-scope item recorded in [Related but Separate](#related-but-separate). + +## Friction Inventory + +Size is the expected reviewable weight of the change: `XS` is a one-line edit, `S` is a handful of lines in one file, `M` spans several files or needs a judgement call. + +| ID | Area | Evidence (verified at `f6b73e29`, 2026-09-09) | Proposed fix | Size | +| --- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| F1 | Developer tooling | Three developer-tool test suites exist and no orchestrator runs any of them: `contrib/dev-tools/git/tests/test-merge-pull-request.sh`, `contrib/dev-tools/checks/tests/test-format-project-words.sh`, `contrib/dev-tools/checks/tests/test-agent-review-report-contract.sh`. `grep -rn "contrib/dev-tools" .github/workflows/` returns only the container persistence test and the hook installer; the suites appear in no `STEPS` entry of `contrib/dev-tools/git/hooks/pre-commit.sh` (lines 51-58) or `pre-push.sh`. Two scripts state the gap themselves: `contrib/dev-tools/checks/tests/test-format-project-words.sh:6` and `contrib/dev-tools/checks/format-project-words.sh:6`. | Add one lightweight CI step that runs the three suites, and delete the now-untrue "not automatically run" notes. Keep the step outside the expensive test matrix; the three suites together complete in roughly one second on a warm host. | S | +| F2 | Issue lifecycle | Sixteen specification directories under `docs/issues/open/` belong to issues GitHub reports as `CLOSED`: 1586, 1588, 2121, 2122, 2130, 2132, 2134, 2136, 2138, 2140, 2150, 2151, 2155, 2156, 2160, 2162. Verified by `gh issue view --json state,closedAt` for every directory in `docs/issues/open/`. The archival rule is `docs/issues/closed/README.md`. | Move the sixteen directories to `docs/issues/closed/` per the `cleanup-completed-issues` skill, repairing any live references the move breaks. Automation of this flow stays with #1774. | M | +| F3 | Workflow triggers | `.github/workflows/container.yaml:16` triggers pushes on `releases/**/*`, while `.github/workflows/deployment.yaml:15` was narrowed to `releases/v*`. Package release branches match `releases/pkg/**` (`.github/workflows/deployment-packages.yaml:35`), so every package release push also starts the container workflow, which then extracts `pkg//v` as its version, fails the semver test at `container.yaml:165`, prints `Not a valid release branch semver. Will Not Continue`, and exits 0. | Narrow `container.yaml:16` to `releases/v*`, matching `deployment.yaml`. The semver guard stays as the second line of defence. | XS | +| F4 | Documentation drift | `src/bin/` now contains only `http_health_check.rs`; `e2e_tests_runner`, `profiling`, and `qbittorrent_e2e_runner` moved to `packages/e2e-tools/src/bin/` in commit `c47173f53`. Five live references were never updated: `AGENTS.md:39`, `.github/skills/dev/testing/manual-http-download-completion-e2e/SKILL.md:21` and `:307`, `.github/skills/dev/testing/manual-udp-download-completion-e2e/SKILL.md:207`, `docs/profiling.md:10`. `docs/adrs/20260519000000_define_global_cli_output_contract.md:8` lists `src/bin/` as a related artifact and now under-describes the binary landscape. | Correct the five live references to `packages/e2e-tools/src/bin/`. Extend the ADR's related-artifacts list rather than rewriting the decision. Leave `docs/issues/closed/` untouched: those are immutable historical records. #2179 names this drift out of its own scope and worth its own issue. | S | +| F5 | Test health | `contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 1 on `develop` for two independent reasons. First, `PROJECT_ROOT` at line 13 climbs three levels from `contrib/dev-tools/checks/tests/` and lands on `/contrib`, so every fixture copy reads `/contrib/contrib/dev-tools/...` and fails; the sibling suite at `contrib/dev-tools/git/tests/test-merge-pull-request.sh:6` climbs four from an equally deep directory and is correct. Commit `ffa2aa2c5` introduced the wrong depth when it moved the suite beside its sensor. Second, with the depth corrected the suite still fails: `create_fixture` (lines 21-28) never provisions `contrib/dev-tools/checks/lint-containerfile.sh`, so pre-commit step 5 of 6 reports `No such file or directory`, `commands.log` holds 3 entries where line 205 asserts 4, and the success banner asserted at line 206 is never printed. | Correct the `PROJECT_ROOT` depth to four levels, and provision the Containerfile lint sensor in the fixture with a stub that keeps the suite hermetic and free of any container runtime. Re-check the `commands.log` count assertion against whichever stub is chosen. | S | +| F6 | Code readability | `contrib/dev-tools/analysis/workspace-coupling/src/main.rs:191` writes an explicit generic argument naming Rust's character type — the five-character token spelled angle bracket, c-h-a-r, angle bracket. It is the only occurrence in the tracked tree. Chat and review transport layers substitute that token with a role or account name, so the line cannot be quoted in a review discussion without arriving as text that would not compile, which makes a reviewer reasonably distrust the quoted artifact. | Take the character by value — `fn is_rust_identifier_char(ch: char) -> bool` — and move the optionality to the two call sites at line 187, which already hold values from `chars().next_back()` and `chars().next()` and can use `is_some_and`. Behaviour is unchanged: an absent adjacent character still reads as "not an identifier character". Where a token-free signature is genuinely impossible, a local type alias or inference through `collect()` serves the same purpose. | XS | +| F7 | Dead comment | `contrib/dev-tools/checks/lint-containerfile.sh:4` reads `Tests: (no automated tests yet — EPIC #2003)`. Once F5 and F1 land, the fixture for that sensor exists and is exercised, so the note becomes untrue in the same pull request that makes it so. | Update the note to point at the fixture that covers the sensor, or delete it. Handle it in the same commit as F1 so the tree is never internally inconsistent. | XS | +| F8 | Documentation drift | `docs/issues/open/2150-add-lychee-link-checker/ISSUE.md:93` records the decision not to add a `.lycheeignore` file, and `project-words.txt:306` still carries `lycheeignore` as a dictionary entry. The file does not exist and by that decision never will. | Confirm no remaining prose needs the word, then drop the dictionary entry. Keep it if the closed specification's own text still requires it — the dictionary serves the documents, not the other way round. | XS | + +## Maintainer Actions + +These two items cannot be performed from a pull request. They are recorded here so they are visible and so the pull request does not silently leave them undone. + +| ID | Item | Evidence | Action owner and change | +| --- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| A1 | Allowed-actions allowlist pins an exact patch | `gh api repos/torrust/torrust-tracker/actions/permissions/selected-actions` returns `taiki-e/install-action@v2.87.2` among `patterns_allowed`. Three workflows use that action (`.github/workflows/testing.yaml:80`, `coverage.yaml:51`, `generate_coverage_pr.yaml:46`), so no Dependabot bump of it can run. On PR #2180 (`2.87.2` to `2.87.6`, head `a90c3bb1`), `gh api "…/actions/runs?head_sha=a90c3bb1…"` shows `Testing` (push), `Testing` (pull_request), and `Generate Coverage Report (PR)` all `startup_failure`, while `gh pr checks 2180` lists 18 rows that are all `pass` or `skipping` — the failures are invisible in the ordinary check view. The repository's own skill already prescribes the fix at `.github/skills/dev/maintenance/update-github-workflow-actions/SKILL.md:49`. | Repository administrator: change the allowlist entry to `taiki-e/install-action@v2.*`, as that skill directs. No file in this repository changes. Note that the permissions endpoint is readable with ordinary access, so the current value can be confirmed before and after. | +| A2 | Two Dependabot pull requests stalled since August | #2055 (`base64` 0.22.1 to 0.23.1, opened 2026-08-07) and #2106 (`syn` 2.0.119 to 3.0.4, opened 2026-08-27). `gh api repos/torrust/torrust-tracker/compare/...develop` puts `develop` 263 and 137 commits ahead respectively; both report `mergeStateStatus: UNSTABLE`, and on each the only failing check is `Docker E2E` — the symptom #2179 diagnoses and fixes. | Maintainer: after #2179 merges, rebase both and re-run, or close them if the major-version bumps are unwanted on their own merits. This issue does not touch either branch and does not duplicate #2179's fix. | + +## Related but Separate + +`Configuration::load` runs the strict Figment extract at `packages/configuration/src/v3_0_0/mod.rs:392` before checking `metadata.schema_version` at line 395. Because every configuration section carries `#[serde(deny_unknown_fields)]`, a version-2 configuration file fails on the first section name the version-3 schema does not know — reported as an unknown-field error naming `tracker` — instead of the `Error::UnsupportedVersion` that exists precisely to explain this case. The user sees a spelling complaint where the real problem is that the file is a schema version behind. + +This is a behavioural change to a user-facing error path, not a maintenance clean-up: it needs its own acceptance criteria, its own regression test, and a decision about whether the version probe reads the metadata section separately or whether the extract is relaxed. It is recorded here because it was found while verifying this batch, and it is recommended for its own issue rather than folded into this one. + +## Dropped Candidates + +Two items proposed for this batch did not reproduce and are recorded so the ground is not re-covered. + +| Candidate | Finding | +| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Broken or redirected local links | `linter lychee` exits 0 on `develop` with `All local Markdown links passed checking!` in 0.137 s. Local link health is already enforced by `.github/workflows/docs-lint.yaml:60`. External links are wholly owned by #2185, whose specification is under review in #2186. Nothing is left for this issue. The `.lycheeignore` file named in the original report does not exist and, per #2150, will not: the configuration lives in `lychee.toml` and `.github/lychee-online.toml`. | +| A second never-run merge-tool suite, `test-github-merge-symlinks.py` | No such file exists on `develop`. `contrib/dev-tools/git/tests/` contains only `test-merge-pull-request.sh`. The Python suite belongs to the unmerged symlink-exceptions work for #2175 and will arrive with it; F1 covers the suites that exist today. | + +## Architectural Decisions + +No architectural decision is expected. Every item is a mechanical correction to an existing decision's implementation, or the recording of an action outside this repository. + +- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` (F4 touches only its related-artifacts list, not the decision) +- ADRs to create: `None known` + +If F1's CI placement turns into a real choice about where developer-tool tests belong rather than a one-step addition, stop and raise it against EPIC #2003 rather than settling it inside a clean-up pull request. + +## Design and Ownership Review + +`Not applicable`. No item involves child processes, asynchronous I/O, network readiness, resource cleanup, or reusable test fixtures beyond the existing shell fixture repaired in F5, which creates and removes its own temporary directory under an `EXIT` trap that already works. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| T1 | TODO | Repair the dictionary-formatter test suite (F5) | `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 0 from a clean checkout; both defects fixed; no container runtime required. | +| T2 | TODO | Run the three developer-tool suites in CI (F1, F7) | One CI step invokes all three suites and fails the workflow when any fails; the "not automatically run" notes and the dead `Tests:` note are removed or corrected in the same change. | +| T3 | TODO | Narrow the container workflow trigger (F3) | `container.yaml:16` reads `releases/v*`; a push to a `releases/pkg/**` branch no longer starts the workflow. | +| T4 | TODO | Correct the stale binary-path references (F4) | The five live references name `packages/e2e-tools/src/bin/`; the ADR's related-artifacts list is extended; `docs/issues/closed/` is untouched. | +| T5 | TODO | Remove the unquotable explicit generic (F6) | The tracked tree contains no occurrence of the token; `cargo clippy` and the tool's own behaviour are unchanged. | +| T6 | TODO | Archive the sixteen closed issue specifications (F2) | The sixteen directories are under `docs/issues/closed/`; `linter lychee` still exits 0 after the move. | +| T7 | TODO | Retire the stale dictionary entry (F8) | `linter cspell` exits 0 with the entry removed, or the entry is kept with a one-line justification in the progress log. | +| T8 | TODO | Record the maintainer actions (A1, A2) | A1 and A2 are stated in the issue body so a maintainer can act; neither is attempted from the pull request. | +| T9 | TODO | Final verification and acceptance review | `linter all` exits 0, the pre-commit checks pass, manual scenarios are recorded, and every acceptance criterion is re-reviewed against observed behaviour. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | +| T1 | The two defects in the dictionary-formatter suite, with the suite green. | Commit once the suite exits 0 from a clean checkout. This lands first: T2 must not wire a red suite into CI. | +| T2 | The CI step plus the two now-untrue script notes. | Commit after the step is validated against the real workflow file. Depends on T1. | +| T3 | The one-line trigger narrowing. | Commit on its own after workflow validation. | +| T4 | The five documentation and skill references plus the ADR artifact list. | Commit on its own; documentation-only and independently revertible. | +| T5 | The signature change and its two call sites. | Commit on its own after focused validation of the tool's output. | +| T6 | The sixteen directory moves and any reference repairs they force. | Commit on its own. It is a large diff of pure moves; mixing it with anything else would bury the other changes. | +| T7 | The dictionary entry. | Fold into T4 if it turns out to be a one-word edit; commit separately if the word survives and the decision needs its own message. | +| T8 | No repository change. | Record in the progress log as a justified no-change decision; do not create an empty commit. | +| T9 | Completion evidence. | Keep separate from the fixes so the verification record is reviewable on its own. | + +Use a Conventional Commit message with the narrow affected scope, and sign every commit with GPG. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created and issue number added to this spec +- [ ] (Optional, recommended for complex issues) Spec-only PR merged into `develop` before implementation +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-09 14:11 UTC - Specification author - Drafted from a re-verification of every candidate friction against `develop` at `f6b73e29`; eight in-scope items, two maintainer actions, one related-but-separate behavioural defect, two dropped candidates - evidence recorded inline in the Friction Inventory, Maintainer Actions, and Dropped Candidates tables + +## Acceptance Criteria + +- [ ] AC1: Each of F1 through F8 is either fixed in this issue's pull request, or explicitly deferred with a linked issue recorded in the progress log. No item is left silently undone. +- [ ] AC2: `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 0 from a clean checkout, on a host with no container runtime available. +- [ ] AC3: All three developer-tool suites run in CI, and a deliberately broken suite fails the workflow. No script in `contrib/dev-tools/` still claims its tests are not automatically run when they are. +- [ ] AC4: A push to a branch matching `releases/pkg/**` starts no run of the container workflow. +- [ ] AC5: No live document, skill, or workflow places `e2e_tests_runner`, `profiling`, or `qbittorrent_e2e_runner` under `src/bin/`. Records under `docs/issues/closed/` are unchanged. +- [ ] AC6: `docs/issues/open/` contains a specification directory only for issues GitHub reports as `OPEN`, verified issue by issue at merge time. +- [ ] AC7: The tracked tree contains no occurrence of the explicit character-type generic described in F6, and `contrib/dev-tools/analysis/workspace-coupling` produces the same output as before the change. +- [ ] AC8: The issue body states maintainer actions A1 and A2 clearly enough for a maintainer to act without re-deriving the evidence. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all` +- `bash contrib/dev-tools/git/hooks/pre-commit.sh` +- The three developer-tool suites, individually and through the new CI step +- `linter lychee`, specifically after the F2 archival moves, to catch references the moves break + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------ | -------------------------------------------- | +| M1 | Repaired suite passes from a clean checkout | Clone the branch into a fresh directory on a host with no container runtime, then run `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` and echo `$?` | Exit code 0 and the line `All formatter and pre-commit hook tests passed.` | TODO | `manual-verification-evidence.md` section V1 | +| M2 | The new CI step actually catches a failure | On a scratch branch, break one assertion in one suite, push, and read the workflow run | The workflow fails and names the broken suite. Revert the scratch branch afterwards | TODO | `manual-verification-evidence.md` section V2 | +| M3 | Package release branches stay quiet | Push a throwaway branch named `releases/pkg/scratch/v0.0.1`, then list workflow runs for its head with `gh api "…/actions/runs?head_sha="`, then delete the branch | No `Container` run appears. Before the fix, one appears and exits 0 at the semver guard | TODO | `manual-verification-evidence.md` section V3 | +| M4 | Corrected paths point at real files | For each reference changed in F4, read the file at the path it now names | Every path exists. `docs/profiling.md` still describes a runnable profiling flow | TODO | `manual-verification-evidence.md` section V4 | +| M5 | The workspace-coupling tool is unchanged | Run the tool on `develop` and on the branch, and compare the two reports | The reports are identical apart from any embedded timestamp | TODO | `manual-verification-evidence.md` section V5 | +| M6 | Archived specifications are all closed | For every directory left in `docs/issues/open/`, run `gh issue view --json state` | Every remaining directory maps to an `OPEN` issue, and every moved one to a `CLOSED` issue | TODO | `manual-verification-evidence.md` section V6 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- M3 requires pushing and deleting a branch in a repository whose workflows react to `releases/**`. Run it on a fork unless a maintainer agrees otherwise, and record which repository was used. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Disposable Verification Scripts + +None is planned. Every scenario above is a direct human-oriented invocation of tooling that already exists, and F5's repair makes the one relevant fixture a maintained suite rather than a throwaway. If implementation nonetheless calls for a temporary script, record its issue-local path, why a maintained Rust automatic test is unsuitable for that specific scenario, its removal or retention owner, and — if written in Python — why Rust does not suit that script, before creating it. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | ------------------ | +| AC1 | TODO | {PR link} | +| AC2 | TODO | M1 | +| AC3 | TODO | M2 | +| AC4 | TODO | M3 | +| AC5 | TODO | M4 | +| AC6 | TODO | M6 | +| AC7 | TODO | M5 | +| AC8 | TODO | {issue body link} | + +## Risks and Trade-offs + +- Batching unrelated fixes can hide a bad one inside a large diff. Mitigation: one commit per friction, in the order set by [Commit Points](#commit-points), so a reviewer can reject a single item without unpicking the rest. F2's sixteen directory moves stay in their own commit for the same reason. +- The F2 archival is a snapshot. Issues close while the pull request is open, so the list can be stale by the time it merges. Mitigation: AC6 re-verifies every remaining directory against GitHub at merge time rather than trusting the list drafted here. +- Wiring the three suites into CI makes a previously invisible failure blocking. That is the point of F1, but it means F5 must land first, and it means a future breakage in those suites will stop a merge. Mitigation: the suites are fast and hermetic, and the CI step is a separate lightweight job so a failure is easy to read and does not consume the test matrix. +- Fixing F6 by changing a function signature touches behaviour-adjacent code in a clean-up pull request. Mitigation: M5 compares the tool's output before and after; if the comparison is anything but identical, defer the item to its own issue. +- F1's placement could turn out to be a design question about the check harness rather than a one-step addition. Mitigation: the stop condition is written into [Architectural Decisions](#architectural-decisions) — raise it against EPIC #2003 rather than deciding it here. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if any friction turns out to be larger than its recorded size, if F1's CI placement becomes a design decision, or if the F6 output comparison is not identical. +- If none of those occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #1774 (archival automation), #2003 (guardrails and automation EPIC), #2159 (folder-style spec adoption), #2179 (Docker E2E package flag), #2185 (external-link triage) +- Related PRs: #2055, #2106, #2180, #2186 +- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` From dbd19f1239829c80fe061ffbed825ce79362f3fb Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Wed, 9 Sep 2026 17:40:19 +0200 Subject: [PATCH 02/13] docs(issues): add issue specification for #2190 Move the reviewed maintenance-frictions clean-up specification out of drafts and into the open backlog under its assigned issue number, so the batch of eight verified frictions, the two maintainer-owned actions, and the one related-but-separate behavioural defect are tracked where implementation work looks for them. The specification records evidence per item against develop at f6b73e29 and keeps one commit per friction, so a reviewer can accept or reject each row independently. --- .../ISSUE.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) rename docs/issues/{drafts/maintenance-frictions-cleanup => open/2190-maintenance-frictions-cleanup}/ISSUE.md (97%) diff --git a/docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md b/docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md similarity index 97% rename from docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md rename to docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md index cb1bbbca0..81b7502d4 100644 --- a/docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md +++ b/docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md @@ -1,14 +1,14 @@ --- doc-type: issue issue-type: task -status: draft +status: open priority: p2 epic: null -github-issue: null -spec-path: docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md -branch: "{issue-number}-maintenance-frictions-cleanup-spec" +github-issue: 2190 +spec-path: docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md +branch: "2190-maintenance-frictions-cleanup-spec" related-pr: null -last-updated-utc: 2026-09-09 14:11 +last-updated-utc: 2026-09-09 15:39 semantic-links: skill-links: - create-issue @@ -23,7 +23,7 @@ semantic-links: -# Issue #[To be assigned] - Repository maintenance frictions clean-up +# Issue #2190 - Repository maintenance frictions clean-up ## Goal @@ -142,9 +142,9 @@ Use a Conventional Commit message with the narrow affected scope, and sign every ### Workflow Checkpoints -- [x] Folder-style spec drafted in `docs/issues/drafts/maintenance-frictions-cleanup/ISSUE.md` -- [ ] Spec reviewed and approved by user/maintainer -- [ ] GitHub issue created and issue number added to this spec +- [x] Folder-style spec drafted and moved to `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` +- [x] Spec reviewed and approved by user/maintainer +- [x] GitHub issue [#2190](https://github.com/torrust/torrust-tracker/issues/2190) created and issue number added to this spec - [ ] (Optional, recommended for complex issues) Spec-only PR merged into `develop` before implementation - [ ] Implementation completed - [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) @@ -159,6 +159,7 @@ Use a Conventional Commit message with the narrow affected scope, and sign every ### Progress Log - 2026-09-09 14:11 UTC - Specification author - Drafted from a re-verification of every candidate friction against `develop` at `f6b73e29`; eight in-scope items, two maintainer actions, one related-but-separate behavioural defect, two dropped candidates - evidence recorded inline in the Friction Inventory, Maintainer Actions, and Dropped Candidates tables +- 2026-09-09 15:39 UTC - Specification author - GitHub issue #2190 created from the reviewed draft; specification moved to `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria From 23db4718bc79e16d4bac30c18e493d09bd65b6b5 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 10:43:47 +0200 Subject: [PATCH 03/13] docs(issues): convert #2190 specification into a planning-only EPIC The specification proposed fixing eight unrelated maintenance frictions in one pull request. That shape makes review expensive and hides items that already fall inside an existing EPIC's scope. Rename the primary document to EPIC.md, restate the scope as planning only, and add a Clusters section that assigns every inventory item to a domain cluster and argues its parent from that parent's own stated scope. The verified inventory, maintainer actions, related-but-separate defect, and dropped candidates are preserved as the evidence behind the subissues. --- .../EPIC.md | 262 ++++++++++++++++++ .../ISSUE.md | 247 ----------------- 2 files changed, 262 insertions(+), 247 deletions(-) create mode 100644 docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md delete mode 100644 docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md diff --git a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md new file mode 100644 index 000000000..560ae8c56 --- /dev/null +++ b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md @@ -0,0 +1,262 @@ +--- +doc-type: epic +issue-type: task +status: planned +priority: p2 +github-issue: 2190 +spec-path: docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +epic-owner: null +branch: "2190-maintenance-frictions-cleanup-spec" +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - docs/templates/EPIC.md + - docs/issues/open/README.md + - docs/issues/drafts/README.md + - docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md + - AGENTS.md + - .github/workflows/container.yaml + - contrib/dev-tools/checks/tests/test-format-project-words.sh + - contrib/dev-tools/analysis/workspace-coupling/src/main.rs +--- + + + +# EPIC #2190 - Repository maintenance frictions clean-up + +## Goal + +Turn a verified inventory of small repository maintenance frictions into a set of domain-clustered, independently reviewable subissues, so each friction is fixed in its own small pull request and under the EPIC that already owns its domain. This EPIC is planning-only: it changes no code, configuration, or documentation outside its own specification and the subissue specifications it produces. + +## Why This Is Needed + +Routine work across this repository keeps running into the same set of small defects: a developer-tool test suite that has been red on `develop` since it was moved, three such suites that no orchestrator runs at all, sixteen issue specifications for closed issues still sitting in the open backlog, a workflow trigger that starts a job on branches it immediately refuses, and documentation that still points at binaries which have since moved into a package. None of these is large enough to have justified its own issue when it was found, and none of them blocks a feature, so each has survived several release cycles. Individually they are noise; collectively they are a standing tax on every contributor and agent who reads a stale path, re-diagnoses a red test, or scrolls past a failed workflow run that was never going to succeed. + +The first version of this specification proposed fixing all of them in one pull request. That shape has two costs. A single pull request touching workflows, shell fixtures, Rust source, documentation, and sixteen directory moves is hard to review and hard to revert item by item, and the reviewing effort grows faster than the size of the diff. It also discards domain context: several of the frictions sit squarely inside the scope of an EPIC that already exists, and fixing them elsewhere hides them from the EPIC that will later have to reason about the same surface. Clustering by domain keeps each fix next to the work that shares its context, which is easier for a human reviewer to hold in mind and easier for an agent to work through with the parent EPIC as its context. + +The inventory itself is still worth keeping. Each entry was verified against the tree rather than reported, and that evidence is what makes the resulting subissues cheap to write and cheap to accept. This EPIC preserves that evidence and spends it on subissue specifications instead of on one large change. + +## Scope + +### In Scope + +- Preserve the verified [Friction Inventory](#friction-inventory), [Maintainer Actions](#maintainer-actions), [Related but Separate](#related-but-separate), and [Dropped Candidates](#dropped-candidates) evidence as the durable record behind every subissue this EPIC produces. +- Cluster every inventory item by domain and record, for each cluster, the EPIC that owns it and the reason that EPIC owns it. +- Produce one draft subissue specification per cluster item under `docs/issues/drafts/`, each sized for one focused pull request and each naming its parent EPIC. +- Create the GitHub subissues from the approved drafts, link them under their parent EPIC, and move each specification into `docs/issues/open/` under the naming convention. +- Hand the two clusters that belong to EPIC #2003 to that EPIC, including the row each needs in its subissue table. +- Track completion of the subissues this EPIC owns until every inventory item is delivered or explicitly closed as won't-fix. + +### Out of Scope + +- Fixing any friction in this EPIC's own pull request. Every code, configuration, and documentation change belongs to a subissue and is reviewed there. +- Re-verifying the inventory. It was verified against `develop` at revision `f6b73e29` on 2026-09-09; a subissue re-checks its own item at implementation time, and a stale entry is corrected in that subissue rather than here. +- Automating the issue-specification archival flow. That is #1774; the archival subissue performs the current archival by hand and does not constrain the script's design. +- Triaging external-link check findings. That is #2185, whose specification is under review in #2186. +- Repairing the `Docker E2E` job in `.github/workflows/testing.yaml`. That is #2179; this EPIC only records which stale pull requests are blocked behind it. +- Migrating legacy single-file specifications to the folder-style layout. That is #2159. +- Designing the long-term check harness and sensor architecture. That is EPIC #2003; the two clusters handed to it add and repair invocations of checks that already exist and do not prejudge that design. +- Any behavioural change to the tracker itself. The one behavioural defect found while verifying the inventory is recorded in [Related but Separate](#related-but-separate) and becomes a standalone issue with its own acceptance criteria. + +## Friction Inventory + +This is the verified evidence behind the subissues. Each entry was re-verified against `develop` at revision `f6b73e29` on 2026-09-09; the evidence column records what was observed rather than what was reported. The proposed fix is the starting point for the subissue that owns the item, not a decision binding on it. + +Size is the expected reviewable weight of the change: `XS` is a one-line edit, `S` is a handful of lines in one file, `M` spans several files or needs a judgement call. The `Cluster` column links each item to its parent in [Clusters](#clusters). + +| ID | Cluster | Area | Evidence (verified at `f6b73e29`, 2026-09-09) | Proposed fix | Size | +| --- | ------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | +| F1 | C2 | Developer tooling | Three developer-tool test suites exist and no orchestrator runs any of them: `contrib/dev-tools/git/tests/test-merge-pull-request.sh`, `contrib/dev-tools/checks/tests/test-format-project-words.sh`, `contrib/dev-tools/checks/tests/test-agent-review-report-contract.sh`. `grep -rn "contrib/dev-tools" .github/workflows/` returns only the container persistence test and the hook installer; the suites appear in no `STEPS` entry of `contrib/dev-tools/git/hooks/pre-commit.sh` (lines 51-58) or `pre-push.sh`. Two scripts state the gap themselves: `contrib/dev-tools/checks/tests/test-format-project-words.sh:6` and `contrib/dev-tools/checks/format-project-words.sh:6`. | Add one lightweight CI step that runs the three suites, and delete the now-untrue "not automatically run" notes. Keep the step outside the expensive test matrix; the three suites together complete in roughly one second on a warm host. | S | +| F2 | C5 | Issue lifecycle | Sixteen specification directories under `docs/issues/open/` belong to issues GitHub reports as `CLOSED`: 1586, 1588, 2121, 2122, 2130, 2132, 2134, 2136, 2138, 2140, 2150, 2151, 2155, 2156, 2160, 2162. Verified by `gh issue view --json state,closedAt` for every directory in `docs/issues/open/`. The archival rule is `docs/issues/closed/README.md`. | Move the sixteen directories to `docs/issues/closed/` per the `cleanup-completed-issues` skill, repairing any live references the move breaks. Automation of this flow stays with #1774. | M | +| F3 | C3 | Workflow triggers | `.github/workflows/container.yaml:16` triggers pushes on `releases/**/*`, while `.github/workflows/deployment.yaml:15` was narrowed to `releases/v*`. Package release branches match `releases/pkg/**` (`.github/workflows/deployment-packages.yaml:35`), so every package release push also starts the container workflow, which then extracts `pkg//v` as its version, fails the semver test at `container.yaml:165`, prints `Not a valid release branch semver. Will Not Continue`, and exits 0. | Narrow `container.yaml:16` to `releases/v*`, matching `deployment.yaml`. The semver guard stays as the second line of defence. | XS | +| F4 | C4 | Documentation drift | `src/bin/` now contains only `http_health_check.rs`; `e2e_tests_runner`, `profiling`, and `qbittorrent_e2e_runner` moved to `packages/e2e-tools/src/bin/` in commit `c47173f53`. Five live references were never updated: `AGENTS.md:39`, `.github/skills/dev/testing/manual-http-download-completion-e2e/SKILL.md:21` and `:307`, `.github/skills/dev/testing/manual-udp-download-completion-e2e/SKILL.md:207`, `docs/profiling.md:10`. `docs/adrs/20260519000000_define_global_cli_output_contract.md:8` lists `src/bin/` as a related artifact and now under-describes the binary landscape. | Correct the five live references to `packages/e2e-tools/src/bin/`. Extend the ADR's related-artifacts list rather than rewriting the decision. Leave `docs/issues/closed/` untouched: those are immutable historical records. #2179 names this drift out of its own scope and worth its own issue. | S | +| F5 | C1 | Test health | `contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 1 on `develop` for two independent reasons. First, `PROJECT_ROOT` at line 13 climbs three levels from `contrib/dev-tools/checks/tests/` and lands on `/contrib`, so every fixture copy reads `/contrib/contrib/dev-tools/...` and fails; the sibling suite at `contrib/dev-tools/git/tests/test-merge-pull-request.sh:6` climbs four from an equally deep directory and is correct. Commit `ffa2aa2c5` introduced the wrong depth when it moved the suite beside its sensor. Second, with the depth corrected the suite still fails: `create_fixture` (lines 21-28) never provisions `contrib/dev-tools/checks/lint-containerfile.sh`, so pre-commit step 5 of 6 reports `No such file or directory`, `commands.log` holds 3 entries where line 205 asserts 4, and the success banner asserted at line 206 is never printed. | Correct the `PROJECT_ROOT` depth to four levels, and provision the Containerfile lint sensor in the fixture with a stub that keeps the suite hermetic and free of any container runtime. Re-check the `commands.log` count assertion against whichever stub is chosen. | S | +| F6 | C6 | Code readability | `contrib/dev-tools/analysis/workspace-coupling/src/main.rs:191` writes an explicit generic argument naming Rust's character type — the five-character token spelled angle bracket, c-h-a-r, angle bracket. It is the only occurrence in the tracked tree. Chat and review transport layers substitute that token with a role or account name, so the line cannot be quoted in a review discussion without arriving as text that would not compile, which makes a reviewer reasonably distrust the quoted artifact. | Take the character by value — `fn is_rust_identifier_char(ch: char) -> bool` — and move the optionality to the two call sites at line 187, which already hold values from `chars().next_back()` and `chars().next()` and can use `is_some_and`. Behaviour is unchanged: an absent adjacent character still reads as "not an identifier character". Where a token-free signature is genuinely impossible, a local type alias or inference through `collect()` serves the same purpose. | XS | +| F7 | C2 | Dead comment | `contrib/dev-tools/checks/lint-containerfile.sh:4` reads `Tests: (no automated tests yet — EPIC #2003)`. Once F5 and F1 land, the fixture for that sensor exists and is exercised, so the note becomes untrue in the same pull request that makes it so. | Update the note to point at the fixture that covers the sensor, or delete it. Handle it in the same commit as F1 so the tree is never internally inconsistent. | XS | +| F8 | C4 | Documentation drift | `docs/issues/open/2150-add-lychee-link-checker/ISSUE.md:93` records the decision not to add a `.lycheeignore` file, and `project-words.txt:306` still carries `lycheeignore` as a dictionary entry. The file does not exist and by that decision never will. | Confirm no remaining prose needs the word, then drop the dictionary entry. Keep it if the closed specification's own text still requires it — the dictionary serves the documents, not the other way round. | XS | + +## Maintainer Actions + +These two items cannot be performed from a pull request; both are cluster C7 and each becomes a subissue that changes no file in this repository. The evidence is kept here so the subissue specifications do not have to re-derive it. + +| ID | Item | Evidence | Action owner and change | +| --- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| A1 | Allowed-actions allowlist pins an exact patch | `gh api repos/torrust/torrust-tracker/actions/permissions/selected-actions` returns `taiki-e/install-action@v2.87.2` among `patterns_allowed`. Three workflows use that action (`.github/workflows/testing.yaml:80`, `coverage.yaml:51`, `generate_coverage_pr.yaml:46`), so no Dependabot bump of it can run. On PR #2180 (`2.87.2` to `2.87.6`, head `a90c3bb1`), `gh api "…/actions/runs?head_sha=a90c3bb1…"` shows `Testing` (push), `Testing` (pull_request), and `Generate Coverage Report (PR)` all `startup_failure`, while `gh pr checks 2180` lists 18 rows that are all `pass` or `skipping` — the failures are invisible in the ordinary check view. The repository's own skill already prescribes the fix at `.github/skills/dev/maintenance/update-github-workflow-actions/SKILL.md:49`. | Repository administrator: change the allowlist entry to `taiki-e/install-action@v2.*`, as that skill directs. No file in this repository changes. Note that the permissions endpoint is readable with ordinary access, so the current value can be confirmed before and after. | +| A2 | Two Dependabot pull requests stalled since August | #2055 (`base64` 0.22.1 to 0.23.1, opened 2026-08-07) and #2106 (`syn` 2.0.119 to 3.0.4, opened 2026-08-27). `gh api repos/torrust/torrust-tracker/compare/...develop` puts `develop` 263 and 137 commits ahead respectively; both report `mergeStateStatus: UNSTABLE`, and on each the only failing check is `Docker E2E` — the symptom #2179 diagnoses and fixes. | Maintainer: after #2179 merges, rebase both and re-run, or close them if the major-version bumps are unwanted on their own merits. This issue does not touch either branch and does not duplicate #2179's fix. | + +## Related but Separate + +`Configuration::load` runs the strict Figment extract at `packages/configuration/src/v3_0_0/mod.rs:392` before checking `metadata.schema_version` at line 395. Because every configuration section carries `#[serde(deny_unknown_fields)]`, a version-2 configuration file fails on the first section name the version-3 schema does not know — reported as an unknown-field error naming `tracker` — instead of the `Error::UnsupportedVersion` that exists precisely to explain this case. The user sees a spelling complaint where the real problem is that the file is a schema version behind. + +This is a behavioural change to a user-facing error path, not a maintenance clean-up: it needs its own acceptance criteria, its own regression test, and a decision about whether the version probe reads the metadata section separately or whether the extract is relaxed. It is recorded here because it was found while verifying this inventory. It is cluster C8, item `R1`: a standalone issue with no parent EPIC, drafted at `docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md`. The configuration overhaul EPIC that would have owned it, #1978, is closed. + +## Dropped Candidates + +Two items proposed for this inventory did not reproduce. They produce no subissue and are recorded so the same ground is not re-covered. + +| Candidate | Finding | +| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Broken or redirected local links | `linter lychee` exits 0 on `develop` with `All local Markdown links passed checking!` in 0.137 s. Local link health is already enforced by `.github/workflows/docs-lint.yaml:60`. External links are wholly owned by #2185, whose specification is under review in #2186. Nothing is left for this issue. The `.lycheeignore` file named in the original report does not exist and, per #2150, will not: the configuration lives in `lychee.toml` and `.github/lychee-online.toml`. | +| A second never-run merge-tool suite, `test-github-merge-symlinks.py` | No such file exists on `develop`. `contrib/dev-tools/git/tests/` contains only `test-merge-pull-request.sh`. The Python suite belongs to the unmerged symlink-exceptions work for #2175 and will arrive with it; F1 covers the suites that exist today. | + +## Clusters + +Each inventory item belongs to exactly one cluster, and each cluster to exactly one parent. A cluster is a domain — one reviewer context, one surface, one body of prior decisions — not a size bucket. Two clusters were adopted by an EPIC that already exists; the rest stay under this EPIC because no existing EPIC's stated scope covers them. + +| Cluster | Items | Domain | Parent | Draft specification | +| ------- | ---------- | --------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------- | +| C1 | F5 | Developer-tool checks: repairing an existing check | EPIC #2003 | `docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md` | +| C2 | F1, F7 | Developer-tool checks: invoking existing checks from CI | EPIC #2003 | `docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md` | +| C3 | F3 | Workflow trigger correctness | EPIC #2190 | `docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md` | +| C4 | F4, F8 | Stale references left behind by completed moves and decisions | EPIC #2190 | `docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md` | +| C5 | F2 | Issue-backlog archival | EPIC #2190 | `docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md` | +| C6 | F6 | Source hygiene for quotable artifacts | EPIC #2190 | `docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md` | +| C7 | A1, A2 | Repository administration; no repository change | EPIC #2190 | `docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md`, `docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md` | +| C8 | R1 | Configuration error reporting | None; standalone issue | `docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md` | + +### Why Each Parent + +**C1 and C2 belong to EPIC #2003 - Overhaul: Automation Tools and AI Agent Guardrails.** Its In Scope list covers exactly this surface: it undertakes to "Evaluate check placement across pre-commit, pre-push, CI, and any future repository-policy or architecture-check category", and it explicitly permits "the narrowly scoped interim formatter described by [`2019-automatically-format-project-dictionary`](../../closed/2019-automatically-format-project-dictionary/ISSUE.md)". F5 repairs that permitted formatter's own test suite, and C2 wires that suite and its two siblings into CI. Both also meet #2003's stated exception for work that may proceed before its architecture decision: "low-risk, additive, independently verifiable documentation, skill, profile, template, and focused validation subissues ... when they do not select or depend on a shared runner, cache, enforcement platform, external workflow tool, or broad consumer migration". Neither cluster selects a runner shape; each adds one invocation of a check that already exists, and both remain replaceable by the later design. F7 rides with C2 rather than standing alone because the dead note it removes — `contrib/dev-tools/checks/lint-containerfile.sh:4`, which reads that the sensor has no automated tests yet and names EPIC #2003 — only becomes untrue once C2 lands; splitting them would leave the tree self-contradicting between two pull requests. + +**C3 stays under this EPIC.** The only EPIC that owns `.github/workflows/container.yaml` is #1840 - Improve PR Workflow Performance, and its goal is stated in time: "Reduce the execution time of the critical PR validation workflows ... so maintainers and contributors can get faster feedback". F3 changes no workflow's runtime and no pull request's wait time. The spurious run it prevents is started by pushes to package release branches, which are not on the pull request critical path at all, and #1840's Out of Scope explicitly excludes "Optimizing unrelated workflows unless they directly affect these two critical paths". F3 is a trigger-predicate defect, not a performance item. + +**C4 stays under this EPIC.** F4's stale paths were created by a package move, which invites EPIC #1669 - Overhaul: Packages, but that EPIC's documentation duty is specific: its audit covers `docs/packages.md`, `packages/AGENTS.md`, the extracted-packages tables, and the dependency diagram at `docs/media/packages/dependencies-workspace-packages.md`. None of F4's five live references is one of those; they are in the testing section of `AGENTS.md`, two testing skills, and `docs/profiling.md`. F8's stale dictionary entry has no package dimension at all. What F4 and F8 share is the shape of the defect rather than the file: both name a referent that no longer exists or never will, one because the binaries moved and one because #2150 decided the file would not be created. That is one reviewer context and one small pull request. + +**C5 stays under this EPIC.** The archival flow's automation is #1774, which is a paused dependency of EPIC #2003 and blocked on that EPIC's architecture decision. Performing the current archival by hand is not automation work and must not inherit that block: it implements no tool, selects no interface, and constrains nothing in #1774's design. Filing it under #2003 would either park it behind a decision it does not need or force an exception into that EPIC's scope for a one-off manual action. + +**C6 stays under this EPIC.** The file it touches, `contrib/dev-tools/analysis/workspace-coupling/`, appears in EPIC #2003's related-artifacts list, but appearing as an artifact of an EPIC is not the same as falling inside its scope, and #2003's scope is the architecture of automation and guardrails rather than the source hygiene of any one tool. F6 changes one function signature so the line can survive being quoted in a review discussion; that concern is about how repository artifacts are reviewed, which is this EPIC's own domain. + +**C7 stays under this EPIC as two subissues with no repository change.** A1 and A2 are administrative actions on the GitHub repository and its pull requests. They are subissues rather than notes so that each has an owner, an acceptance criterion, and a visible state, which a table row inside another issue's body does not give them. + +**C8 has no parent.** The configuration error-ordering defect is a behavioural change to a user-facing error path in `packages/configuration`. The configuration overhaul EPIC that would have owned it, #1978, is closed. It needs its own acceptance criteria and its own regression test, and attaching it to a maintenance EPIC would misrepresent it as clean-up. + +## Subissues + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +These are the subissues this EPIC owns. Issue numbers are assigned when the drafts are approved and the GitHub issues are created; until then the draft path is the specification. + +| Order | Issue | Local Spec | Status | Notes | +| ----- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------- | +| 1 | #[To be assigned] - Narrow the container workflow release trigger | `docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md` | TODO | C3. One-line trigger change; independent of every other subissue. | +| 2 | #[To be assigned] - Correct stale documentation references | `docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md` | TODO | C4. Documentation and dictionary only; independently revertible. | +| 3 | #[To be assigned] - Archive closed issue specifications | `docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md` | TODO | C5. Large diff of pure moves; re-verify issue state at merge time. Does not constrain #1774. | +| 4 | #[To be assigned] - Remove the unquotable character-type generic | `docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md` | TODO | C6. Signature change with a before/after output comparison. | +| 5 | #[To be assigned] - Widen the workflow actions allowlist entry | `docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md` | TODO | C7, A1. Repository administrator action; no file in this repository changes. | +| 6 | #[To be assigned] - Resolve the stalled dependency update PRs | `docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md` | TODO | C7, A2. Blocked until #2179 merges; no file in this repository changes. | + +## Issues Handed to Other Owners + +These items leave this EPIC. Each draft names its own parent, and the parent EPIC's subissue table gains its row when the GitHub issue is created — not in this EPIC's pull request. + +| Items | Draft specification | New owner | Ordering | +| ------ | ---------------------------------------------------------------------------------- | ---------------------- | ------------------------------------------------------------------------ | +| F5 | `docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md` | EPIC #2003 | First. The suite must be green before anything runs it in CI. | +| F1, F7 | `docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md` | EPIC #2003 | After F5. | +| R1 | `docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md` | Standalone; no parent | Independent. | + +## Architectural Decisions + +No architectural decision is expected from this EPIC. It produces specifications; every item is a mechanical correction to an existing decision's implementation, the recording of an action outside this repository, or — for C8 — a behavioural defect whose own issue carries its design question. + +- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` (C4 touches only its related-artifacts list, not the decision) +- ADRs to create: `None known` + +If C2's CI placement turns out to be a real choice about where developer-tool tests belong rather than a one-step addition, it is settled inside EPIC #2003's design rather than in a clean-up pull request. That is one of the reasons C1 and C2 move there. + +## Delivery Strategy + +The EPIC delivers specifications, not fixes. The order below reflects dependency and reviewer cost, not priority. + +For each subissue implementation in this EPIC, the default completion policy is: + +1. Run automatic checks (`linter all`, relevant tests, pre-push checks when applicable). +2. Run manual verification scenarios and record evidence. +3. Re-review acceptance criteria after implementation and update verification evidence. +4. Complete an evidence-based implementation review. Create or update an issue-local retrospective for reusable lessons, material design changes, or meaningful deviations from the plan; otherwise record why one was unnecessary in the issue progress log. + +### Phase 1: Clustering + +- Outcome: every inventory item is assigned to a cluster and a parent, with the assignment argued from the parent's own stated scope. +- Exit criteria: the [Clusters](#clusters) tables are complete, a draft specification exists for every cluster item, and a maintainer has reviewed the clustering. + +### Phase 2: Issue Creation + +- Outcome: the approved drafts become GitHub issues, linked as subissues of their parent EPIC, with each specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number. +- Exit criteria: every row in [Subissues](#subissues) and [Issues Handed to Other Owners](#issues-handed-to-other-owners) carries a real issue number, and EPIC #2003's subissue table carries the two rows it adopted. + +### Phase 3: Delivery + +- Outcome: each subissue is implemented and merged in its own pull request, in the ordering its cluster records. +- Exit criteria: every inventory item is delivered or explicitly closed as won't-fix with the reason recorded in this EPIC's progress log. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted and moved to `docs/issues/open/2190-maintenance-frictions-cleanup/` +- [x] Spec reviewed and approved by user/maintainer +- [x] GitHub issue [#2190](https://github.com/torrust/torrust-tracker/issues/2190) created and issue number added to this spec +- [x] Specification converted from a single implementation issue into a planning-only EPIC +- [ ] Clustering reviewed and approved by a maintainer +- [ ] Spec-only PR merged into `develop` +- [ ] GitHub issue #2190 converted to an EPIC issue: title, labels, and body updated to match this specification +- [ ] Subissues created from the approved drafts and linked under their parent EPIC +- [ ] Subissue specifications moved from `docs/issues/drafts/` to `docs/issues/open/` +- [ ] EPIC #2003's subissue table updated with the two adopted clusters +- [ ] Subissue statuses kept up to date in the `Subissues` table +- [ ] For each implemented subissue: automatic checks completed and recorded +- [ ] For each implemented subissue: manual verification completed and recorded +- [ ] For each implemented subissue: acceptance criteria reviewed post-implementation +- [ ] For each implemented subissue: implementation completion review recorded +- [ ] Epic acceptance criteria reviewed and checked off +- [ ] Epic issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-09 14:11 UTC - Specification author - Drafted from a re-verification of every candidate friction against `develop` at `f6b73e29`; eight in-scope items, two maintainer actions, one related-but-separate behavioural defect, two dropped candidates - evidence recorded inline in the Friction Inventory, Maintainer Actions, and Dropped Candidates tables +- 2026-09-09 15:39 UTC - Specification author - GitHub issue #2190 created from the reviewed draft; specification moved to `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Restructured after the review on PR #2193 requesting an EPIC with domain-clustered subissues instead of one implementation issue: specification renamed to `EPIC.md` and made planning-only, the eight frictions and two maintainer actions clustered into eight clusters, two clusters handed to EPIC #2003, and nine draft subissue specifications added under `docs/issues/drafts/` - https://github.com/torrust/torrust-tracker/pull/2193#pullrequestreview-5164674289 + +## Acceptance Criteria + +- [ ] AC1: Every item in [Friction Inventory](#friction-inventory) and [Maintainer Actions](#maintainer-actions), and the item in [Related but Separate](#related-but-separate), appears in exactly one row of [Clusters](#clusters) with a named parent. +- [ ] AC2: Each cluster's parent is justified from that parent's own stated scope, and the drafts adopted by another EPIC set `epic:` to that EPIC and name it below their title. +- [ ] AC3: Each draft subissue specification is sized for one focused pull request and carries its own acceptance criteria and verification plan. +- [ ] AC4: This EPIC's pull request changes no file outside `docs/issues/` and `docs/copilot-pr-reviews/`. +- [ ] AC5: Every row in [Subissues](#subissues) and [Issues Handed to Other Owners](#issues-handed-to-other-owners) carries a created GitHub issue number, linked as a subissue of its parent EPIC. +- [ ] AC6: Every inventory item is delivered by a merged subissue pull request, or closed as won't-fix with the reason recorded in the progress log. +- [ ] AC7: The [Dropped Candidates](#dropped-candidates) record survives the restructuring, so the same ground is not re-covered. +- [ ] `linter all` exits with code `0` +- [ ] Documentation and governance updates are included when required. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | ---------------------------------------------------------- | +| AC1 | TODO | [Clusters](#clusters) | +| AC2 | TODO | [Why Each Parent](#why-each-parent) and the draft frontmatter | +| AC3 | TODO | The draft specifications listed in [Clusters](#clusters) | +| AC4 | TODO | {PR link} | +| AC5 | TODO | {issue links} | +| AC6 | TODO | {PR links} | +| AC7 | TODO | [Dropped Candidates](#dropped-candidates) | + +## Risks and Trade-offs + +- Splitting eight frictions into six subissues plus two adoptions costs more issue-management overhead than one pull request would have. Mitigation: the split is by domain rather than by item, so the count stays close to the number of reviewer contexts involved rather than to the number of defects, and two clusters are absorbed by an EPIC that already has the context. +- Small subissues can stall before they are filed, leaving the inventory as documentation rather than work. Mitigation: AC5 and AC6 make the created issues and their delivery an acceptance condition of this EPIC, and the EPIC stays open until every item is delivered or closed as won't-fix. +- The inventory is a snapshot taken at `f6b73e29`. An item can be fixed or changed by unrelated work before its subissue is implemented. Mitigation: each subissue re-checks its own evidence at implementation time and records a no-change outcome rather than forcing a fix. +- The C5 archival list is the most perishable entry: issues close while a pull request is open. Mitigation: its subissue re-verifies every remaining directory against GitHub at merge time rather than trusting the list drafted here. +- Handing C1 and C2 to EPIC #2003 places them behind that EPIC's review attention, which is directed at an unfinished architecture decision. Mitigation: both clusters are filed under #2003's own exception for additive, independently verifiable work that may proceed before the decision, so neither waits on it. +- Two subissues change no file in this repository, which is an unusual shape for an issue here. Mitigation: their specifications state the no-change outcome explicitly and record a justified no-change decision in the progress log rather than producing an empty commit. + +## References + +- Related issues: #1774 (archival automation), #2003 (guardrails and automation EPIC), #2150 (lychee link checker), #2159 (folder-style spec adoption), #2179 (Docker E2E package flag), #2185 (external-link triage) +- Related PRs: #2055, #2106, #2180, #2186, #2193 +- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` diff --git a/docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md b/docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md deleted file mode 100644 index 81b7502d4..000000000 --- a/docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md +++ /dev/null @@ -1,247 +0,0 @@ ---- -doc-type: issue -issue-type: task -status: open -priority: p2 -epic: null -github-issue: 2190 -spec-path: docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md -branch: "2190-maintenance-frictions-cleanup-spec" -related-pr: null -last-updated-utc: 2026-09-09 15:39 -semantic-links: - skill-links: - - create-issue - related-artifacts: - - .github/skills/dev/planning/create-issue/SKILL.md - - AGENTS.md - - .github/workflows/container.yaml - - contrib/dev-tools/checks/tests/test-format-project-words.sh - - contrib/dev-tools/analysis/workspace-coupling/src/main.rs - - docs/issues/open/README.md ---- - - - -# Issue #2190 - Repository maintenance frictions clean-up - -## Goal - -Clear a verified batch of small, independent maintenance frictions in one review pass, so that each one stops costing attention on every unrelated change, and record the two items that are not code changes so a maintainer can act on them deliberately. - -## Background - -Routine work across this repository keeps running into the same set of small defects: a developer-tool test suite that has been red on `develop` since it was moved, three such suites that no orchestrator runs at all, sixteen issue specifications for closed issues still sitting in the open backlog, a workflow trigger that starts a job on branches it immediately refuses, and documentation that still points at binaries which have since moved into a package. None of these is large enough to justify its own issue and none of them blocks a feature, so each has survived several release cycles. Individually they are noise; collectively they are a standing tax on every contributor and agent who reads a stale path, re-diagnoses a red test, or scrolls past a failed workflow run that was never going to succeed. - -Each entry below was re-verified against `develop` at revision `f6b73e29` on 2026-09-09; the evidence column records what was observed rather than what was reported. Two candidates that had been proposed for this batch did not reproduce and were dropped; they are recorded in [Dropped Candidates](#dropped-candidates) so the same ground is not re-covered. - -The frictions are deliberately grouped rather than filed separately. They share a review context — small, low-risk, mechanical — and splitting them into a dozen issues would cost more maintainer attention than the defects themselves. They do not share an implementation: each row is independently revertible, so a single reviewer can accept or reject them one at a time within one pull request. - -## Scope - -### In Scope - -- The eight code, configuration, and documentation frictions listed in [Friction Inventory](#friction-inventory), each fixed or explicitly deferred with a linked issue. -- Recording the two maintainer-owned items in [Maintainer Actions](#maintainer-actions) so they are visible and actionable, without attempting to perform them from a pull request. -- Recording the one behavioural defect in [Related but Separate](#related-but-separate) with a recommendation that it gets its own issue. - -### Out of Scope - -- Automating the issue-specification archival flow. That is #1774; this issue performs the current archival by hand and does not constrain the script's design. -- Triaging external-link check findings. That is #2185, whose specification is under review in #2186. -- Repairing the `Docker E2E` job in `.github/workflows/testing.yaml`. That is #2179; this issue only records which stale pull requests are blocked behind it. -- Migrating legacy single-file specifications to the folder-style layout. That is #2159. -- Designing the long-term check harness and sensor architecture. That is EPIC #2003; F1 below adds the missing invocation of suites that already exist and does not prejudge that design. -- Any behavioural change to the tracker itself, other than the explicitly out-of-scope item recorded in [Related but Separate](#related-but-separate). - -## Friction Inventory - -Size is the expected reviewable weight of the change: `XS` is a one-line edit, `S` is a handful of lines in one file, `M` spans several files or needs a judgement call. - -| ID | Area | Evidence (verified at `f6b73e29`, 2026-09-09) | Proposed fix | Size | -| --- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | -| F1 | Developer tooling | Three developer-tool test suites exist and no orchestrator runs any of them: `contrib/dev-tools/git/tests/test-merge-pull-request.sh`, `contrib/dev-tools/checks/tests/test-format-project-words.sh`, `contrib/dev-tools/checks/tests/test-agent-review-report-contract.sh`. `grep -rn "contrib/dev-tools" .github/workflows/` returns only the container persistence test and the hook installer; the suites appear in no `STEPS` entry of `contrib/dev-tools/git/hooks/pre-commit.sh` (lines 51-58) or `pre-push.sh`. Two scripts state the gap themselves: `contrib/dev-tools/checks/tests/test-format-project-words.sh:6` and `contrib/dev-tools/checks/format-project-words.sh:6`. | Add one lightweight CI step that runs the three suites, and delete the now-untrue "not automatically run" notes. Keep the step outside the expensive test matrix; the three suites together complete in roughly one second on a warm host. | S | -| F2 | Issue lifecycle | Sixteen specification directories under `docs/issues/open/` belong to issues GitHub reports as `CLOSED`: 1586, 1588, 2121, 2122, 2130, 2132, 2134, 2136, 2138, 2140, 2150, 2151, 2155, 2156, 2160, 2162. Verified by `gh issue view --json state,closedAt` for every directory in `docs/issues/open/`. The archival rule is `docs/issues/closed/README.md`. | Move the sixteen directories to `docs/issues/closed/` per the `cleanup-completed-issues` skill, repairing any live references the move breaks. Automation of this flow stays with #1774. | M | -| F3 | Workflow triggers | `.github/workflows/container.yaml:16` triggers pushes on `releases/**/*`, while `.github/workflows/deployment.yaml:15` was narrowed to `releases/v*`. Package release branches match `releases/pkg/**` (`.github/workflows/deployment-packages.yaml:35`), so every package release push also starts the container workflow, which then extracts `pkg//v` as its version, fails the semver test at `container.yaml:165`, prints `Not a valid release branch semver. Will Not Continue`, and exits 0. | Narrow `container.yaml:16` to `releases/v*`, matching `deployment.yaml`. The semver guard stays as the second line of defence. | XS | -| F4 | Documentation drift | `src/bin/` now contains only `http_health_check.rs`; `e2e_tests_runner`, `profiling`, and `qbittorrent_e2e_runner` moved to `packages/e2e-tools/src/bin/` in commit `c47173f53`. Five live references were never updated: `AGENTS.md:39`, `.github/skills/dev/testing/manual-http-download-completion-e2e/SKILL.md:21` and `:307`, `.github/skills/dev/testing/manual-udp-download-completion-e2e/SKILL.md:207`, `docs/profiling.md:10`. `docs/adrs/20260519000000_define_global_cli_output_contract.md:8` lists `src/bin/` as a related artifact and now under-describes the binary landscape. | Correct the five live references to `packages/e2e-tools/src/bin/`. Extend the ADR's related-artifacts list rather than rewriting the decision. Leave `docs/issues/closed/` untouched: those are immutable historical records. #2179 names this drift out of its own scope and worth its own issue. | S | -| F5 | Test health | `contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 1 on `develop` for two independent reasons. First, `PROJECT_ROOT` at line 13 climbs three levels from `contrib/dev-tools/checks/tests/` and lands on `/contrib`, so every fixture copy reads `/contrib/contrib/dev-tools/...` and fails; the sibling suite at `contrib/dev-tools/git/tests/test-merge-pull-request.sh:6` climbs four from an equally deep directory and is correct. Commit `ffa2aa2c5` introduced the wrong depth when it moved the suite beside its sensor. Second, with the depth corrected the suite still fails: `create_fixture` (lines 21-28) never provisions `contrib/dev-tools/checks/lint-containerfile.sh`, so pre-commit step 5 of 6 reports `No such file or directory`, `commands.log` holds 3 entries where line 205 asserts 4, and the success banner asserted at line 206 is never printed. | Correct the `PROJECT_ROOT` depth to four levels, and provision the Containerfile lint sensor in the fixture with a stub that keeps the suite hermetic and free of any container runtime. Re-check the `commands.log` count assertion against whichever stub is chosen. | S | -| F6 | Code readability | `contrib/dev-tools/analysis/workspace-coupling/src/main.rs:191` writes an explicit generic argument naming Rust's character type — the five-character token spelled angle bracket, c-h-a-r, angle bracket. It is the only occurrence in the tracked tree. Chat and review transport layers substitute that token with a role or account name, so the line cannot be quoted in a review discussion without arriving as text that would not compile, which makes a reviewer reasonably distrust the quoted artifact. | Take the character by value — `fn is_rust_identifier_char(ch: char) -> bool` — and move the optionality to the two call sites at line 187, which already hold values from `chars().next_back()` and `chars().next()` and can use `is_some_and`. Behaviour is unchanged: an absent adjacent character still reads as "not an identifier character". Where a token-free signature is genuinely impossible, a local type alias or inference through `collect()` serves the same purpose. | XS | -| F7 | Dead comment | `contrib/dev-tools/checks/lint-containerfile.sh:4` reads `Tests: (no automated tests yet — EPIC #2003)`. Once F5 and F1 land, the fixture for that sensor exists and is exercised, so the note becomes untrue in the same pull request that makes it so. | Update the note to point at the fixture that covers the sensor, or delete it. Handle it in the same commit as F1 so the tree is never internally inconsistent. | XS | -| F8 | Documentation drift | `docs/issues/open/2150-add-lychee-link-checker/ISSUE.md:93` records the decision not to add a `.lycheeignore` file, and `project-words.txt:306` still carries `lycheeignore` as a dictionary entry. The file does not exist and by that decision never will. | Confirm no remaining prose needs the word, then drop the dictionary entry. Keep it if the closed specification's own text still requires it — the dictionary serves the documents, not the other way round. | XS | - -## Maintainer Actions - -These two items cannot be performed from a pull request. They are recorded here so they are visible and so the pull request does not silently leave them undone. - -| ID | Item | Evidence | Action owner and change | -| --- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| A1 | Allowed-actions allowlist pins an exact patch | `gh api repos/torrust/torrust-tracker/actions/permissions/selected-actions` returns `taiki-e/install-action@v2.87.2` among `patterns_allowed`. Three workflows use that action (`.github/workflows/testing.yaml:80`, `coverage.yaml:51`, `generate_coverage_pr.yaml:46`), so no Dependabot bump of it can run. On PR #2180 (`2.87.2` to `2.87.6`, head `a90c3bb1`), `gh api "…/actions/runs?head_sha=a90c3bb1…"` shows `Testing` (push), `Testing` (pull_request), and `Generate Coverage Report (PR)` all `startup_failure`, while `gh pr checks 2180` lists 18 rows that are all `pass` or `skipping` — the failures are invisible in the ordinary check view. The repository's own skill already prescribes the fix at `.github/skills/dev/maintenance/update-github-workflow-actions/SKILL.md:49`. | Repository administrator: change the allowlist entry to `taiki-e/install-action@v2.*`, as that skill directs. No file in this repository changes. Note that the permissions endpoint is readable with ordinary access, so the current value can be confirmed before and after. | -| A2 | Two Dependabot pull requests stalled since August | #2055 (`base64` 0.22.1 to 0.23.1, opened 2026-08-07) and #2106 (`syn` 2.0.119 to 3.0.4, opened 2026-08-27). `gh api repos/torrust/torrust-tracker/compare/...develop` puts `develop` 263 and 137 commits ahead respectively; both report `mergeStateStatus: UNSTABLE`, and on each the only failing check is `Docker E2E` — the symptom #2179 diagnoses and fixes. | Maintainer: after #2179 merges, rebase both and re-run, or close them if the major-version bumps are unwanted on their own merits. This issue does not touch either branch and does not duplicate #2179's fix. | - -## Related but Separate - -`Configuration::load` runs the strict Figment extract at `packages/configuration/src/v3_0_0/mod.rs:392` before checking `metadata.schema_version` at line 395. Because every configuration section carries `#[serde(deny_unknown_fields)]`, a version-2 configuration file fails on the first section name the version-3 schema does not know — reported as an unknown-field error naming `tracker` — instead of the `Error::UnsupportedVersion` that exists precisely to explain this case. The user sees a spelling complaint where the real problem is that the file is a schema version behind. - -This is a behavioural change to a user-facing error path, not a maintenance clean-up: it needs its own acceptance criteria, its own regression test, and a decision about whether the version probe reads the metadata section separately or whether the extract is relaxed. It is recorded here because it was found while verifying this batch, and it is recommended for its own issue rather than folded into this one. - -## Dropped Candidates - -Two items proposed for this batch did not reproduce and are recorded so the ground is not re-covered. - -| Candidate | Finding | -| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Broken or redirected local links | `linter lychee` exits 0 on `develop` with `All local Markdown links passed checking!` in 0.137 s. Local link health is already enforced by `.github/workflows/docs-lint.yaml:60`. External links are wholly owned by #2185, whose specification is under review in #2186. Nothing is left for this issue. The `.lycheeignore` file named in the original report does not exist and, per #2150, will not: the configuration lives in `lychee.toml` and `.github/lychee-online.toml`. | -| A second never-run merge-tool suite, `test-github-merge-symlinks.py` | No such file exists on `develop`. `contrib/dev-tools/git/tests/` contains only `test-merge-pull-request.sh`. The Python suite belongs to the unmerged symlink-exceptions work for #2175 and will arrive with it; F1 covers the suites that exist today. | - -## Architectural Decisions - -No architectural decision is expected. Every item is a mechanical correction to an existing decision's implementation, or the recording of an action outside this repository. - -- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` (F4 touches only its related-artifacts list, not the decision) -- ADRs to create: `None known` - -If F1's CI placement turns into a real choice about where developer-tool tests belong rather than a one-step addition, stop and raise it against EPIC #2003 rather than settling it inside a clean-up pull request. - -## Design and Ownership Review - -`Not applicable`. No item involves child processes, asynchronous I/O, network readiness, resource cleanup, or reusable test fixtures beyond the existing shell fixture repaired in F5, which creates and removes its own temporary directory under an `EXIT` trap that already works. - -## Implementation Plan - -Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. - -| ID | Status | Task | Notes / Expected Output | -| --- | ------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| T1 | TODO | Repair the dictionary-formatter test suite (F5) | `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 0 from a clean checkout; both defects fixed; no container runtime required. | -| T2 | TODO | Run the three developer-tool suites in CI (F1, F7) | One CI step invokes all three suites and fails the workflow when any fails; the "not automatically run" notes and the dead `Tests:` note are removed or corrected in the same change. | -| T3 | TODO | Narrow the container workflow trigger (F3) | `container.yaml:16` reads `releases/v*`; a push to a `releases/pkg/**` branch no longer starts the workflow. | -| T4 | TODO | Correct the stale binary-path references (F4) | The five live references name `packages/e2e-tools/src/bin/`; the ADR's related-artifacts list is extended; `docs/issues/closed/` is untouched. | -| T5 | TODO | Remove the unquotable explicit generic (F6) | The tracked tree contains no occurrence of the token; `cargo clippy` and the tool's own behaviour are unchanged. | -| T6 | TODO | Archive the sixteen closed issue specifications (F2) | The sixteen directories are under `docs/issues/closed/`; `linter lychee` still exits 0 after the move. | -| T7 | TODO | Retire the stale dictionary entry (F8) | `linter cspell` exits 0 with the entry removed, or the entry is kept with a one-line justification in the progress log. | -| T8 | TODO | Record the maintainer actions (A1, A2) | A1 and A2 are stated in the issue body so a maintainer can act; neither is attempted from the pull request. | -| T9 | TODO | Final verification and acceptance review | `linter all` exits 0, the pre-commit checks pass, manual scenarios are recorded, and every acceptance criterion is re-reviewed against observed behaviour. | - -## Commit Points - -| Task | Coherent change set | Commit policy | -| ---- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | -| T1 | The two defects in the dictionary-formatter suite, with the suite green. | Commit once the suite exits 0 from a clean checkout. This lands first: T2 must not wire a red suite into CI. | -| T2 | The CI step plus the two now-untrue script notes. | Commit after the step is validated against the real workflow file. Depends on T1. | -| T3 | The one-line trigger narrowing. | Commit on its own after workflow validation. | -| T4 | The five documentation and skill references plus the ADR artifact list. | Commit on its own; documentation-only and independently revertible. | -| T5 | The signature change and its two call sites. | Commit on its own after focused validation of the tool's output. | -| T6 | The sixteen directory moves and any reference repairs they force. | Commit on its own. It is a large diff of pure moves; mixing it with anything else would bury the other changes. | -| T7 | The dictionary entry. | Fold into T4 if it turns out to be a one-word edit; commit separately if the word survives and the decision needs its own message. | -| T8 | No repository change. | Record in the progress log as a justified no-change decision; do not create an empty commit. | -| T9 | Completion evidence. | Keep separate from the fixes so the verification record is reviewable on its own. | - -Use a Conventional Commit message with the narrow affected scope, and sign every commit with GPG. - -## Progress Tracking - -### Workflow Checkpoints - -- [x] Folder-style spec drafted and moved to `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` -- [x] Spec reviewed and approved by user/maintainer -- [x] GitHub issue [#2190](https://github.com/torrust/torrust-tracker/issues/2190) created and issue number added to this spec -- [ ] (Optional, recommended for complex issues) Spec-only PR merged into `develop` before implementation -- [ ] Implementation completed -- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) -- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` -- [ ] Acceptance criteria reviewed after implementation and updated with evidence -- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed -- [ ] Reviewer validated acceptance criteria and updated checkboxes -- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification -- [ ] Committer verified spec progress is up to date before commit -- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` - -### Progress Log - -- 2026-09-09 14:11 UTC - Specification author - Drafted from a re-verification of every candidate friction against `develop` at `f6b73e29`; eight in-scope items, two maintainer actions, one related-but-separate behavioural defect, two dropped candidates - evidence recorded inline in the Friction Inventory, Maintainer Actions, and Dropped Candidates tables -- 2026-09-09 15:39 UTC - Specification author - GitHub issue #2190 created from the reviewed draft; specification moved to `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` - https://github.com/torrust/torrust-tracker/issues/2190 - -## Acceptance Criteria - -- [ ] AC1: Each of F1 through F8 is either fixed in this issue's pull request, or explicitly deferred with a linked issue recorded in the progress log. No item is left silently undone. -- [ ] AC2: `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 0 from a clean checkout, on a host with no container runtime available. -- [ ] AC3: All three developer-tool suites run in CI, and a deliberately broken suite fails the workflow. No script in `contrib/dev-tools/` still claims its tests are not automatically run when they are. -- [ ] AC4: A push to a branch matching `releases/pkg/**` starts no run of the container workflow. -- [ ] AC5: No live document, skill, or workflow places `e2e_tests_runner`, `profiling`, or `qbittorrent_e2e_runner` under `src/bin/`. Records under `docs/issues/closed/` are unchanged. -- [ ] AC6: `docs/issues/open/` contains a specification directory only for issues GitHub reports as `OPEN`, verified issue by issue at merge time. -- [ ] AC7: The tracked tree contains no occurrence of the explicit character-type generic described in F6, and `contrib/dev-tools/analysis/workspace-coupling` produces the same output as before the change. -- [ ] AC8: The issue body states maintainer actions A1 and A2 clearly enough for a maintainer to act without re-deriving the evidence. -- [ ] `linter all` exits with code `0` -- [ ] Relevant tests pass -- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` -- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior -- [ ] Documentation is updated when behavior/workflow changes - -## Verification Plan - -### Automatic Checks - -- `linter all` -- `bash contrib/dev-tools/git/hooks/pre-commit.sh` -- The three developer-tool suites, individually and through the new CI step -- `linter lychee`, specifically after the F2 archival moves, to catch references the moves break - -### Manual Verification Scenarios - -Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. - -| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | -| --- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------ | -------------------------------------------- | -| M1 | Repaired suite passes from a clean checkout | Clone the branch into a fresh directory on a host with no container runtime, then run `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` and echo `$?` | Exit code 0 and the line `All formatter and pre-commit hook tests passed.` | TODO | `manual-verification-evidence.md` section V1 | -| M2 | The new CI step actually catches a failure | On a scratch branch, break one assertion in one suite, push, and read the workflow run | The workflow fails and names the broken suite. Revert the scratch branch afterwards | TODO | `manual-verification-evidence.md` section V2 | -| M3 | Package release branches stay quiet | Push a throwaway branch named `releases/pkg/scratch/v0.0.1`, then list workflow runs for its head with `gh api "…/actions/runs?head_sha="`, then delete the branch | No `Container` run appears. Before the fix, one appears and exits 0 at the semver guard | TODO | `manual-verification-evidence.md` section V3 | -| M4 | Corrected paths point at real files | For each reference changed in F4, read the file at the path it now names | Every path exists. `docs/profiling.md` still describes a runnable profiling flow | TODO | `manual-verification-evidence.md` section V4 | -| M5 | The workspace-coupling tool is unchanged | Run the tool on `develop` and on the branch, and compare the two reports | The reports are identical apart from any embedded timestamp | TODO | `manual-verification-evidence.md` section V5 | -| M6 | Archived specifications are all closed | For every directory left in `docs/issues/open/`, run `gh issue view --json state` | Every remaining directory maps to an `OPEN` issue, and every moved one to a `CLOSED` issue | TODO | `manual-verification-evidence.md` section V6 | - -Notes: - -- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. -- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. -- M3 requires pushing and deleting a branch in a repository whose workflows react to `releases/**`. Run it on a fork unless a maintainer agrees otherwise, and record which repository was used. -- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. - -### Disposable Verification Scripts - -None is planned. Every scenario above is a direct human-oriented invocation of tooling that already exists, and F5's repair makes the one relevant fixture a maintained suite rather than a throwaway. If implementation nonetheless calls for a temporary script, record its issue-local path, why a maintained Rust automatic test is unsuitable for that specific scenario, its removal or retention owner, and — if written in Python — why Rust does not suit that script, before creating it. - -### Acceptance Verification - -| AC ID | Status (`TODO`/`DONE`) | Evidence | -| ----- | ---------------------- | ------------------ | -| AC1 | TODO | {PR link} | -| AC2 | TODO | M1 | -| AC3 | TODO | M2 | -| AC4 | TODO | M3 | -| AC5 | TODO | M4 | -| AC6 | TODO | M6 | -| AC7 | TODO | M5 | -| AC8 | TODO | {issue body link} | - -## Risks and Trade-offs - -- Batching unrelated fixes can hide a bad one inside a large diff. Mitigation: one commit per friction, in the order set by [Commit Points](#commit-points), so a reviewer can reject a single item without unpicking the rest. F2's sixteen directory moves stay in their own commit for the same reason. -- The F2 archival is a snapshot. Issues close while the pull request is open, so the list can be stale by the time it merges. Mitigation: AC6 re-verifies every remaining directory against GitHub at merge time rather than trusting the list drafted here. -- Wiring the three suites into CI makes a previously invisible failure blocking. That is the point of F1, but it means F5 must land first, and it means a future breakage in those suites will stop a merge. Mitigation: the suites are fast and hermetic, and the CI step is a separate lightweight job so a failure is easy to read and does not consume the test matrix. -- Fixing F6 by changing a function signature touches behaviour-adjacent code in a clean-up pull request. Mitigation: M5 compares the tool's output before and after; if the comparison is anything but identical, defer the item to its own issue. -- F1's placement could turn out to be a design question about the check harness rather than a one-step addition. Mitigation: the stop condition is written into [Architectural Decisions](#architectural-decisions) — raise it against EPIC #2003 rather than deciding it here. - -## Implementation Completion Review - -After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. - -- Retrospective: `Not yet assessed` -- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if any friction turns out to be larger than its recorded size, if F1's CI placement becomes a design decision, or if the F6 output comparison is not identical. -- If none of those occurs, add a concise progress-log entry explaining why the work had no material discovery. -- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. - -## References - -- Related issues: #1774 (archival automation), #2003 (guardrails and automation EPIC), #2159 (folder-style spec adoption), #2179 (Docker E2E package flag), #2185 (external-link triage) -- Related PRs: #2055, #2106, #2180, #2186 -- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` From 5331f58fc5ce930e1f081cbac2a28a959243856b Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 10:43:47 +0200 Subject: [PATCH 04/13] docs(issues): draft the subissue specifications for EPIC #2190 Add one folder-style draft specification per cluster item: two adopted by EPIC #2003, six owned by EPIC #2190, and one standalone issue for the behavioural defect found while verifying the inventory. Each draft is sized for a single focused pull request, names its parent below its title, and carries its own scope, acceptance criteria, and verification plan. --- .../ISSUE.md | 187 ++++++++++++++++++ .../ISSUE.md | 187 ++++++++++++++++++ .../ISSUE.md | 178 +++++++++++++++++ .../ISSUE.md | 185 +++++++++++++++++ .../ISSUE.md | 174 ++++++++++++++++ .../ISSUE.md | 171 ++++++++++++++++ .../ISSUE.md | 172 ++++++++++++++++ .../ISSUE.md | 178 +++++++++++++++++ .../ISSUE.md | 180 +++++++++++++++++ 9 files changed, 1612 insertions(+) create mode 100644 docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md create mode 100644 docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md create mode 100644 docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md create mode 100644 docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md create mode 100644 docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md create mode 100644 docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md create mode 100644 docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md create mode 100644 docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md create mode 100644 docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md diff --git a/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md b/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md new file mode 100644 index 000000000..f16c1c152 --- /dev/null +++ b/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md @@ -0,0 +1,187 @@ +--- +doc-type: issue +issue-type: bug +status: draft +priority: p2 +epic: 2003 +github-issue: null +spec-path: docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - contrib/dev-tools/checks/tests/test-format-project-words.sh + - contrib/dev-tools/checks/format-project-words.sh + - contrib/dev-tools/checks/lint-containerfile.sh + - contrib/dev-tools/git/tests/test-merge-pull-request.sh + - contrib/dev-tools/git/hooks/pre-commit.sh + - docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Repair the project dictionary formatter test suite + +**Parent EPIC:** #2003 - Overhaul: Automation Tools and AI Agent Guardrails + +## Goal + +Make `contrib/dev-tools/checks/tests/test-format-project-words.sh` exit 0 from a clean checkout on a host with no container runtime, so the suite can be trusted and, in a following subissue, invoked automatically. + +## Background + +The suite has been red on `develop` since commit `ffa2aa2c5` moved it beside its sensor. It fails for two independent reasons, verified at revision `f6b73e29` on 2026-09-09. + +First, `PROJECT_ROOT` at line 13 climbs three directory levels from `contrib/dev-tools/checks/tests/` and lands on `/contrib`, so every fixture copy reads `/contrib/contrib/dev-tools/...` and fails. The sibling suite at `contrib/dev-tools/git/tests/test-merge-pull-request.sh:6` climbs four levels from an equally deep directory and is correct, which is the reference for the right depth. + +Second, with the depth corrected the suite still fails. `create_fixture` at lines 21-28 never provisions `contrib/dev-tools/checks/lint-containerfile.sh`, so pre-commit step 5 of 6 reports `No such file or directory`, `commands.log` holds three entries where line 205 asserts four, and the success banner asserted at line 206 is never printed. + +Nobody has noticed because no orchestrator runs the suite. That gap is the sibling subissue; this one makes the suite worth running. + +## Scope + +### In Scope + +- Correct the `PROJECT_ROOT` depth so the fixture resolves against the repository root. +- Provision the Containerfile lint sensor in the fixture with a stub that keeps the suite hermetic and free of any container runtime. +- Re-check the `commands.log` count assertion and the success-banner assertion against whichever stub is chosen. +- Leave the suite runnable by a developer with a single `bash` invocation and no environment setup. + +### Out of Scope + +- Invoking this suite, or its two siblings, from CI or a git hook. That is the sibling subissue under this EPIC. +- Changing the behaviour of `contrib/dev-tools/checks/format-project-words.sh` itself. +- Redesigning the fixture, the pre-commit step list, or the check-harness architecture. Those belong to this EPIC's design decision. +- Adding a real Containerfile lint to the fixture, which would reintroduce a container-runtime dependency. + +## Architectural Decisions + +No architectural decision is expected. Both defects are mechanical: a wrong path depth and a fixture that does not provision one file the code under test invokes. The stub choice is a test-fixture detail, not an architecture decision; if it turns into a question about what the fixture is allowed to simulate, stop and raise it against this EPIC. + +- Related ADRs: `None` +- ADRs to create: `None known` + +## Design and Ownership Review + +The suite creates and removes its own temporary directory under an `EXIT` trap that already works, so no new resource-ownership question arises. The one ownership point to preserve is that the stub sensor lives inside the fixture directory and is removed with it, never written into the working tree. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | TODO | Correct the fixture root resolution | `PROJECT_ROOT` climbs four levels; a debug echo of the copied paths shows `/contrib/dev-tools/...` rather than a doubled `contrib`. | +| T2 | TODO | Provision the Containerfile lint sensor in the fixture | Pre-commit step 5 of 6 runs against a stub; no `No such file or directory` appears in the run output. | +| T3 | TODO | Reconcile the log-count and banner assertions | `commands.log` count and the success banner assertion match what the corrected fixture actually produces. | +| T4 | TODO | Final verification and acceptance review | `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 0 from a clean checkout; `linter all` exits 0; every acceptance criterion re-reviewed against observed behaviour. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T1 | The `PROJECT_ROOT` depth correction. | Commit on its own. It is the smallest independently reviewable step and it changes the failure mode visibly. | +| T2, T3 | The fixture stub plus the assertions it forces. | Commit together once the suite exits 0. The assertions are only correct in the presence of the stub, so splitting them would commit a red tree. | +| T4 | Completion evidence. | Keep separate from the fix so the verification record is reviewable on its own. | + +Record a justified no-change decision in the task's evidence without creating an empty commit. Use a Conventional Commit message with the narrow affected scope. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created, linked as a subissue of the parent EPIC, and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C1, friction F5 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 0 from a clean checkout, on a host with no container runtime available. +- [ ] AC2: The suite prints its success banner, and the assertion that checks it is exercised rather than skipped. +- [ ] AC3: A deliberately broken assertion in the suite makes it exit non-zero, so the pass is not vacuous. +- [ ] AC4: The sibling suite `contrib/dev-tools/git/tests/test-merge-pull-request.sh` is unchanged and still passes. +- [ ] AC5: No file outside `contrib/dev-tools/checks/` changes. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all` +- `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` +- `bash contrib/dev-tools/git/tests/test-merge-pull-request.sh` +- `bash contrib/dev-tools/git/hooks/pre-commit.sh` + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | Repaired suite passes from a clean checkout | Clone the branch into a fresh directory on a host with no container runtime, then run `bash contrib/dev-tools/checks/tests/test-format-project-words.sh` and echo `$?` | Exit code 0 and the line `All formatter and pre-commit hook tests passed.` | TODO | `manual-verification-evidence.md` section V1 | +| M2 | The suite is not vacuously green | Change one assertion in the suite to an expectation the fixture cannot satisfy, run it, then revert the change | The suite exits non-zero and names the failed assertion | TODO | `manual-verification-evidence.md` section V2 | +| M3 | No container runtime is reached | Run the suite on a host where no container runtime is installed and read the full output | No step attempts to invoke a container runtime, and no step is silently skipped | TODO | `manual-verification-evidence.md` section V3 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Disposable Verification Scripts + +None is planned. Every scenario is a direct invocation of the suite under repair. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M1 | +| AC2 | TODO | M1 | +| AC3 | TODO | M2 | +| AC4 | TODO | Automatic checks | +| AC5 | TODO | {PR link} | + +## Risks and Trade-offs + +- A stub can make the suite pass while hiding a real integration defect in the Containerfile lint sensor. Mitigation: the stub records its invocation in `commands.log`, so the suite still proves the step was reached, and M3 confirms nothing is skipped. +- Correcting the depth may expose further assertions that were never reached. Mitigation: T3 reconciles the assertions against observed output rather than against the values written before the suite was moved. +- Repairing a suite that nothing runs leaves it free to rot again. Mitigation: the sibling subissue wires it into CI, and it depends on this one. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if either defect turns out to be larger than a fixture correction, or the stub choice raises a question about what the fixture may simulate. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2003 (parent EPIC), #2190 (source inventory), #2019 (the interim dictionary formatter this suite covers) +- Related PRs: #2193 (the EPIC specification that produced this draft) +- Related ADRs: `None` diff --git a/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md b/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md new file mode 100644 index 000000000..5de16a5fb --- /dev/null +++ b/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md @@ -0,0 +1,187 @@ +--- +doc-type: issue +issue-type: enhancement +status: draft +priority: p2 +epic: 2003 +github-issue: null +spec-path: docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - .github/workflows/testing.yaml + - contrib/dev-tools/git/tests/test-merge-pull-request.sh + - contrib/dev-tools/checks/tests/test-format-project-words.sh + - contrib/dev-tools/checks/tests/test-agent-review-report-contract.sh + - contrib/dev-tools/checks/format-project-words.sh + - contrib/dev-tools/checks/lint-containerfile.sh + - contrib/dev-tools/git/hooks/pre-commit.sh + - docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Run the developer-tool test suites in CI + +**Parent EPIC:** #2003 - Overhaul: Automation Tools and AI Agent Guardrails + +## Goal + +Have one lightweight CI step run the three existing developer-tool test suites and fail the workflow when any of them fails, and remove the notes in the tree that will then be untrue. + +## Background + +Three developer-tool test suites exist and no orchestrator runs any of them, verified at revision `f6b73e29` on 2026-09-09: `contrib/dev-tools/git/tests/test-merge-pull-request.sh`, `contrib/dev-tools/checks/tests/test-format-project-words.sh`, and `contrib/dev-tools/checks/tests/test-agent-review-report-contract.sh`. Searching the workflows for `contrib/dev-tools` returns only the container persistence test and the hook installer, and none of the suites appears in a `STEPS` entry of `contrib/dev-tools/git/hooks/pre-commit.sh` (lines 51-58) or `pre-push.sh`. + +Two scripts state the gap themselves, at `contrib/dev-tools/checks/tests/test-format-project-words.sh:6` and `contrib/dev-tools/checks/format-project-words.sh:6`. A third note, at `contrib/dev-tools/checks/lint-containerfile.sh:4`, records that the sensor has no automated tests yet and names this EPIC. That note stops being true in the same change that makes it so, because the sibling subissue provisions the sensor in the formatter suite's fixture and this subissue runs that fixture in CI. + +The three suites together complete in roughly one second on a warm host, so the cost of running them is negligible next to the cost of a suite silently rotting. + +## Scope + +### In Scope + +- Add one lightweight CI step that runs the three suites and fails the workflow when any of them fails. +- Keep that step outside the expensive test matrix, so a failure is easy to read and does not consume matrix capacity. +- Delete the two notes that claim the tests are not automatically run, once they are. +- Correct or delete the dead note at `contrib/dev-tools/checks/lint-containerfile.sh:4`, in the same change, so the tree is never internally inconsistent. + +### Out of Scope + +- Repairing the formatter suite. That is the sibling subissue under this EPIC, and it must merge first. +- Selecting the long-term check-harness shape, runner, cache, or execution tier. Those belong to this EPIC's architecture decision, and this step remains replaceable by it. +- Adding the suites to a git hook, which would change local commit latency without evidence. +- Writing new suites for sensors that have none. + +## Architectural Decisions + +No architectural decision is expected. The step adds one invocation of checks that already exist and selects no runner, cache, or enforcement platform, which is why this work qualifies under the parent EPIC's exception for additive, independently verifiable subissues that may proceed before its architecture decision. + +- Related ADRs: `None` +- ADRs to create: `None known` + +## Design and Ownership Review + +If the CI placement turns out to be a real choice about where developer-tool tests belong rather than a one-step addition, stop and raise it against the parent EPIC rather than settling it here. That stop condition is the reason this subissue sits under EPIC #2003 rather than in a clean-up issue. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | BLOCKED | Wait for the formatter suite repair to merge | The sibling subissue is merged and the formatter suite exits 0 on `develop`. This step must not wire a red suite into CI. | +| T2 | TODO | Add the CI step that runs the three suites | One step invokes all three suites; a locally broken suite makes the step exit non-zero. | +| T3 | TODO | Remove the two now-untrue notes | Neither `test-format-project-words.sh:6` nor `format-project-words.sh:6` still claims the tests are not automatically run. | +| T4 | TODO | Correct the dead note on the Containerfile lint sensor | `lint-containerfile.sh:4` names the fixture that covers the sensor, or the note is gone. | +| T5 | TODO | Final verification and acceptance review | `linter all` exits 0, the CI step is observed failing on a deliberately broken suite, and every acceptance criterion is re-reviewed against observed behaviour. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T2 | The CI step. | Commit on its own after the workflow file is validated. Depends on the sibling subissue being merged. | +| T3, T4 | The three notes. | Commit together with, or immediately after, the step, so no revision of the tree both runs the suites and denies that it does. | +| T5 | Completion evidence. | Keep separate from the change so the verification record is reviewable on its own. | + +Record a justified no-change decision in the task's evidence without creating an empty commit. Use a Conventional Commit message with the narrow affected scope. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created, linked as a subissue of the parent EPIC, and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C2, frictions F1 and F7 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: All three developer-tool suites run in CI on every pull request. +- [ ] AC2: A deliberately broken suite fails the workflow and the failure names the broken suite. +- [ ] AC3: No script in `contrib/dev-tools/` still claims its tests are not automatically run when they are. +- [ ] AC4: The note at `contrib/dev-tools/checks/lint-containerfile.sh:4` is true of the tree it ships in. +- [ ] AC5: The step runs outside the test matrix and adds no measurable time to the matrix jobs. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all` +- The three suites, individually and through the new CI step +- `bash contrib/dev-tools/git/hooks/pre-commit.sh` + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | The new CI step actually catches a failure | On a scratch branch, break one assertion in one suite, push, and read the workflow run | The workflow fails and names the broken suite. Revert the scratch branch afterwards | TODO | `manual-verification-evidence.md` section V1 | +| M2 | The step runs all three suites | Read the run log of the new step on a green build | All three suite names appear in the step output with a passing result each | TODO | `manual-verification-evidence.md` section V2 | +| M3 | No note contradicts the tree | Read the three note lines on the merged revision | Each note describes what the tree actually does | TODO | `manual-verification-evidence.md` section V3 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Disposable Verification Scripts + +None is planned. Every scenario reads a real workflow run or a file in the tree. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M2 | +| AC2 | TODO | M1 | +| AC3 | TODO | M3 | +| AC4 | TODO | M3 | +| AC5 | TODO | M2 | + +## Risks and Trade-offs + +- Wiring previously invisible failures into a blocking check makes a future breakage stop a merge. That is the point, but it is a real cost. Mitigation: the suites are fast and hermetic, and the step is separate and lightweight, so a failure is cheap to read and cheap to fix. +- The step could be superseded by this EPIC's later harness design. Mitigation: it is one workflow step invoking existing scripts, with no shared runner or cache to unpick. +- Merging before the formatter suite repair would make CI red on `develop`. Mitigation: T1 is a blocking dependency, stated as such in the implementation plan. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if the CI placement becomes a design decision rather than a one-step addition, or a suite proves unstable once it actually runs. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2003 (parent EPIC), #2190 (source inventory) +- Related PRs: #2193 (the EPIC specification that produced this draft) +- Related ADRs: `None` diff --git a/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md b/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md new file mode 100644 index 000000000..eebfb10f7 --- /dev/null +++ b/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md @@ -0,0 +1,178 @@ +--- +doc-type: issue +issue-type: task +status: draft +priority: p3 +epic: 2190 +github-issue: null +spec-path: docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + - cleanup-completed-issues + related-artifacts: + - .github/skills/dev/planning/cleanup-completed-issues/SKILL.md + - .github/skills/dev/planning/create-issue/SKILL.md + - docs/issues/open/README.md + - docs/issues/closed/README.md + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Archive the issue specifications of closed issues + +**Parent EPIC:** #2190 - Repository maintenance frictions clean-up + +## Goal + +Leave `docs/issues/open/` containing a specification directory only for issues GitHub reports as open, so the directory listing is a usable picture of the active backlog. + +## Background + +Verified at revision `f6b73e29` on 2026-09-09 by checking every directory in `docs/issues/open/` against GitHub. Sixteen specification directories belong to issues GitHub reports as closed: 1586, 1588, 2121, 2122, 2130, 2132, 2134, 2136, 2138, 2140, 2150, 2151, 2155, 2156, 2160, and 2162. + +The archival rule is stated in `docs/issues/closed/README.md` and the procedure in the `cleanup-completed-issues` skill; both are already correct. What is missing is a pass that applies them. Until it is applied, anyone reading the open backlog by listing the directory over-counts it by sixteen, and an agent choosing work from that listing can pick something already delivered. + +Automating this flow is #1774, which is paused behind EPIC #2003's architecture decision. This subissue does the current pass by hand and constrains nothing in that script's design. + +## Scope + +### In Scope + +- Re-verify every directory under `docs/issues/open/` against GitHub at implementation time, rather than trusting the list above. +- Move each directory whose issue is closed into `docs/issues/closed/`, following the `cleanup-completed-issues` skill. +- Repair the live references the moves break. + +### Out of Scope + +- Automating the archival flow. That is #1774. +- Stage-two deletion of old specifications from `docs/issues/closed/`. +- Migrating legacy single-file specifications to the folder-style layout. That is #2159. +- Editing the content of any moved specification beyond the reference repairs the move forces. + +## Architectural Decisions + +No architectural decision is expected. The lifecycle rule and the procedure both already exist; this applies them. + +- Related ADRs: `None` +- ADRs to create: `None known` + +## Design and Ownership Review + +`Not applicable`. Directory moves and reference repairs only. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | TODO | Re-verify the state of every open specification directory | Each directory under `docs/issues/open/` is checked against GitHub and recorded as open or closed, with the check output kept as evidence. | +| T2 | TODO | Move the closed specifications | Every directory whose issue is closed is under `docs/issues/closed/`; no directory whose issue is open moved. | +| T3 | TODO | Repair references the moves break | `linter lychee` exits 0 after the moves. | +| T4 | TODO | Final verification and acceptance review | `linter all` exits 0 and every acceptance criterion is re-reviewed against observed behaviour. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T2 | The directory moves. | Commit on their own. This is a large diff of pure moves; mixing anything else into it would bury the other change. | +| T3 | The reference repairs. | Commit separately so the moves stay reviewable as moves. | +| T4 | Completion evidence. | Keep separate from the moves so the verification record is reviewable on its own. | + +Record a justified no-change decision in the task's evidence without creating an empty commit. Use a Conventional Commit message with the narrow affected scope. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created, linked as a subissue of the parent EPIC, and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C5, friction F2 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: `docs/issues/open/` contains a specification directory only for issues GitHub reports as open, verified issue by issue at merge time. +- [ ] AC2: Every moved directory maps to an issue GitHub reports as closed. +- [ ] AC3: `linter lychee` exits 0 after the moves. +- [ ] AC4: No moved specification's content changed beyond the reference repairs the move forced. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all` +- `linter lychee`, specifically after the moves, to catch references they break + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | Every remaining directory is an open issue | For every directory left in `docs/issues/open/`, query its issue state on GitHub | Every remaining directory maps to an open issue | TODO | `manual-verification-evidence.md` section V1 | +| M2 | Every moved directory is a closed issue | For every directory moved into `docs/issues/closed/`, query its issue state on GitHub | Every moved directory maps to a closed issue | TODO | `manual-verification-evidence.md` section V2 | +| M3 | The re-verification is repeated at merge time | Repeat the first two scenarios on the merge commit rather than on the branch head | The two lists still hold; any issue that closed while the pull request was open is either included or explicitly deferred | TODO | `manual-verification-evidence.md` section V3 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Disposable Verification Scripts + +A throwaway loop over the directory listing that queries each issue's state is acceptable here, because the scenario is a bulk state query rather than product behaviour and a maintained Rust test would have to reach GitHub to be meaningful. If one is written, keep it in this specification's directory, record what it verifies and who removes it, and prefer the repository's existing tooling over a new script. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M1 and M3 | +| AC2 | TODO | M2 | +| AC3 | TODO | Automatic checks | +| AC4 | TODO | {PR link} | + +## Risks and Trade-offs + +- The list is a snapshot: issues close while the pull request is open, so it can be stale by the time it merges. Mitigation: M3 re-verifies at merge time rather than trusting the list drafted here. +- Moving sixteen directories can break inbound links that the link checker does not reach. Mitigation: `linter lychee` runs after the moves, and the reference repairs are a separate reviewable commit. +- A large move diff can hide an accidental content edit. Mitigation: the moves are committed alone, so the diff is reviewable as renames. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if the moves break references the link checker did not catch, or the re-verification disagrees materially with the drafted list. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2190 (parent EPIC), #1774 (archival automation), #2159 (folder-style spec adoption) +- Related PRs: #2193 (the EPIC specification that produced this draft) +- Related ADRs: `None` diff --git a/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md b/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md new file mode 100644 index 000000000..3011d192e --- /dev/null +++ b/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md @@ -0,0 +1,185 @@ +--- +doc-type: issue +issue-type: task +status: draft +priority: p3 +epic: 2190 +github-issue: null +spec-path: docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - AGENTS.md + - .github/skills/dev/testing/manual-http-download-completion-e2e/SKILL.md + - .github/skills/dev/testing/manual-udp-download-completion-e2e/SKILL.md + - docs/profiling.md + - docs/adrs/20260519000000_define_global_cli_output_contract.md + - project-words.txt + - docs/issues/open/2150-add-lychee-link-checker/ISSUE.md + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Correct stale documentation references left by completed moves and decisions + +**Parent EPIC:** #2190 - Repository maintenance frictions clean-up + +## Goal + +Leave no live document naming a binary at a path it no longer occupies, and no dictionary entry for a file the project decided never to create. + +## Background + +Two stale references share one shape: each names a referent that does not exist. Both were verified at revision `f6b73e29` on 2026-09-09. + +`src/bin/` now contains only `http_health_check.rs`. The `e2e_tests_runner`, `profiling`, and `qbittorrent_e2e_runner` binaries moved to `packages/e2e-tools/src/bin/` in commit `c47173f53`, and five live references were never updated: `AGENTS.md:39`, `.github/skills/dev/testing/manual-http-download-completion-e2e/SKILL.md:21` and `:307`, `.github/skills/dev/testing/manual-udp-download-completion-e2e/SKILL.md:207`, and `docs/profiling.md:10`. Separately, `docs/adrs/20260519000000_define_global_cli_output_contract.md:8` lists `src/bin/` as a related artifact and now under-describes the binary landscape. + +`docs/issues/open/2150-add-lychee-link-checker/ISSUE.md:93` records the decision not to add a `.lycheeignore` file, and `project-words.txt:306` still carries the corresponding dictionary entry. The file does not exist and, by that decision, never will. + +The cost of each is small and identical: a reader follows a path that is not there, or a dictionary entry that documents nothing. + +## Scope + +### In Scope + +- Correct the five live references to name `packages/e2e-tools/src/bin/`. +- Extend the ADR's related-artifacts list so it describes the current binary landscape, without rewriting the decision. +- Confirm no remaining prose needs the stale dictionary word, then drop the entry. + +### Out of Scope + +- Changing anything under `docs/issues/closed/`. Those are immutable historical records. +- Rewriting the decision recorded in the ADR. +- A general audit of the project dictionary, or of documentation paths beyond the ones listed above. +- Revisiting the decision in #2150 not to create the ignore file. + +## Architectural Decisions + +No architectural decision is expected. The ADR touched here gains one entry in its related-artifacts list; its decision text is unchanged. + +- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` +- ADRs to create: `None known` + +## Design and Ownership Review + +`Not applicable`. Documentation and dictionary content only. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | TODO | Correct the five stale binary-path references | Each of the five references names `packages/e2e-tools/src/bin/`, and each named path exists in the tree. | +| T2 | TODO | Extend the ADR related-artifacts list | The list names both `src/bin/` and `packages/e2e-tools/src/bin/`; the decision text is unchanged. | +| T3 | TODO | Retire the stale dictionary entry | `linter cspell` exits 0 with the entry removed, or the entry is kept with a one-line justification in the progress log. | +| T4 | TODO | Final verification and acceptance review | `linter all` exits 0 and every acceptance criterion is re-reviewed against observed behaviour. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T1, T2 | The five references and the ADR artifact list. | Commit together. They are one documentation correction and independently revertible as a unit. | +| T3 | The dictionary entry. | Fold into the commit above if it is a one-word edit; commit separately if the word survives and the decision needs its own message. | +| T4 | Completion evidence. | Keep separate when it improves reviewability. | + +Record a justified no-change decision in the task's evidence without creating an empty commit. Use a Conventional Commit message with the narrow affected scope. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created, linked as a subissue of the parent EPIC, and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C4, frictions F4 and F8 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: No live document, skill, or workflow places `e2e_tests_runner`, `profiling`, or `qbittorrent_e2e_runner` under `src/bin/`. +- [ ] AC2: Every path named by a corrected reference exists in the tree. +- [ ] AC3: Records under `docs/issues/closed/` are unchanged. +- [ ] AC4: The ADR's decision text is unchanged and its related-artifacts list describes the current binary landscape. +- [ ] AC5: The stale dictionary entry is gone, or the progress log records why it stays. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all` +- `linter cspell` +- `linter lychee` + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | Corrected paths point at real files | For each reference changed, read the file at the path it now names | Every path exists | TODO | `manual-verification-evidence.md` section V1 | +| M2 | The profiling document still describes a runnable flow | Follow `docs/profiling.md` from its first command | The described flow runs against the binary at its new location | TODO | `manual-verification-evidence.md` section V2 | +| M3 | No prose still needs the retired dictionary word | Search the tracked tree for the word before removing the entry, then run the spell check | The word appears in no live document, and the spell check exits 0 | TODO | `manual-verification-evidence.md` section V3 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Disposable Verification Scripts + +None is planned. Every scenario is a direct read or a spell-check run. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M1 | +| AC2 | TODO | M1 | +| AC3 | TODO | {PR link} | +| AC4 | TODO | {PR link} | +| AC5 | TODO | M3 | + +## Risks and Trade-offs + +- A search-and-replace could reach historical records. Mitigation: the five references are listed individually, and an acceptance criterion asserts that `docs/issues/closed/` is untouched. +- The dictionary word may still be needed by a document not found by a naive search. Mitigation: M3 searches before removing, and the specification allows keeping the entry with a recorded reason. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if the path correction uncovers further live references beyond the five listed, or the profiling flow does not run at the corrected path. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2190 (parent EPIC), #2150 (the decision behind the retired dictionary entry), #2179 (names this drift as out of its own scope) +- Related PRs: #2193 (the EPIC specification that produced this draft) +- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` diff --git a/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md b/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md new file mode 100644 index 000000000..4958830b9 --- /dev/null +++ b/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md @@ -0,0 +1,174 @@ +--- +doc-type: issue +issue-type: bug +status: draft +priority: p3 +epic: 2190 +github-issue: null +spec-path: docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - .github/workflows/container.yaml + - .github/workflows/deployment.yaml + - .github/workflows/deployment-packages.yaml + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Narrow the container workflow release-branch trigger + +**Parent EPIC:** #2190 - Repository maintenance frictions clean-up + +## Goal + +Stop the container workflow from starting on package release branches, so a push to `releases/pkg/**` no longer produces a workflow run that exists only to refuse itself. + +## Background + +Verified at revision `f6b73e29` on 2026-09-09. `.github/workflows/container.yaml:16` triggers pushes on `releases/**/*`, while `.github/workflows/deployment.yaml:15` was narrowed to `releases/v*`. Package release branches match `releases/pkg/**`, per `.github/workflows/deployment-packages.yaml:35`. + +The consequence is that every package release push also starts the container workflow. The workflow extracts `pkg//v` as its version, fails the semver test at `container.yaml:165`, prints `Not a valid release branch semver. Will Not Continue`, and exits 0. The run is wasted, and worse, it trains readers to scroll past container-workflow runs on release branches. + +The narrowing that `deployment.yaml` already received is the same narrowing this workflow needs. + +## Scope + +### In Scope + +- Narrow the push trigger at `.github/workflows/container.yaml:16` to `releases/v*`, matching `deployment.yaml`. +- Keep the semver guard at `container.yaml:165` as the second line of defence. + +### Out of Scope + +- Removing or relaxing the semver guard. +- Changing `deployment.yaml` or `deployment-packages.yaml`. +- Any other trigger, job, or step in the container workflow. +- Reducing the container workflow's runtime, which is EPIC #1840. + +## Architectural Decisions + +No architectural decision is expected. The change aligns one workflow's trigger predicate with the convention another workflow already follows. + +- Related ADRs: `None` +- ADRs to create: `None known` + +## Design and Ownership Review + +`Not applicable`. No child processes, asynchronous I/O, network readiness, resource cleanup, or reusable test fixtures are involved. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | TODO | Narrow the push trigger | `container.yaml:16` reads `releases/v*`; the workflow file validates. | +| T2 | TODO | Verify on a throwaway release-package branch | A push to a branch matching `releases/pkg/**` starts no run of the container workflow. | +| T3 | TODO | Final verification and acceptance review | `linter all` exits 0 and every acceptance criterion is re-reviewed against observed behaviour. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T1 | The one-line trigger narrowing. | Commit on its own after workflow validation. | +| T2, T3 | Verification evidence. | No repository change. Record the observation in `manual-verification-evidence.md` and the progress log. | + +Record a justified no-change decision in the task's evidence without creating an empty commit. Use a Conventional Commit message with the narrow affected scope. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created, linked as a subissue of the parent EPIC, and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C3, friction F3 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: A push to a branch matching `releases/pkg/**` starts no run of the container workflow. +- [ ] AC2: A push to a branch matching `releases/v*` still starts the container workflow and it still publishes as before. +- [ ] AC3: The semver guard at `container.yaml:165` is unchanged. +- [ ] AC4: No file outside `.github/workflows/container.yaml` changes. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all` +- Workflow file validation as part of the repository's existing checks + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | Package release branches stay quiet | Push a throwaway branch named `releases/pkg/scratch/v0.0.1`, then list workflow runs for its head, then delete the branch | No container-workflow run appears. Before the fix, one appears and exits 0 at the semver guard | TODO | `manual-verification-evidence.md` section V1 | +| M2 | Version release branches still build | Push a throwaway branch named `releases/v0.0.1-scratch`, then list workflow runs for its head, then delete the branch | The container workflow starts and reaches its build steps | TODO | `manual-verification-evidence.md` section V2 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +- Both scenarios push and delete a branch in a repository whose workflows react to `releases/**`. Run them on a fork unless a maintainer agrees otherwise, and record which repository was used. + +### Disposable Verification Scripts + +None is planned. Both scenarios are direct pushes and a read of the resulting run list. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M1 | +| AC2 | TODO | M2 | +| AC3 | TODO | {PR link} | +| AC4 | TODO | {PR link} | + +## Risks and Trade-offs + +- Narrowing a trigger can silence a run somebody depends on. Mitigation: M2 confirms that version release branches still build, and the semver guard shows that package branches were never able to produce a release anyway. +- The verification requires pushing branches that match a release pattern. Mitigation: run it on a fork, use an obviously throwaway name, and delete the branch immediately. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if the trigger narrowing turns out to affect a release path that the semver guard was silently protecting. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2190 (parent EPIC), #1840 (container workflow performance, unrelated to this trigger defect) +- Related PRs: #2193 (the EPIC specification that produced this draft) +- Related ADRs: `None` diff --git a/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md b/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md new file mode 100644 index 000000000..6aff40b3c --- /dev/null +++ b/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md @@ -0,0 +1,171 @@ +--- +doc-type: issue +issue-type: task +status: draft +priority: p3 +epic: 2190 +github-issue: null +spec-path: docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - contrib/dev-tools/analysis/workspace-coupling/src/main.rs + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Remove the unquotable character-type generic from the workspace-coupling tool + +**Parent EPIC:** #2190 - Repository maintenance frictions clean-up + +## Goal + +Let every line of the workspace-coupling tool survive being quoted in a review discussion, by removing the one explicit generic argument that chat and review transports rewrite. + +## Background + +Verified at revision `f6b73e29` on 2026-09-09. `contrib/dev-tools/analysis/workspace-coupling/src/main.rs:191` writes an explicit generic argument naming Rust's character type: the five-character token spelled angle bracket, c-h-a-r, angle bracket. It is the only occurrence in the tracked tree. + +Chat and review transport layers substitute that token with a role or account name. A reviewer who quotes the line therefore receives text that would not compile, and correctly distrusts the quoted artifact. The defect is not in what the code does; it is that this one line cannot be discussed in the medium where the repository's code is discussed. + +The proposed remedy takes the character by value and moves the optionality to the call sites, which already hold values from the adjacent-character lookups at line 187 and can express the same intent without the token. + +## Scope + +### In Scope + +- Change `is_rust_identifier_char` to take the character by value. +- Move the optionality to the two call sites at line 187, keeping the existing meaning that an absent adjacent character reads as not an identifier character. +- Leave the tool's output unchanged. + +### Out of Scope + +- Any other change to the workspace-coupling tool's behaviour, output format, or structure. +- A repository-wide rule or automated check banning the token. If one is wanted, it is a separate proposal against EPIC #2003. +- Refactoring the adjacent-character lookups beyond what the signature change requires. + +## Architectural Decisions + +No architectural decision is expected. Where a token-free signature is genuinely impossible in some future case, a local type alias or inference through a collecting call serves the same purpose; that fallback is a coding convention, not an architecture decision. + +- Related ADRs: `None` +- ADRs to create: `None known` + +## Design and Ownership Review + +`Not applicable`. A single synchronous helper function with no ownership or lifetime question beyond taking a copy type by value. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | TODO | Take the character by value and adjust the two call sites | The function signature carries no explicit generic argument; the call sites express the absent-character case explicitly. | +| T2 | TODO | Compare the tool's output before and after | The reports produced on `develop` and on the branch are identical apart from any embedded timestamp. | +| T3 | TODO | Final verification and acceptance review | `linter all` exits 0, Clippy is clean, and every acceptance criterion is re-reviewed against observed behaviour. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T1 | The signature change and its two call sites. | Commit on its own after the output comparison in T2 is clean. | +| T2, T3 | Comparison and completion evidence. | No repository change. Record the comparison in `manual-verification-evidence.md`. | + +Record a justified no-change decision in the task's evidence without creating an empty commit. Use a Conventional Commit message with the narrow affected scope. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created, linked as a subissue of the parent EPIC, and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C6, friction F6 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: The tracked tree contains no occurrence of the explicit character-type generic described above. +- [ ] AC2: `contrib/dev-tools/analysis/workspace-coupling` produces the same report as before the change, apart from any embedded timestamp. +- [ ] AC3: Clippy reports nothing new for the changed file. +- [ ] AC4: No file outside `contrib/dev-tools/analysis/workspace-coupling/` changes. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all` +- Clippy for the workspace-coupling package +- The tool's own run, compared against a run on `develop` + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | The tool is unchanged | Run the tool on `develop` and on the branch, and compare the two reports | The reports are identical apart from any embedded timestamp | TODO | `manual-verification-evidence.md` section V1 | +| M2 | The changed line quotes cleanly | Paste the changed line into a review comment draft and read what arrives | The pasted text is the same text as the file holds | TODO | `manual-verification-evidence.md` section V2 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Disposable Verification Scripts + +None is planned. The comparison is two runs of the tool and a diff of their output. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M2 | +| AC2 | TODO | M1 | +| AC3 | TODO | Automatic checks | +| AC4 | TODO | {PR link} | + +## Risks and Trade-offs + +- Changing a function signature in a clean-up pull request touches behaviour-adjacent code. Mitigation: M1 compares the tool's output before and after; if the comparison is anything but identical, the change is reverted and the item deferred to its own investigation. +- Removing one occurrence does not stop a new one appearing. Mitigation: that is a rule question, explicitly out of scope here, and the tree currently holds exactly one occurrence to remove. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if the output comparison is not identical, or a token-free signature turns out to require more than the two call-site changes. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2190 (parent EPIC) +- Related PRs: #2193 (the EPIC specification that produced this draft) +- Related ADRs: `None` diff --git a/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md b/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md new file mode 100644 index 000000000..02d1422ea --- /dev/null +++ b/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md @@ -0,0 +1,172 @@ +--- +doc-type: issue +issue-type: task +status: draft +priority: p3 +epic: 2190 +github-issue: null +spec-path: docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Resolve the two dependency update pull requests stalled since August + +**Parent EPIC:** #2190 - Repository maintenance frictions clean-up + +## Goal + +Bring the two long-stalled dependency update pull requests to a decision, either merged after a rebase or closed on the merits of the bump, so neither sits indefinitely as an unread failure. + +## Background + +This issue changes no file in this repository. It is a decision about two open pull requests, recorded as an issue so it has an owner and a visible state. + +Verified on 2026-09-09. Pull request #2055 raises `base64` from 0.22.1 to 0.23.1 and was opened on 2026-08-07; #2106 raises `syn` from 2.0.119 to 3.0.4 and was opened on 2026-08-27. Comparing each head against `develop` puts `develop` 263 and 137 commits ahead respectively. Both report an unstable merge state, and on each the only failing check is `Docker E2E`. + +That failing check is the symptom #2179 diagnoses and fixes; it is not a property of either bump. Until #2179 merges, a rebase would only reproduce the same failure, so the correct action is to wait rather than to churn the branches. + +Both are major-version bumps, so merging is not automatic even once the check is green: each deserves a decision on its own merits. + +## Scope + +### In Scope + +- Wait for #2179 to merge. +- Rebase each pull request onto `develop` and re-run its checks. +- Decide each on its merits: merge it, or close it with the reason recorded. + +### Out of Scope + +- Fixing the `Docker E2E` job. That is #2179. +- Any change to either branch's dependency choice beyond accepting or rejecting the bump as proposed. +- A wider review of the repository's dependency update policy. +- The allowlist change that blocks a different dependency update, which is a separate subissue under this EPIC. + +## Architectural Decisions + +No architectural decision is expected from the handling itself. If either major-version bump forces a code change with design consequences, that change belongs to its own issue, not to this one. + +- Related ADRs: `None` +- ADRs to create: `None known` + +## Design and Ownership Review + +`Not applicable`. No implementation work is planned in this repository. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | BLOCKED | Wait for the Docker E2E repair to merge | #2179 is merged and the job passes on `develop`. | +| T2 | TODO | Rebase and re-run both pull requests | Each pull request is current with `develop` and its checks report a real result. | +| T3 | TODO | Decide each bump on its merits | Each pull request is merged, or closed with the reason recorded in this specification's progress log. | +| T4 | TODO | Final acceptance review | Every acceptance criterion is re-reviewed against observed state. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T1 to T4 | No repository change in this issue's own branch. | Record the outcome in the progress log as a justified no-change decision; do not create an empty commit. Any merge happens in the dependency pull requests themselves. | + +This issue produces decisions and evidence rather than a commit of its own. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created, linked as a subissue of the parent EPIC, and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C7, maintainer action A2 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: Neither pull request is still open in a stalled state: each is merged or closed. +- [ ] AC2: A closure records the reason the bump was not wanted on its own merits, not the transient check failure. +- [ ] AC3: A merge happened only after the checks reported a real result on a rebased head. +- [ ] AC4: No file changed as part of this issue itself. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- The checks on each dependency pull request, after rebase +- `linter all` on `develop` after any merge + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | The blocking failure is gone | After #2179 merges, re-run the checks on each pull request and read the result | `Docker E2E` reports a real result rather than the failure #2179 diagnoses | TODO | `manual-verification-evidence.md` section V1 | +| M2 | Each pull request reaches a decision | Read the state of both pull requests at the end of the work | Each is merged or closed, with the reason visible | TODO | `manual-verification-evidence.md` section V2 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Disposable Verification Scripts + +None is planned. Both scenarios are reads of pull request state. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M2 | +| AC2 | TODO | M2 | +| AC3 | TODO | M1 | +| AC4 | TODO | {issue link} | + +## Risks and Trade-offs + +- Waiting on another issue can turn into waiting indefinitely. Mitigation: T1 names the dependency explicitly and this issue stays blocked and visible rather than silently open. +- Major-version bumps that sat for months may no longer be the current version by the time they can run. Mitigation: the decision step accepts closing a stale bump in favour of a fresh one, with the reason recorded. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if either bump turns out to require code changes with design consequences, or the rebase reveals a failure unrelated to the one diagnosed in #2179. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2190 (parent EPIC), #2179 (the failing check both pull requests are blocked behind) +- Related PRs: #2055, #2106, #2193 (the EPIC specification that produced this draft) +- Related ADRs: `None` diff --git a/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md b/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md new file mode 100644 index 000000000..20cbb58a6 --- /dev/null +++ b/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md @@ -0,0 +1,178 @@ +--- +doc-type: issue +issue-type: task +status: draft +priority: p2 +epic: 2190 +github-issue: null +spec-path: docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - .github/skills/dev/maintenance/update-github-workflow-actions/SKILL.md + - .github/workflows/testing.yaml + - .github/workflows/coverage.yaml + - .github/workflows/generate_coverage_pr.yaml + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Widen the allowed-actions allowlist entry that pins an exact patch version + +**Parent EPIC:** #2190 - Repository maintenance frictions clean-up + +## Goal + +Let dependency updates of the install action run at all, by replacing the exact patch version in the repository's allowed-actions allowlist with the version pattern the repository's own skill prescribes. + +## Background + +This issue changes no file in this repository. It is an administrative change to the repository's GitHub Actions settings, recorded as an issue so it has an owner, an acceptance criterion, and a visible state. + +Verified on 2026-09-09. The repository's selected-actions permissions list `taiki-e/install-action@v2.87.2` among its allowed patterns. Three workflows use that action, at `.github/workflows/testing.yaml:80`, `coverage.yaml:51`, and `generate_coverage_pr.yaml:46`, so no automated bump of it can run: the workflow is refused before it starts. + +The failure mode is worse than a red check. On pull request #2180, which bumped the action from 2.87.2 to 2.87.6 at head `a90c3bb1`, the runs for `Testing` on push, `Testing` on pull request, and `Generate Coverage Report (PR)` all show `startup_failure`, while the ordinary pull request check view lists eighteen rows that are all passing or skipped. The blocked bump therefore looks green to a reviewer. + +The repository's own skill already prescribes the fix, at `.github/skills/dev/maintenance/update-github-workflow-actions/SKILL.md:49`. + +## Scope + +### In Scope + +- A repository administrator changes the allowlist entry from the exact patch version to `taiki-e/install-action@v2.*`, as the maintenance skill directs. +- Confirm the value before and after through the readable permissions endpoint. +- Confirm that a previously blocked bump of that action now produces real workflow runs. + +### Out of Scope + +- Any change to a file in this repository. The allowlist lives in the repository settings. +- Widening or reviewing other entries in the allowlist. +- Changing the three workflows that use the action. +- Merging or closing the blocked dependency pull requests, which is a separate subissue under this EPIC. + +## Architectural Decisions + +No architectural decision is expected. The maintenance skill already records the convention this change restores. + +- Related ADRs: `None` +- ADRs to create: `None known` + +## Design and Ownership Review + +`Not applicable`. A settings change with no runtime, ownership, or lifetime dimension. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | TODO | Read and record the current allowlist value | The current patterns are recorded as evidence, showing the exact patch pin. | +| T2 | TODO | Repository administrator widens the entry | The allowlist carries `taiki-e/install-action@v2.*` in place of the exact patch pin. | +| T3 | TODO | Confirm a blocked bump now runs | A re-run of an affected pull request produces workflow runs that are not `startup_failure`. | +| T4 | TODO | Final acceptance review | Every acceptance criterion is re-reviewed against observed behaviour and recorded in the progress log. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T1 to T4 | No repository change. | Record the outcome in `manual-verification-evidence.md` and as a justified no-change decision in the progress log; do not create an empty commit. | + +This issue produces evidence rather than a commit. Should it turn out that a file in this repository does need to change, record why and use a Conventional Commit message with the narrow affected scope. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created, linked as a subissue of the parent EPIC, and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C7, maintainer action A1 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: The repository's allowed-actions allowlist carries a version pattern rather than an exact patch pin for the install action. +- [ ] AC2: The before and after values are both recorded from the permissions endpoint. +- [ ] AC3: An affected dependency pull request produces workflow runs that reach their jobs rather than failing at startup. +- [ ] AC4: No file in this repository changed. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all`, to confirm the tree is unchanged and still green + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | The allowlist value changes as intended | Read the repository's selected-actions permissions before the change and again after it | The exact patch pin is replaced by the version pattern | TODO | `manual-verification-evidence.md` section V1 | +| M2 | A blocked bump now runs | Re-run the checks on an affected dependency pull request and list the workflow runs for its head | No run reports `startup_failure`; the jobs start and report a real result | TODO | `manual-verification-evidence.md` section V2 | +| M3 | The ordinary check view agrees | Read the pull request check list for the same head | The check list no longer shows an all-green picture over failed startups | TODO | `manual-verification-evidence.md` section V3 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +- The permissions endpoint is readable with ordinary access, so the value can be confirmed before and after without administrator rights. Making the change itself requires a repository administrator. + +### Disposable Verification Scripts + +None is planned. Every scenario is a direct read of repository settings or of a workflow run list. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M1 | +| AC2 | TODO | M1 | +| AC3 | TODO | M2 and M3 | +| AC4 | TODO | {PR link} | + +## Risks and Trade-offs + +- A wider pattern admits future patch releases of that action without review. Mitigation: that is the convention the repository's own maintenance skill prescribes, and the alternative is a pin that silently blocks every update to the same action. +- The change is invisible in the repository history. Mitigation: this issue is the record, and the before and after values are captured as evidence. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if the widened pattern admits a release that breaks a workflow, or the permissions endpoint disagrees with what the settings interface shows. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2190 (parent EPIC) +- Related PRs: #2180 (the bump that showed the failure mode), #2193 (the EPIC specification that produced this draft) +- Related ADRs: `None` diff --git a/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md b/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md new file mode 100644 index 000000000..d26f980d5 --- /dev/null +++ b/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md @@ -0,0 +1,180 @@ +--- +doc-type: issue +issue-type: bug +status: draft +priority: p2 +epic: null +github-issue: null +spec-path: docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md +branch: null +related-pr: null +last-updated-utc: 2026-09-10 09:30 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - packages/configuration/src/v3_0_0/mod.rs + - packages/configuration/src/lib.rs + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +--- + + + +# Issue #[To be assigned] - Report an unsupported configuration schema version instead of an unknown-field error + +**Parent EPIC:** None. This issue is standalone; see the reasoning in [EPIC #2190](../../open/2190-maintenance-frictions-cleanup/EPIC.md). + +## Goal + +Make a configuration file written for an older schema version report that its schema version is unsupported, rather than complaining about a section name the current schema does not know. + +## Background + +Verified at revision `f6b73e29` on 2026-09-09. In `packages/configuration/src/v3_0_0/mod.rs`, `Configuration::load` runs the strict extract at line 392 before checking `metadata.schema_version` at line 395. Every configuration section carries an attribute rejecting unknown fields, so a version-2 configuration file fails on the first section name the version-3 schema does not know, and the user is told there is an unknown field named `tracker`. + +The error that exists precisely to explain this case, `Error::UnsupportedVersion`, is defined at `packages/configuration/src/lib.rs:816` and returned at line 396, but the strict extract has already failed by then, so it is unreachable for exactly the input it was written for. + +The user-visible result is a spelling complaint where the real problem is that the file is a schema version behind, which sends people looking for a typo in a file that has none. This was found while verifying the maintenance inventory in EPIC #2190 and is recorded there as the one item that is a behavioural change rather than clean-up. + +## Scope + +### In Scope + +- Report an unsupported schema version for a configuration file whose declared version is not the one this binary supports, whatever else the file contains. +- Decide between reading the metadata section separately before the strict extract and relaxing the extract enough to reach the version check, and record the reasoning. +- Add a regression test that loads a version-2 file with the version-3 loader and asserts the unsupported-version error. +- Check the same ordering in the version-2 loader at `packages/configuration/src/v2_0_0/mod.rs:362` and record whether it has the same defect. + +### Out of Scope + +- Supporting or migrating older configuration schemas. The goal is a correct error, not compatibility. +- Relaxing the unknown-field policy in general. Unknown fields inside a file of the right schema version must still be rejected. +- Any other change to configuration loading, defaults, or environment overrides. + +## Architectural Decisions + +The choice between a separate metadata probe and a relaxed extract has consequences for every future schema change, so record it. If the chosen approach constrains how later schema versions detect themselves, create an ADR under `docs/adrs/`; if it is contained inside one loader function, a note in this specification is enough. + +- Related ADRs: `None` +- ADRs to create: Configuration schema-version detection order, if the chosen approach constrains future schema versions + +## Design and Ownership Review + +`Not applicable` for process, I/O, and cleanup concerns: loading is synchronous and owns nothing beyond the parsed value. The one interface question is whether a metadata probe becomes a second public entry point on the configuration loader or stays a private step inside `load`; prefer the private step unless a caller genuinely needs the version without the rest of the file. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ---- | ----------------------- | +| T1 | TODO | Reproduce the defect with a failing test | A test loading a version-2 file with the version-3 loader fails, asserting the unsupported-version error and observing the unknown-field error instead. | +| T2 | TODO | Choose and record the detection approach | The chosen approach and the rejected alternative are recorded, with the reason. | +| T3 | TODO | Implement the chosen approach | The failing test passes; unknown fields in a correctly versioned file are still rejected. | +| T4 | TODO | Check the version-2 loader for the same ordering | The version-2 loader is confirmed correct, or its defect is recorded and either fixed here or given its own issue. | +| T5 | TODO | Final verification and acceptance review | `linter all` exits 0, the configuration package tests pass, and every acceptance criterion is re-reviewed against observed behaviour. | + +## Commit Points + +| Task | Coherent change set | Commit policy | +| ---- | ------------------- | ------------- | +| T1 | The failing regression test. | Commit the failing test first so the defect is recorded as a test before it is fixed. | +| T2, T3 | The detection change. | Commit once the regression test passes and the unknown-field rejection still holds. | +| T4 | The version-2 loader finding. | Commit the fix if it is the same one-line ordering; otherwise record a justified no-change decision and open a separate issue. | +| T5 | Completion evidence. | Keep separate from the fix so the verification record is reviewable on its own. | + +Record a justified no-change decision in the task's evidence without creating an empty commit. Use a Conventional Commit message with the narrow affected scope. + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Folder-style spec drafted in `docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md` +- [ ] Spec reviewed and approved by user/maintainer +- [ ] GitHub issue created and issue number added to this spec +- [ ] Specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number +- [ ] Implementation completed +- [ ] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [ ] Manual verification scenarios executed and recorded in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Evidence-based implementation completion review recorded: issue-local retrospective created for material discoveries, or progress log states why none was needed +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Independent reviewer reports recorded in issue-local `agent-review-reports.md` when reviewers received this folder-style specification +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; the related-but-separate behavioural defect recorded there as R1 - https://github.com/torrust/torrust-tracker/issues/2190 + +## Acceptance Criteria + +- [ ] AC1: Loading a configuration file that declares an older schema version reports that the schema version is unsupported, and names the version found. +- [ ] AC2: The reported error no longer names a section as an unknown field when the real cause is the schema version. +- [ ] AC3: A configuration file of the correct schema version that contains a genuinely unknown field is still rejected as such. +- [ ] AC4: A regression test covers both cases and fails if the ordering is reintroduced. +- [ ] AC5: The version-2 loader is either confirmed correct or its equivalent defect is recorded. +- [ ] `linter all` exits with code `0` +- [ ] Relevant tests pass +- [ ] Manual verification scenarios are executed and documented in issue-local `manual-verification-evidence.md` +- [ ] Acceptance criteria are re-reviewed after implementation and reflect actual behavior +- [ ] Documentation is updated when behavior/workflow changes + +## Verification Plan + +### Automatic Checks + +- `linter all` +- The configuration package tests +- The workspace test suite for the packages that depend on configuration loading + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Human-oriented command/steps | Expected Result | Status | Evidence | +| --- | -------- | ---------------------------- | --------------- | ------ | -------- | +| M1 | An old configuration file explains itself | Run the tracker against a configuration file declaring the version-2 schema and read the error printed to the console | The message says the schema version is unsupported and names the version found, not an unknown field | TODO | `manual-verification-evidence.md` section V1 | +| M2 | A genuine typo is still a typo | Run the tracker against a correctly versioned configuration file containing one misspelled field and read the error | The message still identifies the unknown field | TODO | `manual-verification-evidence.md` section V2 | + +Notes: + +- Manual verification is mandatory even when automated tests pass. It is a real human-oriented use of the repository's tooling, not a simulated result and not merely running automated tests. +- Create `manual-verification-evidence.md` from `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md` when executing these scenarios. Record actual prerequisites, actions, commands, program output, relevant logs, and outcomes there. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Disposable Verification Scripts + +None is planned. Both scenarios are direct runs of the binary against a small configuration file, and the regression coverage belongs in the package's own tests. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | -------- | +| AC1 | TODO | M1 | +| AC2 | TODO | M1 | +| AC3 | TODO | M2 | +| AC4 | TODO | Automatic checks | +| AC5 | TODO | {PR link} | + +## Risks and Trade-offs + +- Relaxing the strict extract to reach the version check could weaken unknown-field rejection for correctly versioned files. Mitigation: an acceptance criterion and a manual scenario both assert that rejection still holds, and the alternative approach avoids the relaxation entirely. +- A separate metadata probe parses the file twice. Mitigation: configuration loading happens once at startup, so the cost is negligible next to the clarity of the error. +- The same ordering may exist in other loaders. Mitigation: T4 checks the version-2 loader explicitly rather than assuming. + +## Implementation Completion Review + +After implementation, compare the result with this specification. Record invalidated assumptions, material design changes, unexpected validation findings, and reusable lessons. + +- Retrospective: `Not yet assessed` +- Create `implementation-retrospective.md` from `docs/templates/IMPLEMENTATION-RETROSPECTIVE.md` in this directory if the chosen detection approach constrains how future schema versions are detected, or the version-2 loader turns out to have a materially different defect. +- If none of that occurs, add a concise progress-log entry explaining why the work had no material discovery. +- When an independent reviewer receives this folder-style specification, it records its result in `agent-review-reports.md` using `docs/templates/AGENT-REVIEW-REPORTS.md`. + +## References + +- Related issues: #2190 (the inventory that recorded this defect) +- Related PRs: #2193 (the EPIC specification that produced this draft) +- Related ADRs: `None` yet; see Architectural Decisions From 87f4d422b4e182b1116d884bde0b286c4300e553 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 10:43:47 +0200 Subject: [PATCH 05/13] docs(review): record PR 2193 copilot suggestion audit --- .../pr-2193-copilot-suggestions.md | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md diff --git a/docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md b/docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md new file mode 100644 index 000000000..caeca6bd7 --- /dev/null +++ b/docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md @@ -0,0 +1,51 @@ +--- +semantic-links: + skill-links: + - process-copilot-suggestions + related-artifacts: + - .github/skills/dev/pr-reviews/process-copilot-suggestions/SKILL.md + - docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md + - docs/templates/ISSUE.md + - docs/templates/EPIC.md +--- + + + + + +# PR #2193 Copilot Suggestions Tracking + +Source: Copilot PR review threads for + +Status legend: + +- `action`: code/docs change applied +- `no-action`: suggestion reviewed; no code change needed +- `resolved`: thread resolved in PR + +## Workflow + +1. Download all review threads (including resolved/outdated state and thread IDs). +2. Add one row per thread in the Suggestions table. +3. Process suggestions one by one: + - decide `action` or `no-action` + - if `action`, apply change and validate + - if needed, commit changes + - reply on the PR thread with the fix commit and outcome, or the no-action rationale + - resolve the PR thread +4. Set `Thread State` to `resolved` once resolved in PR. + +## Processing Log + +- 2026-09-10: Reviewed the `last-updated-utc` timestamp-format suggestion against the repository templates and every existing specification. `docs/templates/ISSUE.md:11`, `docs/templates/EPIC.md:7`, `docs/templates/REFACTOR-PLAN.md:6`, and `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md:4` all prescribe `YYYY-MM-DD HH:MM`, and all 68 `last-updated-utc` values under `docs/issues/open/` and `docs/issues/drafts/` use that form; none uses an ISO-8601 designator. Decided `no-action`: the field follows the repository template, and changing one specification alone would make it the only file out of line with the convention. + +## Suggestions + +| # | Thread ID | Path | URL | Suggestion Summary | Decision | Reply URL | Status | Thread State | +| --- | ----------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------ | ------------ | +| 1 | `PRRT_kwDOGp2yqc6g_jtS` | `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` | | Use an ISO-8601 UTC form for `last-updated-utc` instead of `YYYY-MM-DD HH:MM`. | `no-action`: the format is the one the repository templates prescribe and every one of the 68 existing specifications uses. | {reply URL} | DONE | TODO | + +## Notes + +- The commented path is the specification's path before this pull request renamed it to `EPIC.md`; the field itself is unchanged and is now at `docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md:11`. +- A repository-wide move to ISO-8601 timestamps would be a convention change across the templates and every existing specification, not a change to one file. If it is wanted, it belongs in its own issue. From eb7d1fc282a1429cc1efb70bf1c77a90f40ed578 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 10:53:17 +0200 Subject: [PATCH 06/13] docs(review): record PR 2193 copilot reply links --- docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md b/docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md index caeca6bd7..b69967d50 100644 --- a/docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md +++ b/docs/copilot-pr-reviews/pr-2193-copilot-suggestions.md @@ -37,13 +37,17 @@ Status legend: ## Processing Log +- 2026-09-10: Started processing suggestions; one Copilot thread was open. - 2026-09-10: Reviewed the `last-updated-utc` timestamp-format suggestion against the repository templates and every existing specification. `docs/templates/ISSUE.md:11`, `docs/templates/EPIC.md:7`, `docs/templates/REFACTOR-PLAN.md:6`, and `docs/templates/MANUAL-VERIFICATION-EVIDENCE.md:4` all prescribe `YYYY-MM-DD HH:MM`, and all 68 `last-updated-utc` values under `docs/issues/open/` and `docs/issues/drafts/` use that form; none uses an ISO-8601 designator. Decided `no-action`: the field follows the repository template, and changing one specification alone would make it the only file out of line with the convention. +- 2026-09-10: Replied with that evidence on [thread 1](https://github.com/torrust/torrust-tracker/pull/2193#discussion_r3977263040) and resolved it; no repository change was needed. +- 2026-09-10: Answered the maintainer review requesting an EPIC with domain-clustered subissues in [comment 5615823526](https://github.com/torrust/torrust-tracker/pull/2193#issuecomment-5615823526). +- 2026-09-10: Refreshed the review-thread list; no unresolved threads remained. ## Suggestions | # | Thread ID | Path | URL | Suggestion Summary | Decision | Reply URL | Status | Thread State | | --- | ----------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------ | ------------ | -| 1 | `PRRT_kwDOGp2yqc6g_jtS` | `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` | | Use an ISO-8601 UTC form for `last-updated-utc` instead of `YYYY-MM-DD HH:MM`. | `no-action`: the format is the one the repository templates prescribe and every one of the 68 existing specifications uses. | {reply URL} | DONE | TODO | +| 1 | `PRRT_kwDOGp2yqc6g_jtS` | `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` | | Use an ISO-8601 UTC form for `last-updated-utc` instead of `YYYY-MM-DD HH:MM`. | `no-action`: the format is the one the repository templates prescribe and every one of the 68 existing specifications uses. | | DONE | RESOLVED | ## Notes From ce6a313d159366aa8c760dedf9c21b5077d3790b Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 11:05:50 +0200 Subject: [PATCH 07/13] docs(issues): [#2190] follow the maintainers' EPIC shape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EPIC #1840 and EPIC #1347 establish the shape an EPIC in this repository takes: Goal, Why This Is Needed, Scope, Subissues, Delivery Strategy, Progress Tracking, Acceptance Criteria, Risks and Trade-offs, References, plus at most a domain section where the EPIC genuinely needs one — a package inventory in #1669, Known Existing Issues in #2003. EPIC #2190 carried eight sections beyond that spine, and its inventory duplicated evidence the subissue drafts already hold. Collapse the friction, maintainer-action, related-but-separate, cluster, per-parent-argument, and handoff sections into one compact Friction Inventory, shaped like #2003's Known Existing Issues: one row per item, naming the draft that holds its evidence and the EPIC that owns it. The per-parent argument moves into the Subissues table's Notes column and one paragraph of Delivery Strategy; the two candidates that did not reproduce become Out of Scope entries, the form #2003 uses for work it excludes; the ADR pointer moves to References, where every model EPIC keeps one. No EPIC in the repository, and not the EPIC template, carries an Architectural Decisions section — that section belongs to child specs. Reduce the frontmatter to the key set #1840, #1347 and the template share. epic-owner stays null: the template's default is written for an EPIC no maintainer has adopted, and naming one would assert what is not yet true. Add the sentence #2003 uses to keep proposed subissues from becoming GitHub issues before a maintainer approves them, and record the alignment in the progress log. The drafts' progress logs lose the cluster identifiers, which no longer exist, and name their inventory items instead. Every fact survives; only the shape changes. --- .../ISSUE.md | 4 +- .../ISSUE.md | 4 +- .../ISSUE.md | 4 +- .../ISSUE.md | 4 +- .../ISSUE.md | 4 +- .../ISSUE.md | 4 +- .../ISSUE.md | 4 +- .../ISSUE.md | 4 +- .../ISSUE.md | 4 +- .../EPIC.md | 219 ++++++------------ 10 files changed, 94 insertions(+), 161 deletions(-) diff --git a/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md b/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md index f16c1c152..355a9768e 100644 --- a/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md +++ b/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -111,7 +111,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C1, friction F5 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F5 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md b/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md index 5de16a5fb..05159ac0f 100644 --- a/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md +++ b/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -112,7 +112,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C2, frictions F1 and F7 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory items F1 and F7 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md b/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md index eebfb10f7..71b79f016 100644 --- a/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md +++ b/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -106,7 +106,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C5, friction F2 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F2 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md b/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md index 3011d192e..08bf1d777 100644 --- a/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md +++ b/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -111,7 +111,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C4, frictions F4 and F8 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory items F4 and F8 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md b/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md index 4958830b9..30711dd12 100644 --- a/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md +++ b/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -102,7 +102,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C3, friction F3 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F3 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md b/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md index 6aff40b3c..755cde25a 100644 --- a/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md +++ b/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -100,7 +100,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C6, friction F6 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F6 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md b/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md index 02d1422ea..6edc2e05a 100644 --- a/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md +++ b/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -102,7 +102,7 @@ This issue produces decisions and evidence rather than a commit of its own. ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C7, maintainer action A2 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item A2 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md b/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md index 20cbb58a6..f598d384f 100644 --- a/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md +++ b/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -106,7 +106,7 @@ This issue produces evidence rather than a commit. Should it turn out that a fil ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; cluster C7, maintainer action A1 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item A1 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md b/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md index d26f980d5..21f233c90 100644 --- a/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md +++ b/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -106,7 +106,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; the related-but-separate behavioural defect recorded there as R1 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item R1, the one behavioural defect rather than clean-up - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md index 560ae8c56..ad6db4b62 100644 --- a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +++ b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md @@ -1,14 +1,10 @@ --- doc-type: epic -issue-type: task status: planned -priority: p2 github-issue: 2190 spec-path: docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md epic-owner: null -branch: "2190-maintenance-frictions-cleanup-spec" -related-pr: null -last-updated-utc: 2026-09-10 09:30 +last-updated-utc: 2026-09-10 09:45 semantic-links: skill-links: - create-issue @@ -44,11 +40,11 @@ The inventory itself is still worth keeping. Each entry was verified against the ### In Scope -- Preserve the verified [Friction Inventory](#friction-inventory), [Maintainer Actions](#maintainer-actions), [Related but Separate](#related-but-separate), and [Dropped Candidates](#dropped-candidates) evidence as the durable record behind every subissue this EPIC produces. -- Cluster every inventory item by domain and record, for each cluster, the EPIC that owns it and the reason that EPIC owns it. -- Produce one draft subissue specification per cluster item under `docs/issues/drafts/`, each sized for one focused pull request and each naming its parent EPIC. +- Keep the verified inventory as the durable record behind every subissue this EPIC produces, with each item's evidence held in the subissue specification that owns it. +- Assign every inventory item to the EPIC whose own stated scope covers it, and record that assignment. +- Produce one draft subissue specification per item or group of items sharing a domain, each sized for one focused pull request and each naming its parent EPIC. - Create the GitHub subissues from the approved drafts, link them under their parent EPIC, and move each specification into `docs/issues/open/` under the naming convention. -- Hand the two clusters that belong to EPIC #2003 to that EPIC, including the row each needs in its subissue table. +- Hand the two developer-tool-check items to EPIC #2003, including the row each needs in its subissue table. - Track completion of the subissues this EPIC owns until every inventory item is delivered or explicitly closed as won't-fix. ### Out of Scope @@ -59,118 +55,51 @@ The inventory itself is still worth keeping. Each entry was verified against the - Triaging external-link check findings. That is #2185, whose specification is under review in #2186. - Repairing the `Docker E2E` job in `.github/workflows/testing.yaml`. That is #2179; this EPIC only records which stale pull requests are blocked behind it. - Migrating legacy single-file specifications to the folder-style layout. That is #2159. -- Designing the long-term check harness and sensor architecture. That is EPIC #2003; the two clusters handed to it add and repair invocations of checks that already exist and do not prejudge that design. -- Any behavioural change to the tracker itself. The one behavioural defect found while verifying the inventory is recorded in [Related but Separate](#related-but-separate) and becomes a standalone issue with its own acceptance criteria. +- Designing the long-term check harness and sensor architecture. That is EPIC #2003; the two items handed to it add and repair invocations of checks that already exist and do not prejudge that design. +- Any behavioural change to the tracker itself. The one behavioural defect found while verifying the inventory is item `R1`, which becomes a standalone issue with its own acceptance criteria. +- Local Markdown link health. `linter lychee` exits 0 on `develop` with all local links passing in 0.137 s, and `.github/workflows/docs-lint.yaml:60` already enforces it; external links are wholly owned by #2185. The `.lycheeignore` file named in the original candidate list does not exist and, per #2150, will not: the configuration lives in `lychee.toml` and `.github/lychee-online.toml`. +- A second never-run merge-tool suite. No `test-github-merge-symlinks.py` exists on `develop`; `contrib/dev-tools/git/tests/` contains only `test-merge-pull-request.sh`. That Python suite belongs to the unmerged symlink-exceptions work for #2175 and arrives with it. ## Friction Inventory -This is the verified evidence behind the subissues. Each entry was re-verified against `develop` at revision `f6b73e29` on 2026-09-09; the evidence column records what was observed rather than what was reported. The proposed fix is the starting point for the subissue that owns the item, not a decision binding on it. - -Size is the expected reviewable weight of the change: `XS` is a one-line edit, `S` is a handful of lines in one file, `M` spans several files or needs a judgement call. The `Cluster` column links each item to its parent in [Clusters](#clusters). - -| ID | Cluster | Area | Evidence (verified at `f6b73e29`, 2026-09-09) | Proposed fix | Size | -| --- | ------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | -| F1 | C2 | Developer tooling | Three developer-tool test suites exist and no orchestrator runs any of them: `contrib/dev-tools/git/tests/test-merge-pull-request.sh`, `contrib/dev-tools/checks/tests/test-format-project-words.sh`, `contrib/dev-tools/checks/tests/test-agent-review-report-contract.sh`. `grep -rn "contrib/dev-tools" .github/workflows/` returns only the container persistence test and the hook installer; the suites appear in no `STEPS` entry of `contrib/dev-tools/git/hooks/pre-commit.sh` (lines 51-58) or `pre-push.sh`. Two scripts state the gap themselves: `contrib/dev-tools/checks/tests/test-format-project-words.sh:6` and `contrib/dev-tools/checks/format-project-words.sh:6`. | Add one lightweight CI step that runs the three suites, and delete the now-untrue "not automatically run" notes. Keep the step outside the expensive test matrix; the three suites together complete in roughly one second on a warm host. | S | -| F2 | C5 | Issue lifecycle | Sixteen specification directories under `docs/issues/open/` belong to issues GitHub reports as `CLOSED`: 1586, 1588, 2121, 2122, 2130, 2132, 2134, 2136, 2138, 2140, 2150, 2151, 2155, 2156, 2160, 2162. Verified by `gh issue view --json state,closedAt` for every directory in `docs/issues/open/`. The archival rule is `docs/issues/closed/README.md`. | Move the sixteen directories to `docs/issues/closed/` per the `cleanup-completed-issues` skill, repairing any live references the move breaks. Automation of this flow stays with #1774. | M | -| F3 | C3 | Workflow triggers | `.github/workflows/container.yaml:16` triggers pushes on `releases/**/*`, while `.github/workflows/deployment.yaml:15` was narrowed to `releases/v*`. Package release branches match `releases/pkg/**` (`.github/workflows/deployment-packages.yaml:35`), so every package release push also starts the container workflow, which then extracts `pkg//v` as its version, fails the semver test at `container.yaml:165`, prints `Not a valid release branch semver. Will Not Continue`, and exits 0. | Narrow `container.yaml:16` to `releases/v*`, matching `deployment.yaml`. The semver guard stays as the second line of defence. | XS | -| F4 | C4 | Documentation drift | `src/bin/` now contains only `http_health_check.rs`; `e2e_tests_runner`, `profiling`, and `qbittorrent_e2e_runner` moved to `packages/e2e-tools/src/bin/` in commit `c47173f53`. Five live references were never updated: `AGENTS.md:39`, `.github/skills/dev/testing/manual-http-download-completion-e2e/SKILL.md:21` and `:307`, `.github/skills/dev/testing/manual-udp-download-completion-e2e/SKILL.md:207`, `docs/profiling.md:10`. `docs/adrs/20260519000000_define_global_cli_output_contract.md:8` lists `src/bin/` as a related artifact and now under-describes the binary landscape. | Correct the five live references to `packages/e2e-tools/src/bin/`. Extend the ADR's related-artifacts list rather than rewriting the decision. Leave `docs/issues/closed/` untouched: those are immutable historical records. #2179 names this drift out of its own scope and worth its own issue. | S | -| F5 | C1 | Test health | `contrib/dev-tools/checks/tests/test-format-project-words.sh` exits 1 on `develop` for two independent reasons. First, `PROJECT_ROOT` at line 13 climbs three levels from `contrib/dev-tools/checks/tests/` and lands on `/contrib`, so every fixture copy reads `/contrib/contrib/dev-tools/...` and fails; the sibling suite at `contrib/dev-tools/git/tests/test-merge-pull-request.sh:6` climbs four from an equally deep directory and is correct. Commit `ffa2aa2c5` introduced the wrong depth when it moved the suite beside its sensor. Second, with the depth corrected the suite still fails: `create_fixture` (lines 21-28) never provisions `contrib/dev-tools/checks/lint-containerfile.sh`, so pre-commit step 5 of 6 reports `No such file or directory`, `commands.log` holds 3 entries where line 205 asserts 4, and the success banner asserted at line 206 is never printed. | Correct the `PROJECT_ROOT` depth to four levels, and provision the Containerfile lint sensor in the fixture with a stub that keeps the suite hermetic and free of any container runtime. Re-check the `commands.log` count assertion against whichever stub is chosen. | S | -| F6 | C6 | Code readability | `contrib/dev-tools/analysis/workspace-coupling/src/main.rs:191` writes an explicit generic argument naming Rust's character type — the five-character token spelled angle bracket, c-h-a-r, angle bracket. It is the only occurrence in the tracked tree. Chat and review transport layers substitute that token with a role or account name, so the line cannot be quoted in a review discussion without arriving as text that would not compile, which makes a reviewer reasonably distrust the quoted artifact. | Take the character by value — `fn is_rust_identifier_char(ch: char) -> bool` — and move the optionality to the two call sites at line 187, which already hold values from `chars().next_back()` and `chars().next()` and can use `is_some_and`. Behaviour is unchanged: an absent adjacent character still reads as "not an identifier character". Where a token-free signature is genuinely impossible, a local type alias or inference through `collect()` serves the same purpose. | XS | -| F7 | C2 | Dead comment | `contrib/dev-tools/checks/lint-containerfile.sh:4` reads `Tests: (no automated tests yet — EPIC #2003)`. Once F5 and F1 land, the fixture for that sensor exists and is exercised, so the note becomes untrue in the same pull request that makes it so. | Update the note to point at the fixture that covers the sensor, or delete it. Handle it in the same commit as F1 so the tree is never internally inconsistent. | XS | -| F8 | C4 | Documentation drift | `docs/issues/open/2150-add-lychee-link-checker/ISSUE.md:93` records the decision not to add a `.lycheeignore` file, and `project-words.txt:306` still carries `lycheeignore` as a dictionary entry. The file does not exist and by that decision never will. | Confirm no remaining prose needs the word, then drop the dictionary entry. Keep it if the closed specification's own text still requires it — the dictionary serves the documents, not the other way round. | XS | - -## Maintainer Actions - -These two items cannot be performed from a pull request; both are cluster C7 and each becomes a subissue that changes no file in this repository. The evidence is kept here so the subissue specifications do not have to re-derive it. - -| ID | Item | Evidence | Action owner and change | -| --- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| A1 | Allowed-actions allowlist pins an exact patch | `gh api repos/torrust/torrust-tracker/actions/permissions/selected-actions` returns `taiki-e/install-action@v2.87.2` among `patterns_allowed`. Three workflows use that action (`.github/workflows/testing.yaml:80`, `coverage.yaml:51`, `generate_coverage_pr.yaml:46`), so no Dependabot bump of it can run. On PR #2180 (`2.87.2` to `2.87.6`, head `a90c3bb1`), `gh api "…/actions/runs?head_sha=a90c3bb1…"` shows `Testing` (push), `Testing` (pull_request), and `Generate Coverage Report (PR)` all `startup_failure`, while `gh pr checks 2180` lists 18 rows that are all `pass` or `skipping` — the failures are invisible in the ordinary check view. The repository's own skill already prescribes the fix at `.github/skills/dev/maintenance/update-github-workflow-actions/SKILL.md:49`. | Repository administrator: change the allowlist entry to `taiki-e/install-action@v2.*`, as that skill directs. No file in this repository changes. Note that the permissions endpoint is readable with ordinary access, so the current value can be confirmed before and after. | -| A2 | Two Dependabot pull requests stalled since August | #2055 (`base64` 0.22.1 to 0.23.1, opened 2026-08-07) and #2106 (`syn` 2.0.119 to 3.0.4, opened 2026-08-27). `gh api repos/torrust/torrust-tracker/compare/...develop` puts `develop` 263 and 137 commits ahead respectively; both report `mergeStateStatus: UNSTABLE`, and on each the only failing check is `Docker E2E` — the symptom #2179 diagnoses and fixes. | Maintainer: after #2179 merges, rebase both and re-run, or close them if the major-version bumps are unwanted on their own merits. This issue does not touch either branch and does not duplicate #2179's fix. | - -## Related but Separate - -`Configuration::load` runs the strict Figment extract at `packages/configuration/src/v3_0_0/mod.rs:392` before checking `metadata.schema_version` at line 395. Because every configuration section carries `#[serde(deny_unknown_fields)]`, a version-2 configuration file fails on the first section name the version-3 schema does not know — reported as an unknown-field error naming `tracker` — instead of the `Error::UnsupportedVersion` that exists precisely to explain this case. The user sees a spelling complaint where the real problem is that the file is a schema version behind. - -This is a behavioural change to a user-facing error path, not a maintenance clean-up: it needs its own acceptance criteria, its own regression test, and a decision about whether the version probe reads the metadata section separately or whether the extract is relaxed. It is recorded here because it was found while verifying this inventory. It is cluster C8, item `R1`: a standalone issue with no parent EPIC, drafted at `docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md`. The configuration overhaul EPIC that would have owned it, #1978, is closed. - -## Dropped Candidates - -Two items proposed for this inventory did not reproduce. They produce no subissue and are recorded so the same ground is not re-covered. - -| Candidate | Finding | -| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Broken or redirected local links | `linter lychee` exits 0 on `develop` with `All local Markdown links passed checking!` in 0.137 s. Local link health is already enforced by `.github/workflows/docs-lint.yaml:60`. External links are wholly owned by #2185, whose specification is under review in #2186. Nothing is left for this issue. The `.lycheeignore` file named in the original report does not exist and, per #2150, will not: the configuration lives in `lychee.toml` and `.github/lychee-online.toml`. | -| A second never-run merge-tool suite, `test-github-merge-symlinks.py` | No such file exists on `develop`. `contrib/dev-tools/git/tests/` contains only `test-merge-pull-request.sh`. The Python suite belongs to the unmerged symlink-exceptions work for #2175 and will arrive with it; F1 covers the suites that exist today. | - -## Clusters - -Each inventory item belongs to exactly one cluster, and each cluster to exactly one parent. A cluster is a domain — one reviewer context, one surface, one body of prior decisions — not a size bucket. Two clusters were adopted by an EPIC that already exists; the rest stay under this EPIC because no existing EPIC's stated scope covers them. - -| Cluster | Items | Domain | Parent | Draft specification | -| ------- | ---------- | --------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------- | -| C1 | F5 | Developer-tool checks: repairing an existing check | EPIC #2003 | `docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md` | -| C2 | F1, F7 | Developer-tool checks: invoking existing checks from CI | EPIC #2003 | `docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md` | -| C3 | F3 | Workflow trigger correctness | EPIC #2190 | `docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md` | -| C4 | F4, F8 | Stale references left behind by completed moves and decisions | EPIC #2190 | `docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md` | -| C5 | F2 | Issue-backlog archival | EPIC #2190 | `docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md` | -| C6 | F6 | Source hygiene for quotable artifacts | EPIC #2190 | `docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md` | -| C7 | A1, A2 | Repository administration; no repository change | EPIC #2190 | `docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md`, `docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md` | -| C8 | R1 | Configuration error reporting | None; standalone issue | `docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md` | - -### Why Each Parent - -**C1 and C2 belong to EPIC #2003 - Overhaul: Automation Tools and AI Agent Guardrails.** Its In Scope list covers exactly this surface: it undertakes to "Evaluate check placement across pre-commit, pre-push, CI, and any future repository-policy or architecture-check category", and it explicitly permits "the narrowly scoped interim formatter described by [`2019-automatically-format-project-dictionary`](../../closed/2019-automatically-format-project-dictionary/ISSUE.md)". F5 repairs that permitted formatter's own test suite, and C2 wires that suite and its two siblings into CI. Both also meet #2003's stated exception for work that may proceed before its architecture decision: "low-risk, additive, independently verifiable documentation, skill, profile, template, and focused validation subissues ... when they do not select or depend on a shared runner, cache, enforcement platform, external workflow tool, or broad consumer migration". Neither cluster selects a runner shape; each adds one invocation of a check that already exists, and both remain replaceable by the later design. F7 rides with C2 rather than standing alone because the dead note it removes — `contrib/dev-tools/checks/lint-containerfile.sh:4`, which reads that the sensor has no automated tests yet and names EPIC #2003 — only becomes untrue once C2 lands; splitting them would leave the tree self-contradicting between two pull requests. - -**C3 stays under this EPIC.** The only EPIC that owns `.github/workflows/container.yaml` is #1840 - Improve PR Workflow Performance, and its goal is stated in time: "Reduce the execution time of the critical PR validation workflows ... so maintainers and contributors can get faster feedback". F3 changes no workflow's runtime and no pull request's wait time. The spurious run it prevents is started by pushes to package release branches, which are not on the pull request critical path at all, and #1840's Out of Scope explicitly excludes "Optimizing unrelated workflows unless they directly affect these two critical paths". F3 is a trigger-predicate defect, not a performance item. - -**C4 stays under this EPIC.** F4's stale paths were created by a package move, which invites EPIC #1669 - Overhaul: Packages, but that EPIC's documentation duty is specific: its audit covers `docs/packages.md`, `packages/AGENTS.md`, the extracted-packages tables, and the dependency diagram at `docs/media/packages/dependencies-workspace-packages.md`. None of F4's five live references is one of those; they are in the testing section of `AGENTS.md`, two testing skills, and `docs/profiling.md`. F8's stale dictionary entry has no package dimension at all. What F4 and F8 share is the shape of the defect rather than the file: both name a referent that no longer exists or never will, one because the binaries moved and one because #2150 decided the file would not be created. That is one reviewer context and one small pull request. - -**C5 stays under this EPIC.** The archival flow's automation is #1774, which is a paused dependency of EPIC #2003 and blocked on that EPIC's architecture decision. Performing the current archival by hand is not automation work and must not inherit that block: it implements no tool, selects no interface, and constrains nothing in #1774's design. Filing it under #2003 would either park it behind a decision it does not need or force an exception into that EPIC's scope for a one-off manual action. - -**C6 stays under this EPIC.** The file it touches, `contrib/dev-tools/analysis/workspace-coupling/`, appears in EPIC #2003's related-artifacts list, but appearing as an artifact of an EPIC is not the same as falling inside its scope, and #2003's scope is the architecture of automation and guardrails rather than the source hygiene of any one tool. F6 changes one function signature so the line can survive being quoted in a review discussion; that concern is about how repository artifacts are reviewed, which is this EPIC's own domain. - -**C7 stays under this EPIC as two subissues with no repository change.** A1 and A2 are administrative actions on the GitHub repository and its pull requests. They are subissues rather than notes so that each has an owner, an acceptance criterion, and a visible state, which a table row inside another issue's body does not give them. - -**C8 has no parent.** The configuration error-ordering defect is a behavioural change to a user-facing error path in `packages/configuration`. The configuration overhaul EPIC that would have owned it, #1978, is closed. It needs its own acceptance criteria and its own regression test, and attaching it to a maintenance EPIC would misrepresent it as clean-up. +Every item was verified against `develop` at revision `f6b73e29` on 2026-09-09; each was observed in the tree rather than reported. The evidence for an item — its files, line numbers, commands, and observed output — lives in the draft specification named in its row, which is the source of truth for it. `Owner` is the EPIC that carries the item to delivery. + +| ID | Area | Friction | Draft specification | Owner | +| --- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | --------------------- | +| F1 | Developer tooling | Three developer-tool test suites exist and no orchestrator, local or in CI, runs any of them. | `docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md` | EPIC #2003 | +| F2 | Issue lifecycle | Sixteen specification directories under `docs/issues/open/` belong to issues GitHub reports as closed. | `docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md` | EPIC #2190 | +| F3 | Workflow triggers | The container workflow starts on every package release push and then refuses itself on its own semver guard. | `docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md` | EPIC #2190 | +| F4 | Documentation drift | Five live references still point at binaries that moved to `packages/e2e-tools/src/bin/`, and one ADR under-describes the binary landscape. | `docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md` | EPIC #2190 | +| F5 | Test health | The project-dictionary formatter's test suite has been red on `develop` since it was moved beside its sensor, for two independent reasons. | `docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md` | EPIC #2003 | +| F6 | Code readability | One line of the workspace-coupling tool cannot survive being quoted in a review discussion, so the artifact looks self-refuting. | `docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md` | EPIC #2190 | +| F7 | Dead comment | A sensor's note that it has no automated tests yet stops being true when F1 lands, so it is corrected in the same change. | `docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md` | EPIC #2003 | +| F8 | Documentation drift | `project-words.txt` still carries a dictionary entry for a file that #2150 decided will never be created. | `docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md` | EPIC #2190 | +| A1 | Repository administration | The allowed-actions allowlist pins an exact patch version, so no bump of that action can start, and the failure is invisible in check views. | `docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md` | EPIC #2190 | +| A2 | Repository administration | Two dependency update pull requests have been stalled since August behind the single check that #2179 fixes. | `docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md` | EPIC #2190 | +| R1 | Configuration error reporting | A version-2 configuration file is rejected with an unknown-field error instead of the unsupported-version error written for that case. | `docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md` | Standalone; no parent | ## Subissues Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. -These are the subissues this EPIC owns. Issue numbers are assigned when the drafts are approved and the GitHub issues are created; until then the draft path is the specification. - -| Order | Issue | Local Spec | Status | Notes | -| ----- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------- | -| 1 | #[To be assigned] - Narrow the container workflow release trigger | `docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md` | TODO | C3. One-line trigger change; independent of every other subissue. | -| 2 | #[To be assigned] - Correct stale documentation references | `docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md` | TODO | C4. Documentation and dictionary only; independently revertible. | -| 3 | #[To be assigned] - Archive closed issue specifications | `docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md` | TODO | C5. Large diff of pure moves; re-verify issue state at merge time. Does not constrain #1774. | -| 4 | #[To be assigned] - Remove the unquotable character-type generic | `docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md` | TODO | C6. Signature change with a before/after output comparison. | -| 5 | #[To be assigned] - Widen the workflow actions allowlist entry | `docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md` | TODO | C7, A1. Repository administrator action; no file in this repository changes. | -| 6 | #[To be assigned] - Resolve the stalled dependency update PRs | `docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md` | TODO | C7, A2. Blocked until #2179 merges; no file in this repository changes. | +These are the subissues this EPIC owns. Titles and boundaries may be adjusted during maintainer review; no GitHub issues should be created from these drafts without approval. Issue numbers are assigned when the drafts are approved and the GitHub issues are created; until then the draft path is the specification. -## Issues Handed to Other Owners +| Order | Issue | Local Spec | Status | Notes | +| ----- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| 1 | #[To be assigned] - Narrow the container workflow release trigger | `docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md` | TODO | F3. One-line trigger change; independent of every other subissue. Not a #1840 item: that EPIC's goal is pull request wait time and its Out of Scope excludes workflows off the two critical paths, and a package release push is on neither. | +| 2 | #[To be assigned] - Correct stale documentation references | `docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md` | TODO | F4 and F8. Documentation and dictionary only; independently revertible. Not a #1669 item: that EPIC's documentation duty covers `docs/packages.md`, `packages/AGENTS.md`, the extracted-package tables, and the dependency diagram, and none of these files is one. | +| 3 | #[To be assigned] - Archive closed issue specifications | `docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md` | TODO | F2. Large diff of pure moves; re-verify issue state at merge time. Automating the flow is #1774, which is paused behind EPIC #2003's architecture decision; one manual pass implements no tool and must not inherit that block. | +| 4 | #[To be assigned] - Remove the unquotable character-type generic | `docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md` | TODO | F6. Signature change with a before/after output comparison. The tool appears in EPIC #2003's related artifacts, but that EPIC's scope is the architecture of automation, not the source hygiene of any one tool. | +| 5 | #[To be assigned] - Widen the workflow actions allowlist entry | `docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md` | TODO | A1. Repository administrator action; no file in this repository changes. An issue rather than a table row so that it has an owner, an acceptance criterion, and a visible state. | +| 6 | #[To be assigned] - Resolve the stalled dependency update PRs | `docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md` | TODO | A2. Maintainer action, blocked until #2179 merges; no file in this repository changes. Does not duplicate #2179's fix and does not touch either branch. | -These items leave this EPIC. Each draft names its own parent, and the parent EPIC's subissue table gains its row when the GitHub issue is created — not in this EPIC's pull request. - -| Items | Draft specification | New owner | Ordering | -| ------ | ---------------------------------------------------------------------------------- | ---------------------- | ------------------------------------------------------------------------ | -| F5 | `docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md` | EPIC #2003 | First. The suite must be green before anything runs it in CI. | -| F1, F7 | `docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md` | EPIC #2003 | After F5. | -| R1 | `docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md` | Standalone; no parent | Independent. | - -## Architectural Decisions - -No architectural decision is expected from this EPIC. It produces specifications; every item is a mechanical correction to an existing decision's implementation, the recording of an action outside this repository, or — for C8 — a behavioural defect whose own issue carries its design question. - -- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` (C4 touches only its related-artifacts list, not the decision) -- ADRs to create: `None known` +## Delivery Strategy -If C2's CI placement turns out to be a real choice about where developer-tool tests belong rather than a one-step addition, it is settled inside EPIC #2003's design rather than in a clean-up pull request. That is one of the reasons C1 and C2 move there. +The EPIC delivers specifications, not fixes. Each item is assigned to the EPIC whose own stated scope covers it, and to this EPIC only when no existing EPIC's scope does. The order above reflects dependency and reviewer cost, not priority. -## Delivery Strategy +Three items leave this EPIC. F5 and the F1/F7 pair go to EPIC #2003 - Overhaul: Automation Tools and AI Agent Guardrails, whose In Scope undertakes to evaluate check placement across pre-commit, pre-push, and CI and which explicitly permits the interim project-dictionary formatter that these two repair and invoke; both also meet that EPIC's stated exception for low-risk, additive, independently verifiable work that selects no shared runner, cache, or enforcement platform, so neither waits on its architecture decision. F5 is delivered before F1 and F7, because the suite must be green before anything runs it in CI. R1 leaves without a parent: it is a behavioural change to a user-facing error path, needing its own acceptance criteria and its own regression test, and the configuration overhaul EPIC that would have owned it, #1978, is closed. Each of the three drafts names its own parent, and the adopting EPIC's subissue table gains its row when the GitHub issue is created, not in this EPIC's pull request. -The EPIC delivers specifications, not fixes. The order below reflects dependency and reviewer cost, not priority. +No architectural decision is expected from this EPIC. Every item is a mechanical correction to an existing decision's implementation, an action outside this repository, or — for R1 — a behavioural defect whose own issue carries its design question. For each subissue implementation in this EPIC, the default completion policy is: @@ -179,19 +108,19 @@ For each subissue implementation in this EPIC, the default completion policy is: 3. Re-review acceptance criteria after implementation and update verification evidence. 4. Complete an evidence-based implementation review. Create or update an issue-local retrospective for reusable lessons, material design changes, or meaningful deviations from the plan; otherwise record why one was unnecessary in the issue progress log. -### Phase 1: Clustering +### Phase 1 -- Outcome: every inventory item is assigned to a cluster and a parent, with the assignment argued from the parent's own stated scope. -- Exit criteria: the [Clusters](#clusters) tables are complete, a draft specification exists for every cluster item, and a maintainer has reviewed the clustering. +- Outcome: every inventory item is assigned to a parent, with the assignment argued from that parent's own stated scope, and a draft specification exists for every item. +- Exit criteria: the Friction Inventory and Subissues tables are complete and a maintainer has reviewed the assignment. -### Phase 2: Issue Creation +### Phase 2 - Outcome: the approved drafts become GitHub issues, linked as subissues of their parent EPIC, with each specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number. -- Exit criteria: every row in [Subissues](#subissues) and [Issues Handed to Other Owners](#issues-handed-to-other-owners) carries a real issue number, and EPIC #2003's subissue table carries the two rows it adopted. +- Exit criteria: every row in the Subissues table carries a real issue number, the three handed-away drafts carry theirs, and EPIC #2003's subissue table carries the two rows it adopted. -### Phase 3: Delivery +### Phase 3 -- Outcome: each subissue is implemented and merged in its own pull request, in the ordering its cluster records. +- Outcome: each subissue is implemented and merged in its own pull request, in the ordering recorded above. - Exit criteria: every inventory item is delivered or explicitly closed as won't-fix with the reason recorded in this EPIC's progress log. ## Progress Tracking @@ -202,12 +131,12 @@ For each subissue implementation in this EPIC, the default completion policy is: - [x] Spec reviewed and approved by user/maintainer - [x] GitHub issue [#2190](https://github.com/torrust/torrust-tracker/issues/2190) created and issue number added to this spec - [x] Specification converted from a single implementation issue into a planning-only EPIC -- [ ] Clustering reviewed and approved by a maintainer +- [ ] Parent assignment reviewed and approved by a maintainer - [ ] Spec-only PR merged into `develop` - [ ] GitHub issue #2190 converted to an EPIC issue: title, labels, and body updated to match this specification - [ ] Subissues created from the approved drafts and linked under their parent EPIC - [ ] Subissue specifications moved from `docs/issues/drafts/` to `docs/issues/open/` -- [ ] EPIC #2003's subissue table updated with the two adopted clusters +- [ ] EPIC #2003's subissue table updated with the two adopted items - [ ] Subissue statuses kept up to date in the `Subissues` table - [ ] For each implemented subissue: automatic checks completed and recorded - [ ] For each implemented subissue: manual verification completed and recorded @@ -218,45 +147,49 @@ For each subissue implementation in this EPIC, the default completion policy is: ### Progress Log -- 2026-09-09 14:11 UTC - Specification author - Drafted from a re-verification of every candidate friction against `develop` at `f6b73e29`; eight in-scope items, two maintainer actions, one related-but-separate behavioural defect, two dropped candidates - evidence recorded inline in the Friction Inventory, Maintainer Actions, and Dropped Candidates tables +Append one line per meaningful update. + +- 2026-09-09 14:11 UTC - Specification author - Drafted from a re-verification of every candidate friction against `develop` at `f6b73e29`; eight in-scope items, two maintainer actions, one related-but-separate behavioural defect, two candidates that did not reproduce - evidence recorded inline in the specification - 2026-09-09 15:39 UTC - Specification author - GitHub issue #2190 created from the reviewed draft; specification moved to `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` - https://github.com/torrust/torrust-tracker/issues/2190 -- 2026-09-10 09:30 UTC - Specification author - Restructured after the review on PR #2193 requesting an EPIC with domain-clustered subissues instead of one implementation issue: specification renamed to `EPIC.md` and made planning-only, the eight frictions and two maintainer actions clustered into eight clusters, two clusters handed to EPIC #2003, and nine draft subissue specifications added under `docs/issues/drafts/` - https://github.com/torrust/torrust-tracker/pull/2193#pullrequestreview-5164674289 +- 2026-09-10 09:30 UTC - Specification author - Restructured after the review on PR #2193 requesting an EPIC with domain-clustered subissues instead of one implementation issue: specification renamed to `EPIC.md` and made planning-only, the items clustered by domain, two clusters handed to EPIC #2003, and nine draft subissue specifications added under `docs/issues/drafts/` - https://github.com/torrust/torrust-tracker/pull/2193#pullrequestreview-5164674289 +- 2026-09-10 09:45 UTC - Specification author - Aligned the specification with the shape of EPICs #1840 and #1347: the friction, maintainer-action, related-but-separate, cluster, per-parent-argument, and handoff sections collapsed into one compact Friction Inventory and the Subissues table, each item's evidence left in the subissue draft that owns it, the two candidates that did not reproduce recorded in Out of Scope, and the frontmatter reduced to the model key set - https://github.com/torrust/torrust-tracker/pull/2193 ## Acceptance Criteria -- [ ] AC1: Every item in [Friction Inventory](#friction-inventory) and [Maintainer Actions](#maintainer-actions), and the item in [Related but Separate](#related-but-separate), appears in exactly one row of [Clusters](#clusters) with a named parent. -- [ ] AC2: Each cluster's parent is justified from that parent's own stated scope, and the drafts adopted by another EPIC set `epic:` to that EPIC and name it below their title. -- [ ] AC3: Each draft subissue specification is sized for one focused pull request and carries its own acceptance criteria and verification plan. -- [ ] AC4: This EPIC's pull request changes no file outside `docs/issues/` and `docs/copilot-pr-reviews/`. -- [ ] AC5: Every row in [Subissues](#subissues) and [Issues Handed to Other Owners](#issues-handed-to-other-owners) carries a created GitHub issue number, linked as a subissue of its parent EPIC. -- [ ] AC6: Every inventory item is delivered by a merged subissue pull request, or closed as won't-fix with the reason recorded in the progress log. -- [ ] AC7: The [Dropped Candidates](#dropped-candidates) record survives the restructuring, so the same ground is not re-covered. -- [ ] `linter all` exits with code `0` +- [ ] Every item in the Friction Inventory has exactly one named owner, and each item this EPIC owns appears in exactly one row of the Subissues table. +- [ ] Each owner is justified from that owner's own stated scope, and the drafts adopted by another EPIC set `epic:` to that EPIC and name it below their title. +- [ ] Each draft subissue specification is sized for one focused pull request and carries its own evidence, acceptance criteria, and verification plan. +- [ ] This EPIC's pull request changes no file outside `docs/issues/` and `docs/copilot-pr-reviews/`. +- [ ] Every subissue row and every handed-away draft carries a created GitHub issue number, linked as a subissue of its parent EPIC. +- [ ] Every inventory item is delivered by a merged subissue pull request, or closed as won't-fix with the reason recorded in the progress log. +- [ ] The two candidates that did not reproduce remain recorded, so the same ground is not re-covered. +- [ ] `linter all` exits with code `0`. - [ ] Documentation and governance updates are included when required. ### Acceptance Verification -| AC ID | Status (`TODO`/`DONE`) | Evidence | -| ----- | ---------------------- | ---------------------------------------------------------- | -| AC1 | TODO | [Clusters](#clusters) | -| AC2 | TODO | [Why Each Parent](#why-each-parent) and the draft frontmatter | -| AC3 | TODO | The draft specifications listed in [Clusters](#clusters) | -| AC4 | TODO | {PR link} | -| AC5 | TODO | {issue links} | -| AC6 | TODO | {PR links} | -| AC7 | TODO | [Dropped Candidates](#dropped-candidates) | +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | ------------------------------------------------------------- | +| AC1 | TODO | Friction Inventory and Subissues tables | +| AC2 | TODO | Subissue notes, Delivery Strategy, and the draft frontmatter | +| AC3 | TODO | The draft specifications listed in the Friction Inventory | +| AC4 | TODO | {PR link} | +| AC5 | TODO | {issue links} | +| AC6 | TODO | {PR links} | +| AC7 | TODO | The Out of Scope entries for the two candidates | ## Risks and Trade-offs -- Splitting eight frictions into six subissues plus two adoptions costs more issue-management overhead than one pull request would have. Mitigation: the split is by domain rather than by item, so the count stays close to the number of reviewer contexts involved rather than to the number of defects, and two clusters are absorbed by an EPIC that already has the context. -- Small subissues can stall before they are filed, leaving the inventory as documentation rather than work. Mitigation: AC5 and AC6 make the created issues and their delivery an acceptance condition of this EPIC, and the EPIC stays open until every item is delivered or closed as won't-fix. -- The inventory is a snapshot taken at `f6b73e29`. An item can be fixed or changed by unrelated work before its subissue is implemented. Mitigation: each subissue re-checks its own evidence at implementation time and records a no-change outcome rather than forcing a fix. -- The C5 archival list is the most perishable entry: issues close while a pull request is open. Mitigation: its subissue re-verifies every remaining directory against GitHub at merge time rather than trusting the list drafted here. -- Handing C1 and C2 to EPIC #2003 places them behind that EPIC's review attention, which is directed at an unfinished architecture decision. Mitigation: both clusters are filed under #2003's own exception for additive, independently verifiable work that may proceed before the decision, so neither waits on it. -- Two subissues change no file in this repository, which is an unusual shape for an issue here. Mitigation: their specifications state the no-change outcome explicitly and record a justified no-change decision in the progress log rather than producing an empty commit. +- Risk: splitting eight frictions into six subissues plus two adoptions costs more issue-management overhead than one pull request would have. Mitigation: the split is by domain rather than by item, so the count stays close to the number of reviewer contexts involved rather than to the number of defects, and two items are absorbed by an EPIC that already has the context. +- Risk: small subissues can stall before they are filed, leaving the inventory as documentation rather than work. Mitigation: the created issues and their delivery are acceptance conditions of this EPIC, which stays open until every item is delivered or closed as won't-fix. +- Risk: the inventory is a snapshot taken at `f6b73e29`, and an item can be fixed or changed by unrelated work before its subissue is implemented. Mitigation: each subissue re-checks its own evidence at implementation time and records a no-change outcome rather than forcing a fix. +- Risk: the archival list is the most perishable entry, because issues close while a pull request is open. Mitigation: its subissue re-verifies every remaining directory against GitHub at merge time rather than trusting the list drafted here. +- Risk: handing F5 and F1/F7 to EPIC #2003 places them behind that EPIC's review attention, which is directed at an unfinished architecture decision. Mitigation: both are filed under that EPIC's own exception for additive, independently verifiable work that may proceed before the decision, so neither waits on it. +- Risk: two subissues change no file in this repository, which is an unusual shape for an issue here. Mitigation: their specifications state the no-change outcome explicitly and record a justified no-change decision in the progress log rather than producing an empty commit. ## References +- GitHub EPIC: https://github.com/torrust/torrust-tracker/issues/2190 - Related issues: #1774 (archival automation), #2003 (guardrails and automation EPIC), #2150 (lychee link checker), #2159 (folder-style spec adoption), #2179 (Docker E2E package flag), #2185 (external-link triage) - Related PRs: #2055, #2106, #2180, #2186, #2193 -- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` +- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md` (the stale-references subissue extends its related-artifacts list; it does not touch the decision) From 2e6e9a49cd0911f4a759f2cad15c2456358e118b Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 11:09:51 +0200 Subject: [PATCH 08/13] docs(issues): [#2190] date the progress logs from the commits that made them The restructuring entry in EPIC #2190's progress log, and the drafting entry in each of the nine subissue drafts, carried 09:30 UTC. The commit that made both, `d8a2058e`, is dated 08:43 UTC, and the entry recording this alignment is later still, so the log read out of order. Date each entry from the commit that produced it, so git remains the provenance of the record and the log reads in the order the work happened. --- .../ISSUE.md | 4 ++-- .../2003-run-developer-tool-test-suites-in-ci/ISSUE.md | 4 ++-- .../2190-archive-closed-issue-specifications/ISSUE.md | 4 ++-- .../2190-correct-stale-documentation-references/ISSUE.md | 4 ++-- .../ISSUE.md | 4 ++-- .../2190-remove-unquotable-character-type-generic/ISSUE.md | 4 ++-- .../ISSUE.md | 4 ++-- .../2190-widen-workflow-actions-allowlist-entry/ISSUE.md | 4 ++-- .../configuration-schema-version-error-ordering/ISSUE.md | 4 ++-- docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md | 6 +++--- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md b/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md index 355a9768e..4bb6f6490 100644 --- a/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md +++ b/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -111,7 +111,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F5 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F5 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md b/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md index 05159ac0f..651ddaf24 100644 --- a/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md +++ b/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -112,7 +112,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory items F1 and F7 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory items F1 and F7 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md b/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md index 71b79f016..29a216261 100644 --- a/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md +++ b/docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-archive-closed-issue-specifications/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -106,7 +106,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F2 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F2 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md b/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md index 08bf1d777..2ee143d98 100644 --- a/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md +++ b/docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-correct-stale-documentation-references/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -111,7 +111,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory items F4 and F8 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory items F4 and F8 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md b/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md index 30711dd12..ec14bb4f2 100644 --- a/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md +++ b/docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-narrow-container-workflow-release-branch-trigger/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -102,7 +102,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F3 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F3 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md b/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md index 755cde25a..1f9fbd377 100644 --- a/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md +++ b/docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-remove-unquotable-character-type-generic/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -100,7 +100,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F6 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item F6 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md b/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md index 6edc2e05a..0f42a2e17 100644 --- a/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md +++ b/docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-resolve-stalled-dependency-update-pull-requests/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -102,7 +102,7 @@ This issue produces decisions and evidence rather than a commit of its own. ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item A2 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item A2 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md b/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md index f598d384f..283cb478c 100644 --- a/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md +++ b/docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2190-widen-workflow-actions-allowlist-entry/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -106,7 +106,7 @@ This issue produces evidence rather than a commit. Should it turn out that a fil ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item A1 - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item A1 - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md b/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md index 21f233c90..c3959004a 100644 --- a/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md +++ b/docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/configuration-schema-version-error-ordering/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -106,7 +106,7 @@ Record a justified no-change decision in the task's evidence without creating an ### Progress Log -- 2026-09-10 09:30 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item R1, the one behavioural defect rather than clean-up - https://github.com/torrust/torrust-tracker/issues/2190 +- 2026-09-10 08:43 UTC - Specification author - Drafted from the verified evidence in EPIC #2190; inventory item R1, the one behavioural defect rather than clean-up - https://github.com/torrust/torrust-tracker/issues/2190 ## Acceptance Criteria diff --git a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md index ad6db4b62..0c73cbe2b 100644 --- a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +++ b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md @@ -4,7 +4,7 @@ status: planned github-issue: 2190 spec-path: docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md epic-owner: null -last-updated-utc: 2026-09-10 09:45 +last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue @@ -151,8 +151,8 @@ Append one line per meaningful update. - 2026-09-09 14:11 UTC - Specification author - Drafted from a re-verification of every candidate friction against `develop` at `f6b73e29`; eight in-scope items, two maintainer actions, one related-but-separate behavioural defect, two candidates that did not reproduce - evidence recorded inline in the specification - 2026-09-09 15:39 UTC - Specification author - GitHub issue #2190 created from the reviewed draft; specification moved to `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` - https://github.com/torrust/torrust-tracker/issues/2190 -- 2026-09-10 09:30 UTC - Specification author - Restructured after the review on PR #2193 requesting an EPIC with domain-clustered subissues instead of one implementation issue: specification renamed to `EPIC.md` and made planning-only, the items clustered by domain, two clusters handed to EPIC #2003, and nine draft subissue specifications added under `docs/issues/drafts/` - https://github.com/torrust/torrust-tracker/pull/2193#pullrequestreview-5164674289 -- 2026-09-10 09:45 UTC - Specification author - Aligned the specification with the shape of EPICs #1840 and #1347: the friction, maintainer-action, related-but-separate, cluster, per-parent-argument, and handoff sections collapsed into one compact Friction Inventory and the Subissues table, each item's evidence left in the subissue draft that owns it, the two candidates that did not reproduce recorded in Out of Scope, and the frontmatter reduced to the model key set - https://github.com/torrust/torrust-tracker/pull/2193 +- 2026-09-10 08:43 UTC - Specification author - Restructured after the review on PR #2193 requesting an EPIC with domain-clustered subissues instead of one implementation issue: specification renamed to `EPIC.md` and made planning-only, the items clustered by domain, two clusters handed to EPIC #2003, and nine draft subissue specifications added under `docs/issues/drafts/` - https://github.com/torrust/torrust-tracker/pull/2193#pullrequestreview-5164674289 +- 2026-09-10 09:10 UTC - Specification author - Aligned the specification with the shape of EPICs #1840 and #1347: the friction, maintainer-action, related-but-separate, cluster, per-parent-argument, and handoff sections collapsed into one compact Friction Inventory and the Subissues table, each item's evidence left in the subissue draft that owns it, the two candidates that did not reproduce recorded in Out of Scope, and the frontmatter reduced to the model key set - https://github.com/torrust/torrust-tracker/pull/2193 ## Acceptance Criteria From e18b1f40b9cffdfd32a2f70f01020bed4be6b71e Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 11:32:12 +0200 Subject: [PATCH 09/13] docs(issues): [#2190] conform the EPIC specification to the planning guides The EPIC was reshaped to the spine the maintainers' EPICs use, which left four requirements of the written guides unmet. The create-issue skill's spec-only-PR step requires the specification frontmatter `branch:` to name the `-spec` branch, so it is restored. No maintainer EPIC carries the key, but the example is silent where the skill is explicit, and AGENTS.md fixes the same branch name independently. The same skill requires an `Architectural Decisions` section in a drafted specification and carves out only `Commit Points` for EPICs, so the section is added; the paragraph that had carried its content inside Delivery Strategy moves into it rather than being duplicated. Phase 2 now names the GitHub sub-issues API as the linking mechanism, which the link-subissue-to-parent-issue skill defines, and records that a source artifact gains its `issue: #` marker when the subissue number exists. A draft-path marker added earlier would have to be rewritten immediately, which is what the semantic-link convention warns against. The Acceptance Verification table covered seven of the nine acceptance criteria; the two missing rows are added so every criterion has an ID and an evidence slot. The first three workflow checkpoints take the EPIC template's wording. --- .../EPIC.md | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md index 0c73cbe2b..0e92fb7fe 100644 --- a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +++ b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md @@ -3,13 +3,16 @@ doc-type: epic status: planned github-issue: 2190 spec-path: docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +branch: "2190-maintenance-frictions-cleanup-spec" epic-owner: null last-updated-utc: 2026-09-10 09:10 semantic-links: skill-links: - create-issue + - link-subissue-to-parent-issue related-artifacts: - .github/skills/dev/planning/create-issue/SKILL.md + - .github/skills/dev/github/link-subissue-to-parent-issue/SKILL.md - docs/templates/EPIC.md - docs/issues/open/README.md - docs/issues/drafts/README.md @@ -60,6 +63,13 @@ The inventory itself is still worth keeping. Each entry was verified against the - Local Markdown link health. `linter lychee` exits 0 on `develop` with all local links passing in 0.137 s, and `.github/workflows/docs-lint.yaml:60` already enforces it; external links are wholly owned by #2185. The `.lycheeignore` file named in the original candidate list does not exist and, per #2150, will not: the configuration lives in `lychee.toml` and `.github/lychee-online.toml`. - A second never-run merge-tool suite. No `test-github-merge-symlinks.py` exists on `develop`; `contrib/dev-tools/git/tests/` contains only `test-merge-pull-request.sh`. That Python suite belongs to the unmerged symlink-exceptions work for #2175 and arrives with it. +## Architectural Decisions + +No architectural decision is expected from this EPIC. Every item is a mechanical correction to an existing decision's implementation, an action outside this repository, or — for `R1` — a behavioural defect whose own issue carries its design question. A subissue that discovers an architectural decision during implementation raises it under its own parent rather than here, because this EPIC holds no implementation. + +- Related ADRs: `docs/adrs/20260519000000_define_global_cli_output_contract.md`, which the stale-references subissue extends in its related-artifacts list without touching the decision itself. +- ADRs to create: `None known`. + ## Friction Inventory Every item was verified against `develop` at revision `f6b73e29` on 2026-09-09; each was observed in the tree rather than reported. The evidence for an item — its files, line numbers, commands, and observed output — lives in the draft specification named in its row, which is the source of truth for it. `Owner` is the EPIC that carries the item to delivery. @@ -99,8 +109,6 @@ The EPIC delivers specifications, not fixes. Each item is assigned to the EPIC w Three items leave this EPIC. F5 and the F1/F7 pair go to EPIC #2003 - Overhaul: Automation Tools and AI Agent Guardrails, whose In Scope undertakes to evaluate check placement across pre-commit, pre-push, and CI and which explicitly permits the interim project-dictionary formatter that these two repair and invoke; both also meet that EPIC's stated exception for low-risk, additive, independently verifiable work that selects no shared runner, cache, or enforcement platform, so neither waits on its architecture decision. F5 is delivered before F1 and F7, because the suite must be green before anything runs it in CI. R1 leaves without a parent: it is a behavioural change to a user-facing error path, needing its own acceptance criteria and its own regression test, and the configuration overhaul EPIC that would have owned it, #1978, is closed. Each of the three drafts names its own parent, and the adopting EPIC's subissue table gains its row when the GitHub issue is created, not in this EPIC's pull request. -No architectural decision is expected from this EPIC. Every item is a mechanical correction to an existing decision's implementation, an action outside this repository, or — for R1 — a behavioural defect whose own issue carries its design question. - For each subissue implementation in this EPIC, the default completion policy is: 1. Run automatic checks (`linter all`, relevant tests, pre-push checks when applicable). @@ -115,8 +123,8 @@ For each subissue implementation in this EPIC, the default completion policy is: ### Phase 2 -- Outcome: the approved drafts become GitHub issues, linked as subissues of their parent EPIC, with each specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number. -- Exit criteria: every row in the Subissues table carries a real issue number, the three handed-away drafts carry theirs, and EPIC #2003's subissue table carries the two rows it adopted. +- Outcome: the approved drafts become GitHub issues, attached to their parent EPIC through the GitHub sub-issues API as the `link-subissue-to-parent-issue` skill describes, with each specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number. +- Exit criteria: every row in the Subissues table carries a real issue number, the three handed-away drafts carry theirs, EPIC #2003's subissue table carries the two rows it adopted, and each source artifact a subissue will change carries an `issue: #` marker where the link is high-signal. No `issue-spec:` marker is added to a source artifact before then, because a draft path added now would have to be rewritten as soon as the issue exists. ### Phase 3 @@ -127,14 +135,14 @@ For each subissue implementation in this EPIC, the default completion policy is: ### Workflow Checkpoints -- [x] Folder-style spec drafted and moved to `docs/issues/open/2190-maintenance-frictions-cleanup/` -- [x] Spec reviewed and approved by user/maintainer -- [x] GitHub issue [#2190](https://github.com/torrust/torrust-tracker/issues/2190) created and issue number added to this spec +- [x] Epic spec drafted and moved to `docs/issues/open/2190-maintenance-frictions-cleanup/` +- [x] Epic spec reviewed and approved by user/maintainer +- [x] GitHub epic issue [#2190](https://github.com/torrust/torrust-tracker/issues/2190) created and issue number added to this spec - [x] Specification converted from a single implementation issue into a planning-only EPIC - [ ] Parent assignment reviewed and approved by a maintainer - [ ] Spec-only PR merged into `develop` - [ ] GitHub issue #2190 converted to an EPIC issue: title, labels, and body updated to match this specification -- [ ] Subissues created from the approved drafts and linked under their parent EPIC +- [ ] Subissues created from the approved drafts and attached to their parent EPIC through the GitHub sub-issues API - [ ] Subissue specifications moved from `docs/issues/drafts/` to `docs/issues/open/` - [ ] EPIC #2003's subissue table updated with the two adopted items - [ ] Subissue statuses kept up to date in the `Subissues` table @@ -177,6 +185,8 @@ Append one line per meaningful update. | AC5 | TODO | {issue links} | | AC6 | TODO | {PR links} | | AC7 | TODO | The Out of Scope entries for the two candidates | +| AC8 | TODO | The gate run recorded on this EPIC's spec-only pull request | +| AC9 | TODO | This specification and the subissue specifications it lists | ## Risks and Trade-offs From 6393a4a3ca5b5bf8565f2d0215f88f2a590a4ea8 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 11:32:23 +0200 Subject: [PATCH 10/13] docs(issues): [#2190] mark the adopted parent as proposed in the two handed drafts The create-issue skill sets `epic:` only for an explicitly established subissue and forbids inferring a parent from related issues or topic overlap. These two drafts name EPIC #2003 as parent on an argument from that EPIC's own stated scope, which is stronger than overlap but is not yet accepted by its maintainer, and EPIC #2190 still carries the unticked checkpoint for that review. The parent line now says so, so a reader of the draft alone sees the assignment as proposed rather than settled. The other seven drafts are unaffected: six name the EPIC that produced them, and the parentless draft already states it has no parent and why. --- .../ISSUE.md | 4 ++-- .../drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md b/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md index 4bb6f6490..9ca49bc4d 100644 --- a/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md +++ b/docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:10 +last-updated-utc: 2026-09-10 09:32 semantic-links: skill-links: - create-issue @@ -27,7 +27,7 @@ semantic-links: # Issue #[To be assigned] - Repair the project dictionary formatter test suite -**Parent EPIC:** #2003 - Overhaul: Automation Tools and AI Agent Guardrails +**Parent EPIC:** #2003 - Overhaul: Automation Tools and AI Agent Guardrails. The adoption is argued from that EPIC's own stated scope in EPIC #2190 and is pending its maintainer review; the GitHub issue is created only after that review. ## Goal diff --git a/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md b/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md index 651ddaf24..7af7b82a6 100644 --- a/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md +++ b/docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md @@ -8,7 +8,7 @@ github-issue: null spec-path: docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md branch: null related-pr: null -last-updated-utc: 2026-09-10 09:10 +last-updated-utc: 2026-09-10 09:32 semantic-links: skill-links: - create-issue @@ -29,7 +29,7 @@ semantic-links: # Issue #[To be assigned] - Run the developer-tool test suites in CI -**Parent EPIC:** #2003 - Overhaul: Automation Tools and AI Agent Guardrails +**Parent EPIC:** #2003 - Overhaul: Automation Tools and AI Agent Guardrails. The adoption is argued from that EPIC's own stated scope in EPIC #2190 and is pending its maintainer review; the GitHub issue is created only after that review. ## Goal From bd66fd48eb2a1ce27dc6265ed0e20efc56eca07d Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 11:32:32 +0200 Subject: [PATCH 11/13] docs(issues): [#2190] log the guides conformance pass Record the audit against the planning guides in the progress log and move `last-updated-utc` to the time of the change. --- docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md index 0e92fb7fe..d02acaa01 100644 --- a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +++ b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md @@ -5,7 +5,7 @@ github-issue: 2190 spec-path: docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md branch: "2190-maintenance-frictions-cleanup-spec" epic-owner: null -last-updated-utc: 2026-09-10 09:10 +last-updated-utc: 2026-09-10 09:32 semantic-links: skill-links: - create-issue @@ -161,6 +161,7 @@ Append one line per meaningful update. - 2026-09-09 15:39 UTC - Specification author - GitHub issue #2190 created from the reviewed draft; specification moved to `docs/issues/open/2190-maintenance-frictions-cleanup/ISSUE.md` - https://github.com/torrust/torrust-tracker/issues/2190 - 2026-09-10 08:43 UTC - Specification author - Restructured after the review on PR #2193 requesting an EPIC with domain-clustered subissues instead of one implementation issue: specification renamed to `EPIC.md` and made planning-only, the items clustered by domain, two clusters handed to EPIC #2003, and nine draft subissue specifications added under `docs/issues/drafts/` - https://github.com/torrust/torrust-tracker/pull/2193#pullrequestreview-5164674289 - 2026-09-10 09:10 UTC - Specification author - Aligned the specification with the shape of EPICs #1840 and #1347: the friction, maintainer-action, related-but-separate, cluster, per-parent-argument, and handoff sections collapsed into one compact Friction Inventory and the Subissues table, each item's evidence left in the subissue draft that owns it, the two candidates that did not reproduce recorded in Out of Scope, and the frontmatter reduced to the model key set - https://github.com/torrust/torrust-tracker/pull/2193 +- 2026-09-10 09:32 UTC - Specification author - Audited the EPIC and its nine subissue drafts against the planning guides: restored the `branch:` frontmatter key the spec-only-PR step requires, added the `Architectural Decisions` section, named the GitHub sub-issues API and the `issue: #` marker step in Phase 2, completed the Acceptance Verification table, and marked the EPIC #2003 adoption as proposed in the two handed drafts - https://github.com/torrust/torrust-tracker/pull/2193 ## Acceptance Criteria From fe0b0d56190b4833238d44675e80adf4dfd03e18 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Thu, 10 Sep 2026 11:41:35 +0200 Subject: [PATCH 12/13] docs(issues): [#2003] adopt two inventory items as approved early candidates EPIC #2190's inventory found a developer-tool test suite that has been red on `develop` since it was moved, and three such suites that no orchestrator runs. Both sit inside this EPIC's stated scope for check placement across pre-commit, pre-push, and CI, and both meet its exception for low-risk, additive, independently verifiable work that selects no shared runner, cache, or enforcement platform, so they are recorded here rather than in the EPIC that found them. The rows carry `#[To be assigned]` and their draft paths, the shape EPIC numbers when the issues are created. EPIC #2190's checkpoints are split to match: the rows exist now, the numbers arrive in its Phase 2. The table is re-aligned because the adopted titles are wider than every existing entry. --- .../EPIC.md | 23 +++++++++++-------- .../EPIC.md | 7 +++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md b/docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md index 14a7b6379..dcc648b5d 100644 --- a/docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md +++ b/docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md @@ -236,16 +236,18 @@ work. They may be created and implemented now, including through one spec-only P selecting the EPIC's long-term automation or orchestration architecture. Final GitHub issue creation remains subject to maintainer approval of each draft specification. -| Order | Issue | Local Specification | Why It May Proceed | Dependencies | -| ----- | ---------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | -| 1 | #2155 - Document AI agent orchestration | `docs/issues/closed/2155-2003-document-ai-agent-orchestration/ISSUE.md` | Documents current profiles and creates evidence for future enforcement; selects no enforcement tool. | None | -| 2 | #2156 - Create Markdown template skill | `docs/issues/closed/2156-2003-create-markdown-template-skill/ISSUE.md` | Documentation convention and skill only; does not alter shared execution architecture. | None | -| 3 | #2157 - Require documented Clippy allows | `docs/issues/open/2157-2003-require-documented-clippy-allows/ISSUE.md` | Focused policy and validator at an existing validation tier; prospective baseline remains replaceable. | Existing lint entry points | -| 4 | #2158 - Inventory existing Clippy allows | `docs/issues/open/2158-2003-inventory-existing-clippy-allows/ISSUE.md` | Evidence and incremental remediation; does not redesign the linter runner. | #2157 policy conventions, if merged first | -| 5 | #2159 - Adopt folder-style issue specifications | `docs/issues/open/2159-2003-adopt-folder-style-issue-specs/ISSUE.md` | Documentation, templates, and root ADR only; prospective and reversible for new work. | None | -| 6 | #2160 - Persist independent agent review reports | `docs/issues/closed/2160-2003-persist-independent-agent-review-reports/ISSUE.md` | Profile/template documentation and explicit records; does not enforce transitions technically. | #2155 documentation conventions, if merged first | -| 7 | #2185 - Triage advisory external-link check findings | `docs/issues/open/2185-2003-triage-advisory-external-link-check-findings/ISSUE.md` | Evidence-driven refinement of an existing advisory workflow; does not redesign the linter or workflow runner. | #2162 external-link workflow | -| 8 | #2219 - Unify PR review-processing workflow | `docs/issues/open/2219-2003-unify-pr-review-processing/ISSUE.md` | Low-risk, additive, independently verifiable local/CI formatting parity plus skill, template, and review-audit process improvements; selects no shared automation architecture. | Existing pre-commit, pre-push, and PR-review entry points | +| Order | Issue | Local Specification | Why It May Proceed | Dependencies | +| ----- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | +| 1 | #2155 - Document AI agent orchestration | `docs/issues/closed/2155-2003-document-ai-agent-orchestration/ISSUE.md` | Documents current profiles and creates evidence for future enforcement; selects no enforcement tool. | None | +| 2 | #2156 - Create Markdown template skill | `docs/issues/closed/2156-2003-create-markdown-template-skill/ISSUE.md` | Documentation convention and skill only; does not alter shared execution architecture. | None | +| 3 | #2157 - Require documented Clippy allows | `docs/issues/open/2157-2003-require-documented-clippy-allows/ISSUE.md` | Focused policy and validator at an existing validation tier; prospective baseline remains replaceable. | Existing lint entry points | +| 4 | #2158 - Inventory existing Clippy allows | `docs/issues/open/2158-2003-inventory-existing-clippy-allows/ISSUE.md` | Evidence and incremental remediation; does not redesign the linter runner. | #2157 policy conventions, if merged first | +| 5 | #2159 - Adopt folder-style issue specifications | `docs/issues/open/2159-2003-adopt-folder-style-issue-specs/ISSUE.md` | Documentation, templates, and root ADR only; prospective and reversible for new work. | None | +| 6 | #2160 - Persist independent agent review reports | `docs/issues/closed/2160-2003-persist-independent-agent-review-reports/ISSUE.md` | Profile/template documentation and explicit records; does not enforce transitions technically. | #2155 documentation conventions, if merged first | +| 7 | #2185 - Triage advisory external-link check findings | `docs/issues/open/2185-2003-triage-advisory-external-link-check-findings/ISSUE.md` | Evidence-driven refinement of an existing advisory workflow; does not redesign the linter or workflow runner. | #2162 external-link workflow | +| 8 | #2219 - Unify PR review-processing workflow | `docs/issues/open/2219-2003-unify-pr-review-processing/ISSUE.md` | Low-risk, additive, independently verifiable local/CI formatting parity plus skill, template, and review-audit process improvements; selects no shared automation architecture. | Existing pre-commit, pre-push, and PR-review entry points | +| 9 | #[To be assigned] - Repair the project dictionary formatter test suite | `docs/issues/drafts/2003-repair-project-dictionary-formatter-test-suite/ISSUE.md` | Repairs an existing suite for the interim dictionary formatter this EPIC already permits; selects no runner, cache, or enforcement platform. | None | +| 10 | #[To be assigned] - Run the developer-tool test suites in CI | `docs/issues/drafts/2003-run-developer-tool-test-suites-in-ci/ISSUE.md` | Adds one replaceable CI invocation of suites that already exist, and corrects the notes it falsifies; does not prejudge the execution-tier decision. | Subissue 9, which must merge first | ## Delivery Strategy @@ -351,6 +353,7 @@ For each completed subissue in this EPIC, the default completion policy is: specification to `docs/issues/open/2003-overhaul-guardrails-and-automation/` - 2026-07-22 00:00 UTC - josecelano - Approved a narrowly scoped interim project dictionary formatter; it may be replaced or refactored after the EPIC design decision +- 2026-09-10 09:32 UTC - Specification author - Adopted two candidates from the inventory of EPIC #2190 into the approved early implementation candidates: repair the project dictionary formatter test suite, and run the developer-tool test suites in CI - https://github.com/torrust/torrust-tracker/pull/2193 ## Acceptance Criteria diff --git a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md index d02acaa01..9f0569c32 100644 --- a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +++ b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md @@ -47,7 +47,7 @@ The inventory itself is still worth keeping. Each entry was verified against the - Assign every inventory item to the EPIC whose own stated scope covers it, and record that assignment. - Produce one draft subissue specification per item or group of items sharing a domain, each sized for one focused pull request and each naming its parent EPIC. - Create the GitHub subissues from the approved drafts, link them under their parent EPIC, and move each specification into `docs/issues/open/` under the naming convention. -- Hand the two developer-tool-check items to EPIC #2003, including the row each needs in its subissue table. +- Hand the two developer-tool-check items to EPIC #2003, adding the row each needs to that EPIC's approved-early-candidates table. - Track completion of the subissues this EPIC owns until every inventory item is delivered or explicitly closed as won't-fix. ### Out of Scope @@ -124,7 +124,7 @@ For each subissue implementation in this EPIC, the default completion policy is: ### Phase 2 - Outcome: the approved drafts become GitHub issues, attached to their parent EPIC through the GitHub sub-issues API as the `link-subissue-to-parent-issue` skill describes, with each specification moved from `docs/issues/drafts/` to `docs/issues/open/` under its assigned number. -- Exit criteria: every row in the Subissues table carries a real issue number, the three handed-away drafts carry theirs, EPIC #2003's subissue table carries the two rows it adopted, and each source artifact a subissue will change carries an `issue: #` marker where the link is high-signal. No `issue-spec:` marker is added to a source artifact before then, because a draft path added now would have to be rewritten as soon as the issue exists. +- Exit criteria: every row in the Subissues table carries a real issue number, the three handed-away drafts carry theirs, EPIC #2003's two adopted rows carry their assigned numbers, and each source artifact a subissue will change carries an `issue: #` marker where the link is high-signal. No `issue-spec:` marker is added to a source artifact before then, because a draft path added now would have to be rewritten as soon as the issue exists. ### Phase 3 @@ -144,7 +144,8 @@ For each subissue implementation in this EPIC, the default completion policy is: - [ ] GitHub issue #2190 converted to an EPIC issue: title, labels, and body updated to match this specification - [ ] Subissues created from the approved drafts and attached to their parent EPIC through the GitHub sub-issues API - [ ] Subissue specifications moved from `docs/issues/drafts/` to `docs/issues/open/` -- [ ] EPIC #2003's subissue table updated with the two adopted items +- [x] EPIC #2003's approved-early-candidates table carries the two adopted rows +- [ ] Those two rows carry their assigned issue numbers - [ ] Subissue statuses kept up to date in the `Subissues` table - [ ] For each implemented subissue: automatic checks completed and recorded - [ ] For each implemented subissue: manual verification completed and recorded From 7f4943be8c8c89ab9900201faaa8fb6f05b373d1 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Mon, 14 Sep 2026 18:55:32 +0200 Subject: [PATCH 13/13] docs(issues): [#2190] record the EPIC assignment The `epic-owner` frontmatter field mirrors the GitHub assignee. EPICs #1347, #1840 and #2003 each carry `epic-owner: josecelano` and are each assigned to josecelano on GitHub, and every other EPIC specification in this repository that names an owner names the same one. #2190 now has an assignee, so the field reads `da2ce7` rather than `null`, and the specification alone tells a reader who carries the EPIC. Nothing else follows from it yet. The create-issue skill requires a specification to be reviewed and approved before its GitHub issue is created, so the nine subissue drafts this EPIC produced wait for this specification to merge. No progress-log line accompanies the change. No EPIC in this repository records an assignment or an ownership change in its Progress Log, so a line here would introduce a log convention the maintainers' own specifications do not use. --- docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md index 9f0569c32..cb631cbf7 100644 --- a/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md +++ b/docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md @@ -4,8 +4,8 @@ status: planned github-issue: 2190 spec-path: docs/issues/open/2190-maintenance-frictions-cleanup/EPIC.md branch: "2190-maintenance-frictions-cleanup-spec" -epic-owner: null -last-updated-utc: 2026-09-10 09:32 +epic-owner: da2ce7 +last-updated-utc: 2026-09-14 16:54 semantic-links: skill-links: - create-issue