diff --git a/.github/skills/dev/git-workflow/commit-changes/SKILL.md b/.github/skills/dev/git-workflow/commit-changes/SKILL.md index e76609e30..34e1164ba 100644 --- a/.github/skills/dev/git-workflow/commit-changes/SKILL.md +++ b/.github/skills/dev/git-workflow/commit-changes/SKILL.md @@ -128,8 +128,10 @@ Verify these by hand before committing: `docs/` pages reflect the change - **`AGENTS.md` updated**: if architecture, package structure, or key workflows changed, the relevant `AGENTS.md` file is updated -- **New technical terms added to `project-words.txt`**: any new jargon or identifiers that - cspell does not know about are added alphabetically +- **New technical terms added to `project-words.txt`**: run + `./contrib/dev-tools/git/format-project-words.sh` after adding jargon or identifiers that cspell + does not know. The pre-commit hook does this automatically, aborting for deliberate restaging if + it changes the dictionary. ### Debugging a Failing Run diff --git a/.github/skills/dev/git-workflow/run-linters/SKILL.md b/.github/skills/dev/git-workflow/run-linters/SKILL.md index 5b94b6f0d..0f817c55c 100644 --- a/.github/skills/dev/git-workflow/run-linters/SKILL.md +++ b/.github/skills/dev/git-workflow/run-linters/SKILL.md @@ -125,8 +125,9 @@ taplo fmt **/*.toml # Auto-fix TOML formatting ### Spell Check Errors (cspell) -For legitimate technical terms not in dictionaries, add them to `project-words.txt` -(alphabetical order, one per line). +For legitimate technical terms not in dictionaries, add them to `project-words.txt` (one per line) +and run `./contrib/dev-tools/git/format-project-words.sh`. The pre-commit hook runs the formatter +automatically and requests restaging if it changes the dictionary. ### Shell Script Errors (shellcheck) diff --git a/.github/skills/dev/git-workflow/run-linters/references/linters.md b/.github/skills/dev/git-workflow/run-linters/references/linters.md index 40b3ee5fb..bd82190f1 100644 --- a/.github/skills/dev/git-workflow/run-linters/references/linters.md +++ b/.github/skills/dev/git-workflow/run-linters/references/linters.md @@ -56,7 +56,9 @@ Key formatting settings: **Dictionary**: `project-words.txt` **Run**: `linter cspell` -Add technical terms to `project-words.txt` (alphabetical order, one per line). +Add technical terms to `project-words.txt` (one per line), then run +`./contrib/dev-tools/git/format-project-words.sh`. The formatter uses `LC_ALL=C sort -u`; +the pre-commit hook runs it automatically and requests restaging if it changes the dictionary. ## Configuration Linters diff --git a/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md b/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md index b53f4df93..07a807514 100644 --- a/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md +++ b/.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md @@ -47,9 +47,22 @@ TORRUST_GIT_HOOKS_LOG_DIR=.tmp ./contrib/dev-tools/git/hooks/pre-commit.sh The script runs these steps in order: -1. `cargo machete` - unused dependency check -2. `linter all` - all linters (markdown, YAML, TOML, clippy, rustfmt, shellcheck, cspell) -3. `cargo test --doc --workspace` - documentation tests +1. `./contrib/dev-tools/git/format-project-words.sh` - formats `project-words.txt` with + `LC_ALL=C sort -u` +2. `cargo machete --with-metadata` - unused dependency check +3. `cargo deny check bans` - workspace layer-boundary dependency check +4. `linter all` - all linters (markdown, YAML, TOML, clippy, rustfmt, shellcheck, cspell) +5. `cargo test --doc --workspace` - documentation tests + +If the formatter changes the dictionary, the hook exits non-zero before the verification steps. +Stage `project-words.txt` and retry the commit. Run the formatter independently with: + +```bash +./contrib/dev-tools/git/format-project-words.sh +``` + +This is an interim action related to EPIC #2003 and may be replaced or refactored after its +automation design decision. ## Output Modes @@ -117,7 +130,8 @@ Verify these by hand before committing: - **Self-review the diff**: read through `git diff --staged` for debug artifacts or unintended changes - **Documentation updated**: if public API or behaviour changed, doc comments and `docs/` pages reflect it - **`AGENTS.md` updated**: if architecture or key workflows changed, the relevant `AGENTS.md` is updated -- **New technical terms in `project-words.txt`**: new jargon added alphabetically +- **New technical terms in `project-words.txt`**: run the formatter after adding new jargon; the + hook will also format it automatically and request restaging when needed - **Branch name validation**: if the branch uses an issue-number prefix (e.g. `42-some-description`), verify that `docs/issues/open/` contains a matching spec file or directory. This prevents committing under a non-existent, closed, or wrong issue number. diff --git a/contrib/dev-tools/git/format-project-words.sh b/contrib/dev-tools/git/format-project-words.sh new file mode 100755 index 000000000..9634c70cf --- /dev/null +++ b/contrib/dev-tools/git/format-project-words.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# Format the repository cspell dictionary with deterministic ordering and exact de-duplication. + +set -uo pipefail + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +PROJECT_ROOT=$(cd -- "${SCRIPT_DIR}/../../.." && pwd) +DICTIONARY_PATH="${PROJECT_ROOT}/project-words.txt" + +if [[ ! -f "${DICTIONARY_PATH}" ]]; then + printf 'Error: project dictionary not found: %s\n' "${DICTIONARY_PATH}" >&2 + exit 2 +fi + +if ! temporary_dictionary=$(mktemp "${DICTIONARY_PATH}.XXXXXX"); then + printf 'Error: failed to create a temporary project dictionary: %s\n' "${DICTIONARY_PATH}" >&2 + exit 2 +fi + +trap 'rm -f "${temporary_dictionary}"' EXIT + +if ! cp -p "${DICTIONARY_PATH}" "${temporary_dictionary}"; then + printf 'Error: failed to preserve project dictionary metadata: %s\n' "${DICTIONARY_PATH}" >&2 + exit 2 +fi + +if ! LC_ALL=C sort -u "${DICTIONARY_PATH}" >"${temporary_dictionary}"; then + printf 'Error: failed to format project dictionary: %s\n' "${DICTIONARY_PATH}" >&2 + exit 2 +fi + +if cmp -s "${DICTIONARY_PATH}" "${temporary_dictionary}"; then + printf 'project-words.txt is already formatted.\n' + exit 0 +fi + +if ! mv "${temporary_dictionary}" "${DICTIONARY_PATH}"; then + printf 'Error: failed to update project dictionary: %s\n' "${DICTIONARY_PATH}" >&2 + exit 2 +fi + +printf 'Formatted project-words.txt with LC_ALL=C sort -u.\n' +printf "Stage 'project-words.txt' and retry the commit.\n" +exit 1 \ No newline at end of file diff --git a/contrib/dev-tools/git/hooks/pre-commit.sh b/contrib/dev-tools/git/hooks/pre-commit.sh index 477c46c19..9fc4c4509 100755 --- a/contrib/dev-tools/git/hooks/pre-commit.sh +++ b/contrib/dev-tools/git/hooks/pre-commit.sh @@ -9,6 +9,9 @@ # AI agents: set a per-command timeout of at least 3 minutes before invoking this script. # # All steps must pass (exit 0) before committing. +# The formatter is an intentionally small interim action while EPIC #2003 determines +# the repository's long-term automation architecture. It exits 1 after rewriting the +# dictionary so this hook aborts and the contributor can deliberately stage the change. # # TODO: Implement branch-name validation in the Rust git-hooks binary (#1843). # When the branch uses an issue-number prefix (e.g. "42-some-description"), verify that @@ -24,6 +27,7 @@ set -uo pipefail # Each step: "description|command" declare -a STEPS=( + "Formatting project dictionary|./contrib/dev-tools/git/format-project-words.sh" "Checking for unused dependencies (cargo machete --with-metadata)|cargo machete --with-metadata" "Checking workspace layer boundary bans (cargo deny check bans)|cargo deny check bans" "Running all linters|linter all" @@ -329,6 +333,7 @@ TOTAL_STEPS=${#STEPS[@]} overall_status="pass" exit_code=0 failed_step_name="" +failed_step_exit_code=0 if [[ "${FORMAT}" == "text" ]]; then echo "Running pre-commit checks..." @@ -337,10 +342,14 @@ fi for i in "${!STEPS[@]}"; do IFS='|' read -r description command <<< "${STEPS[$i]}" - if ! run_step $((i + 1)) "${TOTAL_STEPS}" "${description}" "${command}"; then + if run_step $((i + 1)) "${TOTAL_STEPS}" "${description}" "${command}"; then + step_exit_code=0 + else + step_exit_code=$? overall_status="fail" - exit_code=1 + exit_code=${step_exit_code} failed_step_name="${description}" + failed_step_exit_code=${step_exit_code} break fi done @@ -364,6 +373,9 @@ fi echo echo "==========================================" echo "FAILED: Pre-commit checks failed!" +if [[ "${failed_step_name}" == "Formatting project dictionary" && "${failed_step_exit_code}" -eq 1 ]]; then + echo "The formatter changed project-words.txt. Stage 'project-words.txt' and retry the commit." +fi echo "Fix the errors above before committing." echo "==========================================" exit 1 diff --git a/contrib/dev-tools/git/tests/test-format-project-words.sh b/contrib/dev-tools/git/tests/test-format-project-words.sh new file mode 100755 index 000000000..62eeb8498 --- /dev/null +++ b/contrib/dev-tools/git/tests/test-format-project-words.sh @@ -0,0 +1,206 @@ +#!/usr/bin/env bash +# Integration tests for the project dictionary formatter and pre-commit orchestration. + +set -euo pipefail + +PROJECT_ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../../../.." && pwd) +TEST_DIRECTORY=$(mktemp -d "${TMPDIR:-/tmp}/test-format-project-words.XXXXXX") +trap 'rm -rf "${TEST_DIRECTORY}"' EXIT + +create_fixture() { + local fixture_name=$1 + local fixture_root="${TEST_DIRECTORY}/${fixture_name}" + + mkdir -p "${fixture_root}/contrib/dev-tools/git/hooks" "${fixture_root}/bin" "${fixture_root}/logs" + cp "${PROJECT_ROOT}/contrib/dev-tools/git/format-project-words.sh" "${fixture_root}/contrib/dev-tools/git/" + cp "${PROJECT_ROOT}/contrib/dev-tools/git/hooks/pre-commit.sh" "${fixture_root}/contrib/dev-tools/git/hooks/" + chmod +x \ + "${fixture_root}/contrib/dev-tools/git/format-project-words.sh" \ + "${fixture_root}/contrib/dev-tools/git/hooks/pre-commit.sh" + + printf '%s\n' "${fixture_root}" +} + +create_successful_command_stubs() { + local fixture_root=$1 + + cat >"${fixture_root}/bin/cargo" <<'EOF' +#!/usr/bin/env bash +printf 'cargo %s\n' "$*" >>"${TEST_COMMAND_LOG}" +EOF + cat >"${fixture_root}/bin/linter" <<'EOF' +#!/usr/bin/env bash +printf 'linter %s\n' "$*" >>"${TEST_COMMAND_LOG}" +EOF + chmod +x "${fixture_root}/bin/cargo" "${fixture_root}/bin/linter" +} + +it_should_sort_and_remove_exact_duplicates_when_dictionary_requires_formatting() { + # Arrange + local fixture_root + fixture_root=$(create_fixture "formatter-changed") + printf 'zebra\nAlpha\nalpha\nAlpha\n' >"${fixture_root}/project-words.txt" + + # Act + if "${fixture_root}/contrib/dev-tools/git/format-project-words.sh" >"${fixture_root}/formatter-output.txt" 2>&1; then + printf 'Expected formatter to report a changed dictionary.\n' >&2 + return 1 + fi + + # Assert + diff -u "${fixture_root}/project-words.txt" <(printf 'Alpha\nalpha\nzebra\n') + grep -F -q 'Formatted project-words.txt with LC_ALL=C sort -u.' "${fixture_root}/formatter-output.txt" +} + +it_should_report_success_when_dictionary_is_already_formatted() { + # Arrange + local fixture_root + fixture_root=$(create_fixture "formatter-unchanged") + printf 'Alpha\nalpha\nzebra\n' >"${fixture_root}/project-words.txt" + + # Act + "${fixture_root}/contrib/dev-tools/git/format-project-words.sh" >"${fixture_root}/formatter-output.txt" + + # Assert + grep -F -q 'project-words.txt is already formatted.' "${fixture_root}/formatter-output.txt" +} + +it_should_report_a_temp_file_creation_failure() { + # Arrange + local fixture_root + fixture_root=$(create_fixture "formatter-mktemp-failure") + printf 'Alpha\nzebra\n' >"${fixture_root}/project-words.txt" + cat >"${fixture_root}/bin/mktemp" <<'EOF' +#!/usr/bin/env bash +exit 1 +EOF + chmod +x "${fixture_root}/bin/mktemp" + + # Act + if PATH="${fixture_root}/bin:${PATH}" "${fixture_root}/contrib/dev-tools/git/format-project-words.sh" >"${fixture_root}/formatter-output.txt" 2>&1; then + printf 'Expected formatter to fail when it cannot create its temporary dictionary.\n' >&2 + return 1 + fi + + # Assert + grep -F -q 'Error: failed to create a temporary project dictionary:' "${fixture_root}/formatter-output.txt" +} + +it_should_abort_pre_commit_and_request_restaging_when_dictionary_is_formatted() { + # Arrange + local fixture_root + fixture_root=$(create_fixture "hook-changed") + printf 'zebra\nAlpha\nAlpha\n' >"${fixture_root}/project-words.txt" + create_successful_command_stubs "${fixture_root}" + + # Act + if ( + cd "${fixture_root}" || exit + PATH="${fixture_root}/bin:${PATH}" \ + TEST_COMMAND_LOG="${fixture_root}/commands.log" \ + TORRUST_GIT_HOOKS_LOG_DIR="${fixture_root}/logs" \ + ./contrib/dev-tools/git/hooks/pre-commit.sh >"${fixture_root}/hook-output.txt" 2>&1 + ); then + printf 'Expected pre-commit hook to abort after formatting the dictionary.\n' >&2 + return 1 + fi + + # Assert + diff -u "${fixture_root}/project-words.txt" <(printf 'Alpha\nzebra\n') + grep -F -q "Stage 'project-words.txt' and retry the commit" "${fixture_root}/hook-output.txt" + [[ ! -e "${fixture_root}/commands.log" ]] +} + +it_should_not_mislabel_log_creation_failures_as_dictionary_changes() { + # Arrange + local fixture_root + fixture_root=$(create_fixture "hook-log-mktemp-failure") + printf 'Alpha\nzebra\n' >"${fixture_root}/project-words.txt" + create_successful_command_stubs "${fixture_root}" + cat >"${fixture_root}/bin/mktemp" <<'EOF' +#!/usr/bin/env bash +if [[ "$1" == *pre-commit-* ]]; then + exit 1 +fi +exec /usr/bin/mktemp "$@" +EOF + chmod +x "${fixture_root}/bin/mktemp" + + # Act + if ( + cd "${fixture_root}" || exit + PATH="${fixture_root}/bin:${PATH}" \ + TEST_COMMAND_LOG="${fixture_root}/commands.log" \ + TORRUST_GIT_HOOKS_LOG_DIR="${fixture_root}/logs" \ + ./contrib/dev-tools/git/hooks/pre-commit.sh >"${fixture_root}/hook-output.txt" 2>&1 + ); then + printf 'Expected pre-commit hook to fail when it cannot create a step log.\n' >&2 + return 1 + fi + + # Assert + grep -F -q "Error: failed to create a temporary log file in '${fixture_root}/logs'." "${fixture_root}/hook-output.txt" + ! grep -F -q "The formatter changed project-words.txt." "${fixture_root}/hook-output.txt" +} + +it_should_report_infrastructure_failures_with_their_exit_code_in_json() { + # Arrange + local fixture_root + fixture_root=$(create_fixture "hook-log-mktemp-failure-json") + printf 'Alpha\nzebra\n' >"${fixture_root}/project-words.txt" + create_successful_command_stubs "${fixture_root}" + cat >"${fixture_root}/bin/mktemp" <<'EOF' +#!/usr/bin/env bash +if [[ "$1" == *pre-commit-* ]]; then + exit 2 +fi +exec /usr/bin/mktemp "$@" +EOF + chmod +x "${fixture_root}/bin/mktemp" + + # Act + if ( + cd "${fixture_root}" || exit + PATH="${fixture_root}/bin:${PATH}" \ + TEST_COMMAND_LOG="${fixture_root}/commands.log" \ + TORRUST_GIT_HOOKS_LOG_DIR="${fixture_root}/logs" \ + ./contrib/dev-tools/git/hooks/pre-commit.sh --format=json >"${fixture_root}/hook-output.txt" 2>&1 + ); then + printf 'Expected pre-commit hook to fail when it cannot create a step log.\n' >&2 + return 1 + fi + + # Assert + grep -F -q '"exit_code": 2' "${fixture_root}/hook-output.txt" +} + +it_should_continue_pre_commit_checks_when_dictionary_is_already_formatted() { + # Arrange + local fixture_root + fixture_root=$(create_fixture "hook-unchanged") + printf 'Alpha\nzebra\n' >"${fixture_root}/project-words.txt" + create_successful_command_stubs "${fixture_root}" + + # Act + ( + cd "${fixture_root}" || exit + PATH="${fixture_root}/bin:${PATH}" \ + TEST_COMMAND_LOG="${fixture_root}/commands.log" \ + TORRUST_GIT_HOOKS_LOG_DIR="${fixture_root}/logs" \ + ./contrib/dev-tools/git/hooks/pre-commit.sh >"${fixture_root}/hook-output.txt" + ) + + # Assert + [[ $(wc -l <"${fixture_root}/commands.log") -eq 4 ]] + grep -F -q 'SUCCESS: All pre-commit checks passed!' "${fixture_root}/hook-output.txt" +} + +it_should_sort_and_remove_exact_duplicates_when_dictionary_requires_formatting +it_should_report_success_when_dictionary_is_already_formatted +it_should_report_a_temp_file_creation_failure +it_should_abort_pre_commit_and_request_restaging_when_dictionary_is_formatted +it_should_not_mislabel_log_creation_failures_as_dictionary_changes +it_should_report_infrastructure_failures_with_their_exit_code_in_json +it_should_continue_pre_commit_checks_when_dictionary_is_already_formatted + +printf 'All formatter and pre-commit hook tests passed.\n' \ No newline at end of file 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 d668a7360..4db9d4f69 100644 --- a/docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md +++ b/docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md @@ -5,7 +5,7 @@ status: planned github-issue: 2003 spec-path: docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md epic-owner: josecelano -last-updated-utc: 2026-07-20 00:00 +last-updated-utc: 2026-07-22 00:00 semantic-links: skill-links: - create-issue @@ -161,6 +161,11 @@ build actions needed by its checks. - Add a required deterministic check that verifies `project-words.txt` uses one documented ordering rule and contains no duplicate entries. Decide its package and execution tier through the EPIC design rather than coupling it to the tracker library. +- Permit the narrowly scoped interim formatter described by + [`2019-automatically-format-project-dictionary/ISSUE.md`](../2019-automatically-format-project-dictionary/ISSUE.md). + It supplies immediate developer feedback but does not select the EPIC's long-term architecture, + execution tier, or check/action contract, and may be replaced or refactored after the design + decision. - Re-evaluate #1843, #1774, and #1768 against the resulting evidence and recommend whether each should proceed unchanged, be re-scoped, be split, or be superseded. - Present the evidence and options for maintainer review before selecting a full design. @@ -174,7 +179,8 @@ build actions needed by its checks. ### Out of Scope - Implementing, migrating, or consolidating automation tools or checks before the design decision - and implementation subissues are approved. + and implementation subissues are approved, except for the explicitly approved interim project + dictionary formatter linked in Scope. - Prescribing a `workspace-tools` crate, a single Rust binary, Bash scripts, a task runner, or any other tool shape before alternatives are compared and reviewed. - Prototyping architecture tests before the research identifies a question that requires a @@ -317,6 +323,8 @@ For each completed subissue in this EPIC, the default completion policy is: - 2026-07-20 00:00 UTC - josecelano - Approved the draft EPIC and its supporting artifacts - 2026-07-20 00:00 UTC - GitHub Operator - Created EPIC #2003 and moved the approved local 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 ## Acceptance Criteria diff --git a/docs/issues/open/2019-automatically-format-project-dictionary/ISSUE.md b/docs/issues/open/2019-automatically-format-project-dictionary/ISSUE.md new file mode 100644 index 000000000..7c204e527 --- /dev/null +++ b/docs/issues/open/2019-automatically-format-project-dictionary/ISSUE.md @@ -0,0 +1,159 @@ +--- +doc-type: issue +issue-type: enhancement +status: open +priority: p2 +github-issue: 2019 +spec-path: docs/issues/open/2019-automatically-format-project-dictionary/ISSUE.md +branch: "2019-automatically-format-project-dictionary" +related-pr: 2020 +last-updated-utc: 2026-07-22 00:00 +semantic-links: + skill-links: + - create-issue + related-artifacts: + - .github/skills/dev/planning/create-issue/SKILL.md + - contrib/dev-tools/git/format-project-words.sh + - contrib/dev-tools/git/hooks/pre-commit.sh + - docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md + - project-words.txt +--- + + + +# Issue #2019 - Automatically format the project dictionary + +## Goal + +Make `project-words.txt` consistently sorted and free of exact duplicate entries without requiring contributors or AI agents to edit its ordering manually. + +## Background + +`project-words.txt` is the custom cspell dictionary. Its intended alphabetical ordering is documented but not enforced by `linter all` or the pre-commit hook, so pull-request reviews repeatedly identify unsorted entries. This issue delivers a small, immediately useful interim formatter while EPIC #2003 evaluates the long-term automation and guardrail architecture. It must not constrain that future design: the EPIC may replace or refactor this implementation after its design decision. + +## Scope + +### In Scope + +- Add `contrib/dev-tools/git/format-project-words.sh`, an independently runnable formatter that applies `LC_ALL=C sort -u` to `project-words.txt`. +- Invoke the formatter from the pre-commit hook. +- Detect when formatting changes the dictionary and abort the commit with clear restaging instructions. +- Document the automatic behavior and manual formatting command in the relevant pre-commit workflow guidance. +- Ensure the committed dictionary is formatted by the new command. + +### Out of Scope + +- Changing the cspell configuration or its accepted dictionaries. +- Case-insensitive de-duplication or normalization of dictionary entries. +- Reordering unrelated project files. +- Selecting the long-term repository automation or guardrail architecture; that decision belongs to EPIC #2003. +- Treating this interim script as a constraint on EPIC #2003's future implementation. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| T1 | DONE | Add an independently runnable dictionary formatter | `contrib/dev-tools/git/format-project-words.sh` applies `LC_ALL=C sort -u` to `project-words.txt` and reports whether it changed the file. | +| T2 | DONE | Invoke the formatter from the pre-commit hook | The hook calls the formatter before verification steps and retains its role as orchestration scaffolding. | +| T3 | DONE | Abort when the formatter changes the dictionary | The commit stops and tells the contributor to stage `project-words.txt` and retry, preventing a stale index from being committed. | +| T4 | DONE | Update workflow documentation | The documentation describes automatic formatting, the helper command, and the interim relationship to EPIC #2003; it no longer requires manual alphabetical-order review. | +| T5 | DONE | Add or update automated tests for formatter and hook behavior | `contrib/dev-tools/git/tests/test-format-project-words.sh` covers formatter and hook behavior for changed and unchanged dictionaries. | +| T6 | DONE | Format and verify the dictionary | The checked-in file is formatted; focused tests and the required pre-commit validation gate pass. | + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Spec drafted in `docs/issues/drafts/` +- [x] Spec reviewed and approved by user/maintainer +- [x] GitHub issue created and issue number added to this spec +- [ ] (Optional, recommended for complex issues) Spec-only PR merged into `develop` before implementation +- [x] Implementation completed +- [x] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [x] Manual verification scenarios executed and recorded (status + evidence) +- [x] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] 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 + +Append one line per meaningful update. + +- 2026-07-22 00:00 UTC - GitHub Copilot - Created draft specification for review - `docs/issues/drafts/automatically-format-project-dictionary.md` +- 2026-07-22 00:00 UTC - josecelano - Approved an interim standalone formatter and hook integration while EPIC #2003 determines the long-term automation design - draft updated +- 2026-07-22 00:00 UTC - GitHub Operator - Created issue #2019 - https://github.com/torrust/torrust-tracker/issues/2019 +- 2026-07-22 00:00 UTC - GitHub Copilot - Implemented the standalone formatter, pre-commit orchestration, focused shell tests, and synchronized workflow guidance; reviewed the linked `create-issue` skill with no process change required +- 2026-07-22 00:00 UTC - GitHub Copilot - Verified focused formatter and hook tests, the standalone formatter, and `TORRUST_GIT_HOOKS_LOG_DIR=.tmp ./contrib/dev-tools/git/hooks/pre-commit.sh --format=json`; all passed +- 2026-07-22 00:00 UTC - GitHub Copilot - Verified `TORRUST_GIT_HOOKS_LOG_DIR=.tmp ./contrib/dev-tools/git/hooks/pre-push.sh --format=json`; all nightly checks, documentation build, and stable workspace tests passed +- 2026-07-22 00:00 UTC - GitHub Copilot - Re-reviewed the acceptance criteria against the implementation and recorded the existing verification evidence +- 2026-07-22 00:00 UTC - GitHub Copilot - Moved the specification into the documented issue-folder layout after review feedback + +## Acceptance Criteria + +- [x] AC1: `contrib/dev-tools/git/format-project-words.sh` applies `LC_ALL=C sort -u` to `project-words.txt`, preserving distinct entries that differ only by case. +- [x] AC2: If formatting modifies `project-words.txt`, the pre-commit hook exits non-zero and clearly instructs the contributor to stage the modified file and retry the commit. +- [x] AC3: If formatting does not modify `project-words.txt`, the pre-commit hook continues with its existing verification steps. +- [x] AC4: Automated coverage verifies both unchanged and changed formatter and hook behavior. +- [x] AC5: The workflow documentation describes the automatic behavior and standalone formatter command. +- [x] AC6: The implementation is documented as an interim measure related to EPIC #2003 and can be replaced or refactored by its future design. +- [x] `linter all` exits with code `0`. +- [x] Relevant tests pass. +- [x] Manual verification scenarios are executed and documented (status + evidence). +- [x] Acceptance criteria are re-reviewed after implementation and reflect actual behavior. +- [x] Documentation is updated when behavior/workflow changes. + +## Verification Plan + +Define verification before implementation starts and execute it before closing the issue. + +### Automatic Checks + +- `linter all` +- Focused tests for the pre-commit hook behavior +- `./contrib/dev-tools/git/format-project-words.sh` +- `TORRUST_GIT_HOOKS_LOG_DIR=.tmp ./contrib/dev-tools/git/hooks/pre-commit.sh` +- Pre-push checks when applicable + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Command/Steps | Expected Result | Status | Evidence | +| --- | ----------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| M1 | Dictionary needs formatting | Temporarily add unsorted and duplicate exact entries in an isolated Git checkout, then run the pre-commit hook. | The hook rewrites `project-words.txt`, exits non-zero, and instructs the user to stage the file and retry. | DONE | `test-format-project-words.sh`: `it_should_abort_pre_commit_and_request_restaging_when_dictionary_is_formatted`. | +| M2 | Dictionary already formatted | Run the pre-commit hook with the formatted tracked dictionary. | The formatter leaves the file unchanged and the hook continues to its existing checks. | DONE | `TORRUST_GIT_HOOKS_LOG_DIR=.tmp ./contrib/dev-tools/git/hooks/pre-commit.sh --format=json` passed its formatter and all four verification steps. | +| M3 | Case variants remain distinct | Run the standalone formatter against a disposable dictionary containing otherwise identical case variants. | Both variants remain; only exact duplicate lines are removed. | DONE | `test-format-project-words.sh`: `it_should_sort_and_remove_exact_duplicates_when_dictionary_requires_formatting`. | + +Notes: + +- Manual verification is mandatory even when automated tests pass. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | ---------------------------------------------------------------------------------------- | +| AC1 | DONE | Formatter uses `LC_ALL=C sort -u`; M3 verifies case variants remain distinct. | +| AC2 | DONE | M1 and focused hook test verify the non-zero exit and restaging instruction. | +| AC3 | DONE | M2 and focused hook test verify the existing checks continue. | +| AC4 | DONE | `test-format-project-words.sh` covers changed and unchanged formatter and hook behavior. | +| AC5 | DONE | `run-pre-commit-checks` documents the automatic behavior and standalone command. | +| AC6 | DONE | The formatter, hook, and workflow guidance identify this as interim work for EPIC #2003. | + +## Risks and Trade-offs + +- A hook that changes a working-tree file after Git has prepared the index could otherwise allow the unsorted staged version to be committed. The hook must abort after a formatting change so the corrected file can be staged deliberately. +- Locale-sensitive sorting would yield inconsistent output across machines. Setting `LC_ALL=C` makes the ordering deterministic. +- Case-insensitive de-duplication could delete meaningful proper-name or acronym variants. Exact duplicate removal only avoids that data loss. + +## References + +- `project-words.txt` +- `cspell.json` +- `contrib/dev-tools/git/format-project-words.sh` +- `contrib/dev-tools/git/hooks/pre-commit.sh` +- `docs/issues/open/2003-overhaul-guardrails-and-automation/EPIC.md` +- `.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md` diff --git a/docs/pr-reviews/pr-2020-copilot-suggestions.md b/docs/pr-reviews/pr-2020-copilot-suggestions.md new file mode 100644 index 000000000..4de142596 --- /dev/null +++ b/docs/pr-reviews/pr-2020-copilot-suggestions.md @@ -0,0 +1,70 @@ +--- +semantic-links: + skill-links: + - process-copilot-suggestions + related-artifacts: + - .github/skills/dev/pr-reviews/process-copilot-suggestions/SKILL.md +--- + + + + + +# PR #2020 Copilot Suggestions Tracking + +Source: Copilot PR review threads for https://github.com/torrust/torrust-tracker/pull/2020 + +Column legend: + +- **Decision**: `action` means a code or documentation change was applied; `no-action` means the suggestion was reviewed and declined with a documented rationale. +- **Status**: `OPEN` while a thread is being processed; `DONE` after it has been handled. +- **Thread State**: `OPEN` until the thread is resolved in the PR; `RESOLVED` after resolution. + +## 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, implement and validate action items, reply on the PR thread, then resolve the thread. +4. Set `Thread State` to `resolved` once resolved in PR. + +## Processing Log + +- 2026-07-22: Started processing six Copilot suggestions. +- 2026-07-22: Applied the accepted fixes in signed commit `b917355c` and replied to and resolved all six original threads. +- 2026-07-22: Processed all follow-up Copilot threads opened after subsequent pushes; every accepted change was committed, validated, replied to, and resolved. +- 2026-07-22: Processed the final hook JSON and BSD `mktemp` portability suggestions in signed commit `53c0a6e6`. +- 2026-07-22: Processed the issue metadata and dictionary typo suggestions in signed commit `57ed3b05`. +- 2026-07-22: Started processing the tracker thread-ID formatting suggestion. +- 2026-07-22: Corrected the tracker thread ID in signed commit `53909678`, replied to, and resolved the formatting suggestion. + +## Suggestions + +| # | Thread ID | Path | URL | Suggestion Summary | Decision | Reply URL | Status | Thread State | +| --- | --------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------ | ------------ | +| 1 | PRRT_kwDOGp2yqc6S2_XP | `contrib/dev-tools/git/tests/test-format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628911184 | Ensure assertions fail the test script. | action: enabled fail-fast shell execution. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628954196 | DONE | RESOLVED | +| 2 | PRRT_kwDOGp2yqc6S2_Xn | `contrib/dev-tools/git/format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628911225 | Replace the dictionary atomically. | action: used a same-directory temporary file and `mv`. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628955657 | DONE | RESOLVED | +| 3 | PRRT_kwDOGp2yqc6S2_X4 | `contrib/dev-tools/git/hooks/pre-commit.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628911249 | Do not mislabel formatter operational errors as changes. | action: show restaging guidance only for formatter exit code 1. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628957067 | DONE | RESOLVED | +| 4 | PRRT_kwDOGp2yqc6S2_YS | `.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628911279 | Synchronize documented hook steps. | action: added `cargo deny check bans` and the current machete command. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628958264 | DONE | RESOLVED | +| 5 | PRRT_kwDOGp2yqc6S2_Yt | `docs/issues/open/2019-automatically-format-project-dictionary.md` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628911319 | Keep completed acceptance criteria consistent with evidence. | action: marked verified criteria complete. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628959344 | DONE | RESOLVED | +| 6 | PRRT_kwDOGp2yqc6S2_ZL | `docs/issues/open/2019-automatically-format-project-dictionary.md` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628911359 | Replace stale pending acceptance-verification entries. | action: recorded completion evidence. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628960975 | DONE | RESOLVED | +| 7 | PRRT_kwDOGp2yqc6S3Lr0 | `contrib/dev-tools/git/format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628981491 | Report temporary-file creation failures explicitly. | action: added the diagnostic and focused test coverage. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629010458 | DONE | RESOLVED | +| 8 | PRRT_kwDOGp2yqc6S3LsT | `docs/issues/open/2019-automatically-format-project-dictionary.md` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3628981533 | Align the issue specification with the documented layout. | action: moved the spec to its documented `ISSUE.md` folder layout. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629239329 | DONE | RESOLVED | +| 9 | PRRT_kwDOGp2yqc6S3T8 | `contrib/dev-tools/git/hooks/pre-commit.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629029141 | Retain the exact failed step exit code. | action: captured the `run_step` exit code directly. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629242405 | DONE | RESOLVED | +| 10 | PRRT_kwDOGp2yqc6S3dJZ | `contrib/dev-tools/git/format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629081831 | Support non-GNU local toolchains. | action: replaced GNU-only options with portable equivalents. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629243737 | DONE | RESOLVED | +| 11 | PRRT_kwDOGp2yqc6S3k60 | `docs/pr-reviews/pr-2020-copilot-suggestions.md` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629126625 | Make tracker column meanings unambiguous. | action: replaced the ambiguous legend with column-specific definitions. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629280599 | DONE | RESOLVED | +| 12 | PRRT_kwDOGp2yqc6S32cm | `.github/skills/dev/git-workflow/run-linters/references/linters.md` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629225537 | Synchronize the documented portable formatter command. | action: documented `LC_ALL=C sort -u`. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629282267 | DONE | RESOLVED | +| 13 | PRRT_kwDOGp2yqc6S32dU | `contrib/dev-tools/git/tests/test-format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629225593 | Use portable test assertion options. | action: replaced GNU-only `diff` and `grep` options. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629283760 | DONE | RESOLVED | +| 14 | PRRT_kwDOGp2yqc6S32dt | `contrib/dev-tools/git/tests/test-format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629225631 | Use portable `grep` options. | action: replaced GNU-only `grep` options. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629285275 | DONE | RESOLVED | +| 15 | PRRT_kwDOGp2yqc6S32eH | `contrib/dev-tools/git/tests/test-format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629225665 | Use portable `grep` options. | action: replaced GNU-only `grep` options. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629287113 | DONE | RESOLVED | +| 16 | PRRT_kwDOGp2yqc6S32ec | `contrib/dev-tools/git/tests/test-format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629225692 | Use portable test assertion options. | action: replaced GNU-only `diff` and `grep` options. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629290234 | DONE | RESOLVED | +| 17 | PRRT_kwDOGp2yqc6S32eo | `contrib/dev-tools/git/tests/test-format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629225706 | Use portable `grep` options. | action: replaced GNU-only `grep` options. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629305692 | DONE | RESOLVED | +| 18 | PRRT_kwDOGp2yqc6S32e3 | `contrib/dev-tools/git/tests/test-format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629225730 | Use portable `grep` options. | action: replaced GNU-only `grep` options. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629307405 | DONE | RESOLVED | +| 19 | PRRT_kwDOGp2yqc6S4CoL | `contrib/dev-tools/git/hooks/pre-commit.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629295494 | Preserve infrastructure errors in JSON results. | action: propagated the actual failed-step exit code. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629362577 | DONE | RESOLVED | +| 20 | PRRT_kwDOGp2yqc6S4Coq | `contrib/dev-tools/git/tests/test-format-project-words.sh` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629295532 | Use a portable test directory `mktemp` template. | action: supplied an explicit BSD-compatible template. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629365111 | DONE | RESOLVED | +| 21 | PRRT_kwDOGp2yqc6S4JkJ | `docs/issues/open/2019-automatically-format-project-dictionary/ISSUE.md` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629334908 | Link the issue specification to its implementation PR. | action: set `related-pr: 2020`. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629396136 | DONE | RESOLVED | +| 22 | PRRT_kwDOGp2yqc6S4Jkr | `project-words.txt` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629334953 | Remove the unreferenced dictionary typo. | action: removed `Unamed`. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629397148 | DONE | RESOLVED | +| 23 | PRRT_kwDOGp2yqc6S4Z4w | `docs/pr-reviews/pr-2020-copilot-suggestions.md` | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629428258 | Remove Markdown asterisks from row 9's thread ID. | action: corrected the thread ID to its exact value. | https://github.com/torrust/torrust-tracker/pull/2020#discussion_r3629575867 | DONE | RESOLVED | + +## Notes + +- The linked `process-copilot-suggestions` skill was reviewed while updating this tracker; its workflow requires no change. diff --git a/project-words.txt b/project-words.txt index 64b0ae2fb..a9ad9aa3c 100644 --- a/project-words.txt +++ b/project-words.txt @@ -1,12 +1,118 @@ +ASMS +AUTOINCREMENT +Addrs +Agentic +Aideq +Arvid +Avicora +Azureus +Beránek +Biriukov +Bitflu +Bragilevsky +BuildKit +Buildx +CALLSITE +Celano +Cinstrument +Condvar +Containerfile +Cyberneering +DGRAM +DNSSEC +Deque +Dihc +Dijke +Dmqcd +EADDRINUSE +EINVAL +Eray +Freebox +Frostegård +Garnham +Gibibytes +Glrg +Graphviz +Grcov +HDRINCL +Hydranode +IPPROTO +IPV6 +Icelake +Intermodal +Irwe +Jakub +Joakim +JobManager +JoinSet +Karatay +Kibibytes +LOGNAME +LVJDMDAwMDAwMDAwMDAwMDAwMDE +Laravel +LoadTest +Lphant +MSRV +Mbps +Mebibytes +Naim +Norberg +PGID +PRRT +PUID +Pando +Publishability +QJSF +QUIC +Quickstart +RAII +REUSEPORT +RPIT +RUSTDOCFLAGS +RUSTFLAGS +Radeon +Rakshasa +Rasterbar +Registar +Rustls +Ryzen +SHLVL +Seedable +Shareaza +Signedness +Subissues +Swatinem +Swiftbit +TSIG +Tebibytes +Tera +Torrentstorm +Trackon +Trixie +UNCONN +Unamed +Unparker +Unsendable +VARCHAR +Vagaa +Vitaly +Vuze +WEBUI +Weidendorfer +Werror +Winsock +XBTT +Xacrimon +Xdebug +Xeon +Xtorrent +Xunlei acgnxtracker actix -Addrs adduser adminadmin adrs -Agentic agentskills -Aideq alekitto alives alloca @@ -17,17 +123,12 @@ aquasec aquasecurity argjson artefacts -Arvid asdh -ASMS asyn autoclean -AUTOINCREMENT autolinks automock autoremove -Avicora -Azureus backlinks bdecode behaviour @@ -36,35 +137,26 @@ bencode bencoded bencoding beps -Beránek bidirectionality binascii bindv6only binstall -Biriukov bitcode -Bitflu bools bottlenecked -Bragilevsky bufs buildid -BuildKit -Buildx byteorder callgrind -CALLSITE callsites camino canonicalize canonicalized categorisation cdylib -Celano certbot chihaya chrono -Cinstrument ciphertext clippy cloneable @@ -75,15 +167,12 @@ colours commiter completei composecheck -Condvar connectionless -Containerfile conv creds curr cvar cves -Cyberneering cyclomatic dashmap datagram @@ -94,16 +183,10 @@ dbname debuginfo defence depgraph -Deque dfsg -DGRAM -Dihc -Dijke distroless distros dler -Dmqcd -DNSSEC dockerhub doctest downloadedi @@ -111,8 +194,6 @@ dpkg dport dtolnay dylib -EADDRINUSE -EINVAL elif endgroup endianness @@ -120,7 +201,6 @@ envcontainer epoll eprint eprintln -Eray esac eventfd exploitability @@ -142,21 +222,13 @@ formatjson fput fputwc fract -Freebox frontmatter -Frostegård fscanf -Garnham gecos getaddrinfo gethostbyname ghac -Gibibytes -Glrg -Graphviz -Grcov hasher -HDRINCL healthcheck heaptrack hexdigit @@ -168,10 +240,8 @@ hotfixes hotspot hotspots httpclientpeerid -Hydranode hyperium hyperthread -Icelake iiiiiiiiiiiiiiiiiiiid iiiiiiiiiiiiiiiipp iiiiiiiiiiiiiiiippe @@ -185,29 +255,18 @@ infohash infohashes infoschema initialisation -Intermodal intervali io_uring -IPPROTO -IPV6 -Irwe isready iterationsadd -Jakub jdbe -Joakim -JobManager -JoinSet josecelano kallsyms -Karatay kcachegrind kexec keyout -Kibibytes kptr ksys -Laravel lcov leafification leecher @@ -221,14 +280,8 @@ libsqlite libtorrent libz llist -LoadTest -LOGNAME -Lphant lscr -LVJDMDAwMDAwMDAwMDAwMDAwMDE matchmakes -Mbps -Mebibytes metainfo microbenchmark microbenchmarks @@ -244,13 +297,10 @@ mmdb mockall monomorphisation mprotect -MSRV multimap myacicontext mysqladmin mysqld -ñaca -Naim nanos newkey newtrackon @@ -264,7 +314,6 @@ nocapture nologin nonblocking nonroot -Norberg notnull nping nquery @@ -284,7 +333,6 @@ organisation organised ostr overengineered -Pando parallelisable parallelise parallelised @@ -294,7 +342,6 @@ peerlist peersld penalise pessimize -PGID pipefail pkey pkill @@ -305,19 +352,9 @@ prioritise programatik proot proto -PRRT -Publishability -PUID qbittorrent -QJSF -QUIC quickcheck -Quickstart -Radeon -RAII -Rakshasa randomised -Rasterbar readelf realpath reannounce @@ -327,7 +364,6 @@ recompiles recvfrom recvspace referer -Registar reorganisation reorganising repomix @@ -337,7 +373,6 @@ reqwest rerequests rescope reuseaddr -REUSEPORT ringbuf ringsize rlib @@ -345,33 +380,24 @@ rmem rngs rosegment routable -RPIT rsplit rstest rusqlite rustc rustdoc -RUSTDOCFLAGS -RUSTFLAGS rustfmt -Rustls rustup -Ryzen sarif savepath scanf sccache -Seedable sendto serde serialisation setgroups setsockopt -Shareaza sharktorrent shellcheck -SHLVL -Signedness skiplist slowloris socat @@ -384,23 +410,18 @@ srcset sscanf stabilised subissue -Subissues subkey subsec substeps summarising supertrait -Swatinem -Swiftbit syscall sysmalloc sysret taiki taplo tdyne -Tebibytes tempfile -Tera testcontainer testcontainers thirdparty @@ -410,38 +431,30 @@ tlnp tlsv toki toplevel -Torrentstorm torru torrust torrustracker trackerid -Trackon triaging trivy trivy-action trivy-results -Trixie trunc tryhackx -TSIG tslconfig ttwu typenum udpv ulnp -Unamed unconfigured -UNCONN underflows ungetwc uninit unittests unparked -Unparker unrecognised unrepresentable unreviewed -Unsendable unsync untuple unvalidated @@ -451,31 +464,18 @@ ureq urlencode uroot usize -Vagaa valgrind -VARCHAR -Vitaly vmlinux vtable vulns -Vuze wakelist wakeup walkdir webtorrent -WEBUI -Weidendorfer -Werror whitespaces -Winsock -Xacrimon -XBTT -Xdebug -Xeon -Xtorrent -Xunlei xxxxxxxxxxxxxxxxxxxxd yyyyyyyyyyyyyyyyyyyyd zerocopy zeroize zstd +ñaca