Repository: reactive-firewall/multicast
Pull request #402: Round two of CI/CD Improvements
Author: login: reactive-firewall
Labels: name: Bash Lang
description: Changes to the BASH scripts
name: Testing
description: Something can be verified
name: CI
description: Continuous Integration Tooling
name: GitHub
description: Anything Meta
name: Make Lang
description: Changes to makefiles
Created: 2025-05-17T01:37:29Z | Merged: 2025-05-17T05:35:43Z

# Patch Notes

## Impacted GHI

 - [x] Closes #338
 - [ ] Opens #403

## Changes

Changes in file .github/workflows/CI-DOCS.yml:
 * similar changes for documentation generation in CI/CD

Additions with file .github/actions/setup-py-reqs/action.yml:
 * ✨ New action for handling python pip installs in CI/CD

Changes in file .github/workflows/Tests.yml:
 * improved summary reporting for CI/CD tests
 * integrated new GHA template
 * related work

Changes in file Makefile:
 * attempt to make build target less pre-emptive
 * related work


### New CI Testing Dependency Graph

```mermaid
graph TD;
    PUSH-EVENT-->CI-Build.yml;
    CI-Build.yml-->Build-Artifact.whl;
    CI-Build.yml-->Build-Info-Artifact.txt;
    CI-Build.yml-->Build-Summary-Artifact.txt;
    Build-Artifact.whl-->CI-MATs.yml;
    Build-Info-Artifact.txt-->CI-MATs.yml;
    CI-MATs.yml-->MATs-Info-Artifact.txt;
    CI-MATs.yml-->MATs-Summary-Artifact.txt;
    Build-Artifact.whl-->CI-Tests.yml;
    MATs-Info-Artifact.txt-->CI-Tests.yml;
    CI-Tests.yml-->COVERAGE-Artifact.zip;
    CI-Tests.yml-->Test-Results-Artifact.zip;
    CI-Tests.yml-->Test-Summary-Artifact.txt;
    Build-Artifact.whl-->CI-DOCs.yml;
    MATs-Info-Artifact.txt-->CI-DOCs.yml;
    CI-DOCs.yml-->Documentation-Artifact.zip;
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
    - Introduced a GitHub Action to automate Python dependency installation and artifact management.
    - Enhanced CI workflows with detailed integration and documentation test reporting, including summary artifacts and commit comments.
- **Improvements**
    - CI workflows now use explicit dependency installation steps and improved artifact handling.
    - Makefile updated for streamlined installation targets and exclusion of additional files in packaging.
    - Improved Python version handling in minimal acceptance tests action.
    - Extended spell-checking with additional known typo detection.
- **Bug Fixes**
    - Fixed HTML summary formatting in CI reports.
    - Removed redundant permissions and obsolete steps in workflows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #338: Round 2 of Test Organization improvements
## Background

Starting with #199 and the related changes cumulating in the `v2.0.5` pre-release ( PR #330 ) the initial groundwork for reorganizing the testing workflow has been laid.

**Update**: As of `v2.0.8` stable builds are possible in CI and can be pushed and pulled from the github CI infrastructure. This allows for CI pipeline style testing.

## Next Steps

Further improvements are needed; Namely:

 * Regressions in the coupling between changes (from pushes or PR/MRs) and the results of the CI/CD testing via GHAs, need to be corrected so that testing results are provided readily to maintainers through the GitHub platform similar to as it was the case before splitting the `Tests.yml` workflow.

    - [x] `CI-Test` need to once again apply to each pull-requests check suites, while still being dependent on a successful `CI-BUILD` workflow run.
    - [x] `CI-Test` need to once again apply to relevant pull-requests check suites, while still being dependent on a successful `CI-MATs` workflow run.
    - [x] The result of the `CI-BUILD` should include an artifact with the built python package in a form that can be `pip install`-ed while testing.
    - [x] `CI-MATs` should use the same environment as that used by `CI-BUILD` which it depends
    - [x] `CI-DOCs` should NOT use an environment unless needed
    - [x] `CI-Tests` should use the same environment as that used by `CI-BUILD` (and `CI-MATs`) which it depends
    - ~`CD-DOCs` should use the same environment as that used by `CI-DOCs` which it depends~
    - [x] `CI-DOCs` should use the new `Documentation` environment
 - [x] Improved CI/CD result summaries, (eg. **what** passed, or failed?)
    - [x] Comments on GitHub Commits (namely for the commit by SHA of the CI run)
    - [x] Feedback on GitHub PRs (when relevant)
      <img width="619" alt="Image" src="https://github.com/user-attachments/assets/d126f9eb-4903-46d0-9016-74f3910de2e4" />

## General idea for CI/CD

### New Dependency Graph

```mermaid
graph TD;
    PUSH-EVENT-->CI-Build.yml;
    CI-Build.yml-->Build-Artifact.whl;
    CI-Build.yml-->Build-Info-Artifact.txt;
    CI-Build.yml-->Build-Summary-Artifact.txt;
    Build-Artifact.whl-->CI-MATs.yml;
    Build-Info-Artifact.txt-->CI-MATs.yml;
    CI-MATs.yml-->MATs-Info-Artifact.txt;
    CI-MATs.yml-->MATs-Summary-Artifact.txt;
    Build-Artifact.whl-->CI-Tests.yml;
    MATs-Info-Artifact.txt-->CI-Tests.yml;
    CI-Tests.yml-->COVERAGE-Artifact.zip;
    CI-Tests.yml-->Test-Results-Artifact.zip;
    CI-Tests.yml-->Test-Summary-Artifact.txt;
    Build-Artifact.whl-->CD-DOCs.yml;
    MATs-Info-Artifact.txt-->CD-DOCs.yml;
    CD-DOCs.yml-->Documentation-Artifact.zip;
```

### Improved CI/CD process

> [!NOTE]
> This diagram is only a summary, a lot more steps are performed, but these are only the more relevant sequences of interactions. See implementation for exact behavior.

```mermaid
sequenceDiagram
    Actor User
    participant GH as GitHub
    User->>+GH: Pushes Changes
    Note left of GH: eg. triggers actions
    create participant BUILD as .github/workflows/CI-Build.yml
    GH->>BUILD: TRIGGER
    GH-->>User: Pushed
    deactivate GH
    critical Build Action
        BUILD->>BUILD: Builds "dist/multicast-Artifact.whl"
    option Build Success
        BUILD->>GH: Uploads "dist/multicast-Artifact.whl"
        BUILD-->>BUILD: Creates "Build-Summary-Artifact.txt"
    option Build Failure
        BUILD->>BUILD: Creates "Build-Summary-Artifact.txt"
    end
    destroy BUILD
    BUILD-->>GH: Uploads "Build-Summary-Artifact.txt"
    Note right of BUILD: BUILD is Done.
    create participant MATs as .github/workflows/CI-MATs.yml
    GH->>MATs: TRIGGER
    alt IF Build Success
        Note Left of MATs: FIND "dist/multicast-Artifact.whl"
        MATs<<->>GH: Downloads "dist/multicast-Artifact.whl"
        MATs-->>MATs: Invoke MATs
        MATs->>MATs: Creates "MATs-Summary-Artifact.txt"
        MATs-->>GH: Uploads "MATs-Summary-Artifact.txt"
    else IF Build Failure
        GH-xMATs: CANCEL
    end
    Note right of MATs: MATs are Done.
    destroy MATs
    GH--xMATs: 
    create participant TESTs as .github/workflows/CI-Tests.yml
    GH->>TESTs: TRIGGER
    opt If PR
        create participant DOCs as .github/workflows/CI-DOCs.yml
        GH->>DOCs: TRIGGER
        alt IF Build AND MATs Success
            Note Left of DOCs: Found "dist/multicast-Artifact.whl"
            DOCs<<->>GH: Downloads "dist/multicast-Artifact.whl"
            Note right of DOCs: Found "MATs-Summary-Artifact.txt"
            DOCs->>DOCs: Invoke Documentation Linting/Testing
            alt Documentation Linting Success
                DOCs-->DOCs: Creates "DOCs-Summary-Artifact.txt"
                DOCs->>DOCs: Creates "Documentation-Artifact.zip"
                DOCs-->>DOCs: Uploads "Documentation-Artifact.zip"
            else Documentation Linting failure
                DOCs->>DOCs: Creates "DOCs-Summary-Artifact.txt"
            end
            destroy DOCs
            DOCs-->>GH: Uploads "DOCs-Summary-Artifact.txt"
        end
    end
    alt IF Build AND MATs Success
        Note Left of TESTs: Found "dist/multicast-Artifact.whl"
        TESTs<<->>GH: Downloads "dist/multicast-Artifact.whl"
        Note Left of TESTs: Found "MATs-Summary-Artifact.txt"
        TESTs->>TESTs: Invoke Coverage Testing
        TESTs->>TESTs: Invoke Style Testing
        alt Style Test Success
            alt ALL Coverage tests are a success
                TESTs-->>TESTs: Invoke Integration Coverage Testing
                alt ALL Integration tests are ALSO a success
                    TESTs->>TESTs: Creates "COVERAGE-Artifact.zip"
                    TESTs-->>TESTs: Uploads "COVERAGE-Artifact.zip"
                else Integration tests have a failure
                    TESTs->>TESTs: Creates "TESTs-Summary-Artifact.txt"
                end
            else Coverage tests have a failure
                TESTs->>TESTs: Creates "TESTs-Summary-Artifact.txt"
            end
        else Style tests have a failure
            TESTs->>TESTs: Creates "TESTs-Summary-Artifact.txt"
        end
        TESTs->>TESTs: Creates "Test-Results-Artifact.zip"
        TESTs-->>GH: Uploads "MATs-Summary-Artifact.txt"
        TESTs-->>GH: Uploads "Test-Results-Artifact.zip"
    else IF Build Failure
        GH-xTESTs: CANCEL
    else IF MATs Failure
        Note Left of TESTs: Found "dist/multicast-Artifact.whl"
        TESTs<<->>GH: Downloads "dist/multicast-Artifact.whl"
        GH-xTESTs: CANCEL
    end
    Note right of TESTs: TESTs are Done.
```
Linked issue comments: user: login: reactive-firewall
created_at: 2025-04-17T02:05:06Z
body: @coderabbitai, please look at GHI #338 and help me draft a plan.
author_association: COLLABORATOR
user: login: coderabbitai[bot]
created_at: 2025-04-17T02:06:26Z
body: <!-- This is an auto-generated reply by CodeRabbit -->
> [!TIP]
> For best results, initiate chat on the files or code changes.

<details>
<summary>🧩 Analysis chain</summary>

🏁 Script executed:
```
#!/bin/bash
# Retrieve the issue details
gh issue view 338 --repo reactive-firewall/multicast
```

Length of output: 5753

---

🏁 Script executed:
```
#!/bin/bash
# List all workflow files to understand the current CI/CD setup
find .github/workflows -type f -name "*.yml" | sort

# Check content of the CI-Build workflow
echo "=== CI-BUILD ==="
cat .github/workflows/CI-Build.yml 2>/dev/null || echo "File not found"

# Check content of the CI-MATs workflow
echo "=== CI-MATs ==="
cat .github/workflows/CI-MATs.yml 2>/dev/null || echo "File not found"

# Check content of the CI-Tests workflow
echo "=== CI-Tests ==="
cat .github/workflows/CI-Tests.yml 2>/dev/null || echo "File not found"

# Check content of the CD-DOCs workflow if it exists
echo "=== CD-DOCs ==="
cat .github/workflows/CD-DOCs.yml 2>/dev/null || echo "File not found"
```

Length of output: 5267

---

🏁 Script executed:
```
#!/bin/bash
# Check content of the CI-BUILD workflow (note the uppercase)
echo "=== CI-BUILD ==="
cat .github/workflows/CI-BUILD.yml 2>/dev/null || echo "File not found"

# Check content of the Tests workflow
echo "=== Tests.yml ==="
cat .github/workflows/Tests.yml 2>/dev/null || echo "File not found"

# Check content of CI-DOCS workflow
echo "=== CI-DOCS ==="
cat .github/workflows/CI-DOCS.yml 2>/dev/null || echo "File not found"

# Check current triggers for these workflows
echo "=== CI-BUILD Triggers ==="
grep -A5 "on:" .github/workflows/CI-BUILD.yml 2>/dev/null || echo "Not found"

echo "=== CI-MATs Triggers ==="
grep -A5 "on:" .github/workflows/CI-MATs.yml 2>/dev/null || echo "Not found"

echo "=== Tests Triggers ==="
grep -A5 "on:" .github/workflows/Tests.yml 2>/dev/null || echo "Not found"

echo "=== CI-DOCS Triggers ==="
grep -A5 "on:" .github/workflows/CI-DOCS.yml 2>/dev/null || echo "Not found"
```

Length of output: 41767

---



</details>



```mermaid
flowchart TD
    A["Issue #338: Test Organization Improvements"] --o B["Update CI-BUILD.yml workflow"]
    A --o C["Update CI-MATs.yml workflow"]
    A --o D["Rename Tests.yml to CI-Tests.yml"]
    A --o E["Create/Modify CD-DOCs.yml workflow"]
    
    B --o B1["Modify to produce .whl artifact"]
    B --o B2["Create Build-Summary-Artifact.txt"]
    
    C --o C1["Update triggers for push events"]
    C --o C2["Ensure dependency on CI-BUILD"]
    C --o C3["Download build artifact"]
    C --o C4["Create MATs-Summary-Artifact.txt"]
    
    D --o D1["Update triggers for push events"]
    D --o D2["Ensure dependency on CI-MATs"]
    D --o D3["Download artifacts from previous steps"]
    D --o D4["Generate test summary artifacts"]
    
    E --o E1["Set up push event triggers"]
    E --o E2["Ensure dependency on CI-MATs"]
    E --o E3["Download artifacts from previous steps"]
    E --o E4["Generate documentation artifacts"]
```

@reactive-firewall Based on my review of issue #338 and the current GitHub workflows, here's a detailed implementation plan to address the required improvements:

## 1. CI-BUILD.yml Updates
- Modify to explicitly create and upload a build artifact (.whl file)
- Create and upload a Build-Summary-Artifact.txt with build status information
- Ensure the artifact is properly named and accessible to dependent workflows

## 2. CI-MATs.yml Updates
- Update the triggers to respond to push events while maintaining dependency on CI-BUILD
- Download the build artifact (.whl) from CI-BUILD
- Create and upload a MATs-Summary-Artifact.txt
- Use the same environment as CI-BUILD

## 3. Tests.yml Updates
- Rename to CI-Tests.yml for consistency
- Update triggers to respond to push events while maintaining dependency on CI-MATs
- Download artifacts from both CI-BUILD and CI-MATs
- Generate and upload required test artifacts (COVERAGE, Test-Results, Test-Summary)

## 4. CD-DOCs.yml Creation/Modification
- Modify the existing CI-DOCS.yml to CD-DOCs.yml or create a new one
- Set up proper dependencies on CI-MATs
- Download necessary artifacts
- Generate and upload Documentation-Artifact.zip

## Implementation Approach
1. I recommend implementing these changes in sequence (BUILD → MATs → Tests → DOCs) to maintain workflow integrity
2. Each workflow should explicitly check for successful completion of its dependencies
3. Use GitHub Actions' artifact download/upload features for passing data between workflows
4. Add detailed summary steps to provide rich feedback on what passed/failed

Would you like me to start drafting the specific YAML changes for each workflow file?

(∩^o^)⊃━☆ﾟ.*

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:12-12
Timestamp: 2024-11-26T01:18:43.559Z
Learning: Reactive-firewall prefers that I open follow-up issues for refactoring tasks upon request, using specified titles and including details and references to related issues.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#259
File: .github/workflows/CI-MATs.yml:34-40
Timestamp: 2024-12-16T08:21:56.888Z
Learning: Reactive-firewall prefers to track code review issues by adding comments to existing issues like #265.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: LICENSE.md:36-43
Timestamp: 2024-11-14T07:03:35.207Z
Learning: Reactive-firewall prefers that I verify URLs before suggesting changes, and avoid raising hypothetical issues without verification.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#110
File: docs/USAGE.md:66-66
Timestamp: 2024-09-17T03:38:28.677Z
Learning: Reactive-firewall prefers to use "Caveat" as a heading instead of "Caution".
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: multicast/exceptions.py:187-254
Timestamp: 2024-11-15T04:44:54.598Z
Learning: Reactive-firewall prefers to retain the current implementation using `(*args, **kwargs)` in method definitions.
```

</details>



---

⏳ Preparing changes...




<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><nextState>plan-edits</nextState></rawResChunk> -->

<!-- <rawResChunk><answer><details>
<summary>🧩 Analysis chain</summary>

🏁 Script executed:
```
#!/bin/bash
# Retrieve the issue details
gh issue view 338 --repo reactive-firewall/multicast
```

Length of output: 5753

---

🏁 Script executed:
```
#!/bin/bash
# List all workflow files to understand the current CI/CD setup
find .github/workflows -type f -name "*.yml" | sort

# Check content of the CI-Build workflow
echo "=== CI-BUILD ==="
cat .github/workflows/CI-Build.yml 2>/dev/null || echo "File not found"

# Check content of the CI-MATs workflow
echo "=== CI-MATs ==="
cat .github/workflows/CI-MATs.yml 2>/dev/null || echo "File not found"

# Check content of the CI-Tests workflow
echo "=== CI-Tests ==="
cat .github/workflows/CI-Tests.yml 2>/dev/null || echo "File not found"

# Check content of the CD-DOCs workflow if it exists
echo "=== CD-DOCs ==="
cat .github/workflows/CD-DOCs.yml 2>/dev/null || echo "File not found"
```

Length of output: 5267

---

🏁 Script executed:
```
#!/bin/bash
# Check content of the CI-BUILD workflow (note the uppercase)
echo "=== CI-BUILD ==="
cat .github/workflows/CI-BUILD.yml 2>/dev/null || echo "File not found"

# Check content of the Tests workflow
echo "=== Tests.yml ==="
cat .github/workflows/Tests.yml 2>/dev/null || echo "File not found"

# Check content of CI-DOCS workflow
echo "=== CI-DOCS ==="
cat .github/workflows/CI-DOCS.yml 2>/dev/null || echo "File not found"

# Check current triggers for these workflows
echo "=== CI-BUILD Triggers ==="
grep -A5 "on:" .github/workflows/CI-BUILD.yml 2>/dev/null || echo "Not found"

echo "=== CI-MATs Triggers ==="
grep -A5 "on:" .github/workflows/CI-MATs.yml 2>/dev/null || echo "Not found"

echo "=== Tests Triggers ==="
grep -A5 "on:" .github/workflows/Tests.yml 2>/dev/null || echo "Not found"

echo "=== CI-DOCS Triggers ==="
grep -A5 "on:" .github/workflows/CI-DOCS.yml 2>/dev/null || echo "Not found"
```

Length of output: 41767

---



</details>



```mermaid
flowchart TD
    A["Issue #338: Test Organization Improvements"] --o B["Update CI-BUILD.yml workflow"]
    A --o C["Update CI-MATs.yml workflow"]
    A --o D["Rename Tests.yml to CI-Tests.yml"]
    A --o E["Create/Modify CD-DOCs.yml workflow"]
    
    B --o B1["Modify to produce .whl artifact"]
    B --o B2["Create Build-Summary-Artifact.txt"]
    
    C --o C1["Update triggers for push events"]
    C --o C2["Ensure dependency on CI-BUILD"]
    C --o C3["Download build artifact"]
    C --o C4["Create MATs-Summary-Artifact.txt"]
    
    D --o D1["Update triggers for push events"]
    D --o D2["Ensure dependency on CI-MATs"]
    D --o D3["Download artifacts from previous steps"]
    D --o D4["Generate test summary artifacts"]
    
    E --o E1["Set up push event triggers"]
    E --o E2["Ensure dependency on CI-MATs"]
    E --o E3["Download artifacts from previous steps"]
    E --o E4["Generate documentation artifacts"]
```

@reactive-firewall Based on my review of issue #338 and the current GitHub workflows, here's a detailed implementation plan to address the required improvements:

## 1. CI-BUILD.yml Updates
- Modify to explicitly create and upload a build artifact (.whl file)
- Create and upload a Build-Summary-Artifact.txt with build status information
- Ensure the artifact is properly named and accessible to dependent workflows

## 2. CI-MATs.yml Updates
- Update the triggers to respond to push events while maintaining dependency on CI-BUILD
- Download the build artifact (.whl) from CI-BUILD
- Create and upload a MATs-Summary-Artifact.txt
- Use the same environment as CI-BUILD

## 3. Tests.yml Updates
- Rename to CI-Tests.yml for consistency
- Update triggers to respond to push events while maintaining dependency on CI-MATs
- Download artifacts from both CI-BUILD and CI-MATs
- Generate and upload required test artifacts (COVERAGE, Test-Results, Test-Summary)

## 4. CD-DOCs.yml Creation/Modification
- Modify the existing CI-DOCS.yml to CD-DOCs.yml or create a new one
- Set up proper dependencies on CI-MATs
- Download necessary artifacts
- Generate and upload Documentation-Artifact.zip

## Implementation Approach
1. I recommend implementing these changes in sequence (BUILD → MATs → Tests → DOCs) to maintain workflow integrity
2. Each workflow should explicitly check for successful completion of its dependencies
3. Use GitHub Actions' artifact download/upload features for passing data between workflows
4. Add detailed summary steps to provide rich feedback on what passed/failed

Would you like me to start drafting the specific YAML changes for each workflow file?

(∩^o^)⊃━☆ﾟ.*

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:12-12
Timestamp: 2024-11-26T01:18:43.559Z
Learning: Reactive-firewall prefers that I open follow-up issues for refactoring tasks upon request, using specified titles and including details and references to related issues.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#259
File: .github/workflows/CI-MATs.yml:34-40
Timestamp: 2024-12-16T08:21:56.888Z
Learning: Reactive-firewall prefers to track code review issues by adding comments to existing issues like #265.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: LICENSE.md:36-43
Timestamp: 2024-11-14T07:03:35.207Z
Learning: Reactive-firewall prefers that I verify URLs before suggesting changes, and avoid raising hypothetical issues without verification.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#110
File: docs/USAGE.md:66-66
Timestamp: 2024-09-17T03:38:28.677Z
Learning: Reactive-firewall prefers to use "Caveat" as a heading instead of "Caution".
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: multicast/exceptions.py:187-254
Timestamp: 2024-11-15T04:44:54.598Z
Learning: Reactive-firewall prefers to retain the current implementation using `(*args, **kwargs)` in method definitions.
```

</details>



---

⏳ Preparing changes...

</answer></rawResChunk> -->
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-04-17T02:06:49Z
body: <!-- This is an auto-generated reply by CodeRabbit -->
> [!CAUTION]
> CodeRabbit did not find changes to make.
author_association: CONTRIBUTOR
user: login: reactive-firewall
created_at: 2025-04-17T02:11:36Z
body: > Would you like me to start drafting the specific YAML changes for each workflow file?

@coderabbitai, no need to start drafting just yet. Give me some time to review and respond to your initial plan draft first.
author_association: COLLABORATOR
user: login: coderabbitai[bot]
created_at: 2025-04-17T02:12:00Z
body: <!-- This is an auto-generated reply by CodeRabbit -->
> [!TIP]
> For best results, initiate chat on the files or code changes.

@reactive-firewall Understood! Take all the time you need to review the plan first. I'll wait for your feedback before drafting any specific YAML changes for the workflows. Happy to make adjustments to the approach based on your input.

(^・ω・^)

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: LICENSE.md:36-43
Timestamp: 2024-11-14T07:03:35.207Z
Learning: Reactive-firewall prefers that I verify URLs before suggesting changes, and avoid raising hypothetical issues without verification.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#110
File: docs/USAGE.md:66-66
Timestamp: 2024-09-17T03:38:28.677Z
Learning: Reactive-firewall prefers to use "Caveat" as a heading instead of "Caution".
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: multicast/exceptions.py:187-254
Timestamp: 2024-11-15T04:44:54.598Z
Learning: Reactive-firewall prefers to retain the current implementation using `(*args, **kwargs)` in method definitions.
```

</details>




<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall Understood! Take all the time you need to review the plan first. I'll wait for your feedback before drafting any specific YAML changes for the workflows. Happy to make adjustments to the approach based on your input.

(^・ω・^)

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: LICENSE.md:36-43
Timestamp: 2024-11-14T07:03:35.207Z
Learning: Reactive-firewall prefers that I verify URLs before suggesting changes, and avoid raising hypothetical issues without verification.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#110
File: docs/USAGE.md:66-66
Timestamp: 2024-09-17T03:38:28.677Z
Learning: Reactive-firewall prefers to use "Caveat" as a heading instead of "Caution".
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: multicast/exceptions.py:187-254
Timestamp: 2024-11-15T04:44:54.598Z
Learning: Reactive-firewall prefers to retain the current implementation using `(*args, **kwargs)` in method definitions.
```

</details>

</answer></rawResChunk> -->
author_association: CONTRIBUTOR

Diff:
diff --git a/.github/actions/run-minimal-acceptance-tests/action.yml b/.github/actions/run-minimal-acceptance-tests/action.yml
index dfcdcaf4..87920db2 100644
--- a/.github/actions/run-minimal-acceptance-tests/action.yml
+++ b/.github/actions/run-minimal-acceptance-tests/action.yml
@@ -91,7 +91,7 @@ runs:
         PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
       shell: bash
       run: |
-        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+        if [[ -n $PYTHON_VERSION_INPUT ]]; then
           printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
           PYTHON_VERSION=${PYTHON_VERSION_INPUT}
         else
diff --git a/.github/actions/setup-py-reqs/action.yml b/.github/actions/setup-py-reqs/action.yml
new file mode 100644
index 00000000..fec448ae
--- /dev/null
+++ b/.github/actions/setup-py-reqs/action.yml
@@ -0,0 +1,239 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -n $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "artifact-name=%s\n" multicast-integration-${BUILD_SHA}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "artifact-name=%s" multicast-integration-${BUILD_SHA}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            # Initialize result as success b/c nothing failed ... yet
+            THE_RESULT="success"
+          else
+            # Initialize result as skipped b/c nothing could be done without requirements.txt
+            THE_RESULT="skipped"
+          fi
+        else
+          # Initialize result as failure right away
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          # keep result as success b/c something succeeded and nothing failed ... yet
+          THE_RESULT="success"
+        else
+          # check for actual failure
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             # force result as failure b/c something failed
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          # keep result as success b/c something succeeded and nothing failed ... at all
+          THE_RESULT="success"
+        else
+          # check for actual failure
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             # force result as failure b/c something failed
+             THE_RESULT="failure"
+          fi
+        fi
+        # hint to help with debugging
+        printf "::debug:: %s\n" "The result of dependency evaluation: ${THE_RESULT}"
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          # exit as failure b/c either a soft-fail (skip/cancelled/etc.) or actual failure
+          exit 1
+        fi
+    - name: "Summarize DEPs"
+      id: deps_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.deps_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for [${BUILD_SHA}](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt)" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for \`${BUILD_SHA}\`~" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_build_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [tests/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/tests/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `tests/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [docs/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/docs/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `docs/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+    - name: "Collect and Enumerate Generated Files"
+      id: output_artifact_files
+      if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+      env:
+        DEPS_MATCH_PATTERN: "Dependencies-Summary-Artifact-*.txt"
+        SCRIPT_NAME: ".github/actions/setup-py-reqs/action.yml"
+      shell: bash
+      run: |
+        FILES=$(git ls-files -o --exclude-standard -- ${{ env.DEPS_MATCH_PATTERN }} )
+        if [ -z "$FILES" ]; then
+          printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
+          printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
+          exit 1
+        else
+          printf "%s\n" "DEPS summary files found:"
+          printf "%s\n" "$FILES"
+          mkdir DEPS || :
+          printf "%s\n" "$FILES" | xargs -I{} mv -f "{}" "DEPS/{}" || :
+          # Replace line breaks with spaces for GitHub Action Output
+          FILES="${FILES//$'\n'/ }"
+          printf "%s\n" "files=$FILES" >> "$GITHUB_OUTPUT"
+          exit 0
+        fi
+    - name: "Upload Details"
+      id: upload
+      if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+      with:
+        path: DEPS
+        name: ${{ steps.output_artifact_name.outputs.artifact-name }}
+        if-no-files-found: error
+        compression-level: 9
+        overwrite: true
+    - name: "Cleanup from run"
+      id: deps_cleanup_success
+      if: ${{ success() }}
+      shell: bash
+      run: |
+        rm -fRd ./DEPS 2>/dev/null || :
+    - name: "Cleanup from failed run"
+      id: deps_cleanup_failure
+      if: ${{ failure() }}
+      shell: bash
+      run: |
+        rm -fRd ./DEPS 2>/dev/null
+        exit 1
diff --git a/.github/workflows/CI-DOCS.yml b/.github/workflows/CI-DOCS.yml
index e6e9c4c9..84d5910b 100644
--- a/.github/workflows/CI-DOCS.yml
+++ b/.github/workflows/CI-DOCS.yml
@@ -9,22 +9,108 @@ run-name: Generate and lint documentation for ${{ github.ref_name }} by @${{ git
 # Required Secrets:
 # - DOCS_BUILD_REF: Automatic
 
+# Declare default permissions as none.
 permissions: {}
 
 on:  # yamllint disable-line rule:truthy
-  push:
-    branches: ["main", "master", "stable"]
-    tags: ["v*"]
-    paths: ["docs/**", ".github/workflows/CI-DOCS.yml", "**/*.md", "README.md", "LICENSE.md"]
-  pull_request:
-    types: [opened, reopened, ready_for_review]
-    branches: ["feature-*", "patch-*", "HOTFIX-*"]
-    paths: ["docs/**", ".github/workflows/CI-DOCS.yml", "**/*.md", "multicast/*.py"]
-  pull_request_target:
-    types: [opened, edited, reopened, ready_for_review]
-    branches: ["main", "master", "stable"]
+  workflow_run:
+    workflows: ["CI-MATs"]
+    types:
+      - completed
 
 jobs:
+  check_mats:
+    permissions:
+      actions: read
+      pull-requests: read
+      checks: write
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    env:
+      GH_TOKEN: ${{ github.token }}
+    outputs:
+      should_run: ${{ steps.check.outputs.should_run }}
+      trigger_id: ${{ steps.get_trigger_id.outputs.trigger_id }}
+      build_id: ${{ steps.load_build_info.outputs.build_id }}
+      build_url: ${{ steps.load_build_info.outputs.build_url }}
+      build_ref: ${{ steps.load_build_info.outputs.build_ref }}
+      build_ref_name: ${{ steps.load_build_info.outputs.build_ref_name }}
+      build_sha: ${{ steps.load_build_info.outputs.build_sha }}
+      build_artifact_filename: ${{ steps.load_build_info.outputs.build_artifact_filename }}
+      build_artifact_url: ${{ steps.load_build_info.outputs.build_artifact_url }}
+      build_artifact_id: ${{ steps.load_build_info.outputs.build_artifact_id }}
+      build_artifact_digest: ${{ steps.load_build_info.outputs.build_artifact_digest }}
+      build_environment: ${{ steps.load_build_info.outputs.build_environment }}
+      mats_environment: ${{ steps.load_build_info.outputs.mats_environment }}
+      mats_id: ${{ steps.load_build_info.outputs.mats_id }}
+      mats_url: ${{ steps.load_build_info.outputs.mats_url }}
+      mats_ref: ${{ steps.load_build_info.outputs.mats_ref }}
+      mats_ref_name: ${{ steps.load_build_info.outputs.mats_ref_name }}
+      mats_sha: ${{ steps.load_build_info.outputs.mats_sha }}
+      mats_success: ${{ steps.load_build_info.outputs.mats_success }}
+      docs_id: ${{ steps.output_run_id.outputs.docs_id }}
+      docs_check_url: ${{ steps.output_run_id.outputs.docs_url }}
+      check_id: ${{ steps.output_docs_check_id.outputs.check-id }}
+    steps:
+      - id: check
+        run: |
+          if [[ "${{ github.event.workflow_run.conclusion }}" == "success" ]]; then
+            echo "should_run=true" >> "$GITHUB_OUTPUT"
+          else
+            echo "should_run=false" >> "$GITHUB_OUTPUT"
+          fi
+      - id: get_trigger_id
+        if: ${{ (steps.check.outputs.should_run == 'true') && success() }}
+        run: |
+          ID_VALUE=$(gh api "${{ github.event.workflow_run.url }}" --jq '.id')
+          if [[ -n "$ID_VALUE" ]]; then
+            echo "trigger_id=$ID_VALUE" >> "$GITHUB_OUTPUT"
+          else
+            echo "trigger_id=null" >> "$GITHUB_OUTPUT"  # Default fallback
+          fi
+      - name: "Fetch MATs Info"
+        if: ${{ (github.repository == 'reactive-firewall/multicast') && success() }}
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: "multicast-info.txt"
+          pattern: multicast-info-*
+          repository: reactive-firewall/multicast
+          merge-multiple: true
+          github-token: ${{ env.GH_TOKEN }}
+          run-id: ${{ steps.get_trigger_id.outputs.trigger_id }}
+      - name: "move into place"
+        id: load_build_info
+        if: ${{ (github.repository == 'reactive-firewall/multicast') && success() }}
+        run: |
+          mv -vf "multicast-info.txt/multicast-info.txt" ./"multicast-info-tmp.txt" ;
+          wait ;
+          rmdir -v ./"multicast-info.txt"
+          mv -vf ./"multicast-info-tmp.txt" ./"multicast-info.txt"
+          cat <"multicast-info.txt" >> "$GITHUB_OUTPUT"
+      - id: output_run_id
+        shell: bash
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        run: |
+          printf "docs_url=%s\n" 'https://github.com/reactive-firewall/multicast/actions/runs/${{ github.run_id }}' >> "$GITHUB_OUTPUT"
+          printf "docs_id=%s\n" ${{ github.run_id }} >> "$GITHUB_OUTPUT"
+      - name: checkout repository actions for check
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
+          ref: ${{ steps.load_build_info.outputs.build_sha }}
+          sparse-checkout: '.github/actions/check-control'
+      - name: "Queue Tests GitHub Check"
+        id: output_docs_check_id
+        uses: ./.github/actions/check-control
+        with:
+          name: "CI-DOCS"
+          title: "Documentation Testing"
+          status: 'in_progress'
+          summary: 'Documentation Testing is _Starting_'
+          sha: ${{ steps.load_build_info.outputs.build_sha }}
+          workflow-run-id: ${{ steps.output_run_id.outputs.docs_id }}
+          details-url: ${{ steps.output_run_id.outputs.docs_url }}
+
   DOCS:
     permissions:
       actions: read
@@ -33,6 +119,9 @@ jobs:
       packages: none
       pull-requests: read
       security-events: none
+    environment: "Documentation"
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') }}
+    needs: [check_mats]
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
@@ -43,37 +132,60 @@ jobs:
       PYTHON_VERSION: ${{ matrix.python-version }}
       LANG: "en_US.utf-8"
       LC_CTYPE: "en_US.utf-8"
-      DOCS_BUILD_REF: ${{ github.sha }}
+      COVERAGE_RCFILE: ./.coveragerc
+      COV_CORE_SOURCE: ./
+      COV_CORE_CONFIG: ./.coveragerc
+      COV_CORE_DATAFILE: ./coverage.xml
+      CI_BRANCH: ${{ needs.check_mats.outputs.mats_ref_name }}
+      CI_COMMIT_SHA: ${{ needs.check_mats.outputs.mats_sha }}
+      BRANCH_NAME: ${{ needs.check_mats.outputs.mats_ref_name }}
+      VCS_BRANCH_NAME: ${{ needs.check_mats.outputs.build_ref_name }}
+      VCS_COMMIT_ID: ${{ needs.check_mats.outputs.build_sha }}
+      DOCS_BUILD_REF: ${{ needs.check_mats.outputs.build_sha }}
+    outputs:
+      docs_outcome: ${{ steps.generate_documentation.outcome }}
+      docs_artifact_url: ${{ steps.upload-documentation.outputs.artifact-url }}
+      docs_artifact_id: ${{ steps.upload-documentation.outputs.artifact-id }}
+      docs_artifact_digest: ${{ steps.upload-documentation.outputs.artifact-digest }}
     steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: pre-checkout repository for actions
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
         with:
           persist-credentials: false
-      - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
+          ref: ${{ needs.check_mats.outputs.build_sha }}
+          sparse-checkout: '.github/actions/checkout-and-rebuild'
+      - name: Checkout repository for Documentation with ${{ matrix.python-version }}
+        id: fetch-build
+        uses: ./.github/actions/checkout-and-rebuild
         with:
+          sha: ${{ needs.check_mats.outputs.build_sha }}
+          build-run-id: ${{ needs.check_mats.outputs.build_id }}
           python-version: ${{ matrix.python-version }}
-      - name: Fix braindead windows ${{ matrix.python-version }} on ${{ matrix.os }}
-        uses: ./.github/actions/upgrade-windows-pip
-      - name: Install dependencies for python ${{ matrix.python-version }} on ${{ matrix.os }}
-        run: |
-          pip install --upgrade "pip>=24.3.1" "setuptools>=75.0" "wheel>=0.44" "build>=1.2.1";
-          pip install -r ./requirements.txt ;
-          pip install -r ./tests/requirements.txt || true ;
-      - name: Pre-Clean
-        id: clean-prep
-        run: make -j1 -f Makefile clean ;
-      - name: Pre-build for Python ${{ matrix.python-version }} on ${{ matrix.os }}
-        run: make -j1 -f Makefile build ;
-        if: ${{ success() }}
+          path: ${{ github.workspace }}
       - name: Generate documentation with py${{ matrix.python-version }} on ${{ matrix.os }}
-        run: make -j1 -f Makefile build-docs 2>&1 >> $GITHUB_STEP_SUMMARY ;
+        id: generate_documentation
+        run: make -j1 -f Makefile build-docs
         if: ${{ !cancelled() }}
+      - id: prep-doc-part
+        if: ${{ !cancelled() }}
+        shell: bash
+        run: |
+          if [[ ( -d ./docs/www/ ) ]] ; then
+            mkdir ./Multicast-Documentation
+            mkdir ./Multicast-Documentation/${{ runner.os }}-${PYTHON_VERSION}
+            mkdir ./Multicast-Documentation/${{ runner.os }}-${PYTHON_VERSION}/docs
+            mv -vf ./docs/www ./Multicast-Documentation/${{ runner.os }}-${PYTHON_VERSION}/docs/www || exit 1
+          else
+            exit 1
+          fi
       - name: Upload Docs Artifact with Python ${{ matrix.python-version }} on ${{ matrix.os }}
+        id: upload-documentation
         uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
         with:
-          name: Multicast-Documentation-${{ github.sha }}-${{ matrix.os }}-${{ matrix.python-version }}
-          path: ./docs/www/
+          name: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-${{ matrix.os }}-${{ matrix.python-version }}
+          path: ./Multicast-Documentation
           if-no-files-found: ignore
+          overwrite: true
       - name: Post-purge
         id: post-uninstall
         run: make -j1 -f Makefile purge || true ;
@@ -82,3 +194,108 @@ jobs:
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.DOCS.outputs.docs_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=false" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "  * :x: Generating Documentation Failed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "docs_summary=Generating Documentation Unsuccessful" >> "$GITHUB_OUTPUT"
+          fi
+          cat <"${DOCUMENTATION_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY"
+          { printf "%s\n" 'docs_text<<EOF'; cat <"${DOCUMENTATION_COMMENT_BODY}"; printf "%s\n" 'EOF'; } >> "$GITHUB_OUTPUT"
+      - name: "Upload DOCs summary"
+        id: upload-docs-summary
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: ./DOCUMENTATION-Summary-Artifact.txt
+          name: DOCUMENTATION-COMMENT-BODY-${{ needs.check_mats.outputs.build_sha }}
+          if-no-files-found: error
+          compression-level: 3
+          retention-days: 2
+          overwrite: true
+      - name: "Upload DOCs Bundle"
+        id: upload-docs-bundle
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: Multicast-Documentation
+          name: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-ALL
+          if-no-files-found: error
+          compression-level: 9
+          overwrite: true
+      - name: checkout repository actions for check
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
+          ref: ${{ needs.check_mats.outputs.build_sha }}
+          sparse-checkout: '.github/actions/check-control'
+      - name: "Compleate DOCs GitHub Check"
+        id: compleate_docs
+        if: ${{ (github.repository == 'reactive-firewall/multicast') && always() }}
+        uses: ./.github/actions/check-control
+        with:
+          name: "CI-DOCS"
+          check-id: ${{ needs.check_mats.outputs.check_id }}
+          title: "Documentation Testing"
+          status: 'completed'
+          conclusion: ${{ needs.DOCS.outputs.docs_outcome }}
+          summary: ${{ steps.report_status.outputs.docs_summary }}
+          text: ${{ steps.report_status.outputs.docs_text }}
+          sha: ${{ needs.check_mats.outputs.build_sha }}
+          workflow-run-id: ${{ needs.check_mats.outputs.docs_id }}
+          details-url: ${{ needs.check_mats.outputs.docs_check_url }}
+
+  DOCS_REPORT:
+    permissions:
+      actions: read
+      contents: write
+    needs: [check_mats, DOCS_SUMMARY]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() }}
+    steps:
+      - name: "Download Status Summary Artifact"
+        id: download-documentation-summary
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          name: DOCUMENTATION-COMMENT-BODY-${{ needs.check_mats.outputs.build_sha }}
+          github-token: ${{ github.token }}
+      - name: "DOCs commit comment"
+        id: documentation-commit-comment
+        if: ${{ success() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: peter-evans/commit-comment@5a6f8285b8f2e8376e41fe1b563db48e6cf78c09 # v3.0.0
+        with:
+          sha: ${{ needs.check_mats.outputs.build_sha }}
+          token: ${{ github.token }}
+          body-path: '${{ steps.download-documentation-summary.outputs.download-path }}/DOCUMENTATION-Summary-Artifact.txt'
diff --git a/.github/workflows/Tests.yml b/.github/workflows/Tests.yml
index 7925b89e..e11bb03c 100644
--- a/.github/workflows/Tests.yml
+++ b/.github/workflows/Tests.yml
@@ -1,5 +1,7 @@
 ---
 name: CI-TESTS
+description: "Continuous Integration for post-MATs additional testing, and validation."
+run-name: Extended Testing
 # Continuous Integration workflow for post-MATs additional testing, and validating of the project.
 #
 # Jobs included:
@@ -107,7 +109,7 @@ jobs:
           ref: ${{ steps.load_build_info.outputs.build_sha }}
           sparse-checkout: '.github/actions/check-control'
       - name: "Queue Tests GitHub Check"
-        id: output_mats_check_id
+        id: output_tests_check_id
         uses: ./.github/actions/check-control
         with:
           name: "CI-TESTs"
@@ -166,7 +168,7 @@ jobs:
         persist-credentials: false
         ref: ${{ needs.check_mats.outputs.build_sha }}
         sparse-checkout: '.github/actions/checkout-and-rebuild'
-    - name: Checkout repository for MATs with ${{ matrix.python-version }}
+    - name: Checkout repository for Tests with ${{ matrix.python-version }}
       id: fetch-build
       uses: ./.github/actions/checkout-and-rebuild
       with:
@@ -174,6 +176,13 @@ jobs:
         build-run-id: ${{ needs.check_mats.outputs.build_id }}
         python-version: ${{ matrix.python-version }}
         path: ${{ github.workspace }}
+    - name: Install dependencies for python ${{ matrix.python-version }} on ${{ matrix.os }}
+      id: install-coverage-deps
+      if: ${{ success() }}
+      uses: ./.github/actions/setup-py-reqs
+      with:
+        sha: ${{ needs.check_mats.outputs.build_sha }}
+        python-version: ${{ matrix.python-version }}
     - name: Install coverage tools for ${{ matrix.python-version }} on ${{ matrix.os }}
       id: fetch-test-tools
       if: ${{ !cancelled() && runner.os != 'Windows' }}
@@ -324,7 +333,7 @@ jobs:
           printf "%s\n" "  * :x: ~Codebase Coverage Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`~" > "$COV_STEP_SUMMARY"
           printf "%s\n" " :x: ~Codebase Coverage Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\`~" >> "$GITHUB_STEP_SUMMARY"
         fi
-        printf "\n%s\n\n" "<details></summary>Coverage Details</summary>" >> "$COV_STEP_SUMMARY"
+        printf "\n%s\n\n" "<details><summary>Coverage Details</summary>" >> "$COV_STEP_SUMMARY"
         if [[ "${{ steps.coverage_tests.outcome }}" == "success" ]] ; then
           printf "%s\n" "  * :ballot_box_with_check: Codebase coverage was collected from testing" >> "$COV_STEP_SUMMARY"
         else
@@ -380,7 +389,7 @@ jobs:
         SCRIPT_NAME: ".github/actions/run-coverage-tests/action.yml"
       shell: bash
       run: |
-        FILES=$(git ls-files -o --exclude-standard -- ${{ env.MATS_MATCH_PATTERN }} )
+        FILES=$(git ls-files -o --exclude-standard -- ${{ env.COV_MATCH_PATTERN }} )
         if [ -z "$FILES" ]; then
           printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
           printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
@@ -453,7 +462,7 @@ jobs:
         persist-credentials: false
         ref: ${{ needs.check_mats.outputs.build_sha }}
         sparse-checkout: '.github/actions/checkout-and-rebuild'
-    - name: Checkout repository for MATs with ${{ matrix.python-version }}
+    - name: Checkout repository for Tests with ${{ matrix.python-version }}
       id: fetch-build
       uses: ./.github/actions/checkout-and-rebuild
       with:
@@ -461,6 +470,13 @@ jobs:
         build-run-id: ${{ needs.check_mats.outputs.build_id }}
         python-version: ${{ matrix.python-version }}
         path: ${{ github.workspace }}
+    - name: Install dependencies for python ${{ matrix.python-version }} on ${{ matrix.os }}
+      id: install-doctests-deps
+      if: ${{ success() }}
+      uses: ./.github/actions/setup-py-reqs
+      with:
+        sha: ${{ needs.check_mats.outputs.build_sha }}
+        python-version: ${{ matrix.python-version }}
     - name: Install coverage tools for ${{ matrix.python-version }} on ${{ matrix.os }}
       id: fetch-test-tools
       if: ${{ !cancelled() && runner.os != 'Windows' }}
@@ -586,7 +602,7 @@ jobs:
           printf "%s\n" "  * :x: ~Doctests succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`~" > "$DOC_STEP_SUMMARY"
           printf "%s\n" " :x: ~Doctests succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\`~" >> "$GITHUB_STEP_SUMMARY"
         fi
-        printf "\n%s\n\n" "<details></summary>Doctests Details</summary>" >> "$DOC_STEP_SUMMARY"
+        printf "\n%s\n\n" "<details><summary>Doctests Details</summary>" >> "$DOC_STEP_SUMMARY"
         if [[ "${{ steps.doctests-main.outcome }}" == "success" ]] ; then
           printf "%s\n" "  * :ballot_box_with_check: Doctests succeeded" >> "$DOC_STEP_SUMMARY"
         else
@@ -667,7 +683,6 @@ jobs:
     permissions:
       actions: read
       pull-requests: read
-      checks: write
     needs: [check_mats, COVERAGE, DOCTESTS]
     runs-on: ubuntu-latest
     if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.COVERAGE.outputs.coverage_outcome != 'cancelled') }}
@@ -709,8 +724,8 @@ jobs:
           done ;
           cat <"${COV_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY"
           { printf "%s\n" 'tests_text<<EOF'; cat <"${COV_COMMENT_BODY}"; printf "%s\n" 'EOF'; } >> "$GITHUB_OUTPUT"
-      - name: "Upload MATs summary"
-        id: upload-mats-summary
+      - name: "Upload COVERAGE summary"
+        id: upload-coverage-summary
         if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
         uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
         with:
@@ -726,21 +741,6 @@ jobs:
           persist-credentials: false
           ref: ${{ needs.check_mats.outputs.build_sha }}
           sparse-checkout: '.github/actions/check-control'
-      - name: "Compleate MATs GitHub Check"
-        id: compleate_mats
-        if: ${{ (github.repository == 'reactive-firewall/multicast') && always() }}
-        uses: ./.github/actions/check-control
-        with:
-          name: "CI-TESTs"
-          check-id: ${{ needs.check_mats.outputs.check_id }}
-          title: "Extended Testing"
-          status: 'completed'
-          conclusion: ${{ needs.COVERAGE.outputs.coverage_outcome }}
-          summary: ${{ steps.report_status.outputs.tests_summary }}
-          text: ${{ steps.report_status.outputs.tests_text }}
-          sha: ${{ needs.check_mats.outputs.build_sha }}
-          workflow-run-id: ${{ needs.check_mats.outputs.tests_id }}
-          details-url: ${{ needs.check_mats.outputs.tests_url }}
 
   COVERAGE_REPORT:
     permissions:
@@ -797,7 +797,7 @@ jobs:
         persist-credentials: false
         ref: ${{ needs.check_mats.outputs.build_sha }}
         sparse-checkout: '.github/actions/checkout-and-rebuild'
-    - name: Checkout repository for MATs with ${{ matrix.python-version }}
+    - name: "Checkout repository for Style with ${{ vars.PYTHON_DEFAULT }}"
       id: fetch-build
       uses: ./.github/actions/checkout-and-rebuild
       with:
@@ -805,11 +805,13 @@ jobs:
         build-run-id: ${{ needs.check_mats.outputs.build_id }}
         path: ${{ github.workspace }}
         python-version: "${{ vars.PYTHON_DEFAULT }}"
-    - name: Install dependencies for python Linters
+    - name: Install dependencies for style
+      id: install-deps
       if: ${{ success() }}
-      id: doc-deps-for-style
-      run: |
-        pip install -r ./docs/requirements.txt || true ;
+      uses: ./.github/actions/setup-py-reqs
+      with:
+        sha: ${{ needs.check_mats.outputs.build_sha }}
+        python-version: "${{ vars.PYTHON_DEFAULT }}"
     - name: Pre-Clean
       id: clean-up-style
       run: make -j1 -f Makefile clean || true ;
@@ -856,6 +858,20 @@ jobs:
       VCS_COMMIT_ID: ${{ needs.check_mats.outputs.build_sha }}
       CODECLIMATE_REPO_TOKEN: ${{ secrets.CODECLIMATE_REPO_TOKEN }}
       CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
+    outputs:
+      integration_outcome: ${{ steps.integration_outcome.outcome }}
+      integration_test_outcome: ${{ steps.integration_tests.outputs.integration_test_outcome }}
+      integration_pytest_outcome: ${{ steps.integration-pytest.outcome }}
+      integration_doctest_outcome: ${{ steps.integration-doctests.outcome }}
+      integration_function_outcome: ${{ steps.integration-main.outcome }}
+      integration_upload_codecov_test_outcome: ${{ steps.integration-codecov-results-upload.outcome }}
+      integration_upload_codecov_coverage_outcome: ${{ steps.integration-codecov-upload.outcome }}
+      integration_upload_codeclimate_outcome: ${{ steps.integration-codeclimate-upload.outcome }}
+      integration_upload_deepsource_outcome: ${{ steps.integration-deepsource-upload.outcome }}
+      integration_upload_artifact_outcome: ${{ steps.integration-reports-upload.outcome }}
+      integration_artifact_url: ${{ steps.integration-reports-upload.outputs.artifact-url }}
+      integration_artifact_id: ${{ steps.integration-reports-upload.outputs.artifact-id }}
+      integration_artifact_digest: ${{ steps.integration-reports-upload.outputs.artifact-digest }}
     steps:
     - name: pre-checkout repository for actions
       uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -863,7 +879,7 @@ jobs:
         persist-credentials: false
         ref: ${{ needs.check_mats.outputs.build_sha }}
         sparse-checkout: '.github/actions/checkout-and-rebuild'
-    - name: Checkout repository for MATs with ${{ matrix.python-version }}
+    - name: Checkout repository for Tests with ${{ matrix.python-version }}
       id: fetch-build
       uses: ./.github/actions/checkout-and-rebuild
       with:
@@ -872,11 +888,12 @@ jobs:
         python-version: ${{ matrix.python-version }}
         path: ${{ github.workspace }}
     - name: Install dependencies for python ${{ matrix.python-version }} on ${{ matrix.os }}
-      run: |
-        pip install --upgrade "pip>=24.3.1" "setuptools>=75.0" "wheel>=0.44" "build>=1.2.1";
-        pip install --upgrade -r ./requirements.txt ;
-        pip install --upgrade -r ./tests/requirements.txt || true ;
-        pip install --upgrade -r ./docs/requirements.txt || true ;
+      id: install-deps
+      if: ${{ !cancelled() }}
+      uses: ./.github/actions/setup-py-reqs
+      with:
+        sha: ${{ needs.check_mats.outputs.build_sha }}
+        python-version: ${{ matrix.python-version }}
     - name: Install coverage tools for ${{ matrix.python-version }} on ${{ matrix.os }}
       id: fetch-test-tools
       if: ${{ !cancelled() && runner.os != 'Windows' }}
@@ -887,28 +904,26 @@ jobs:
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
-    - name: Pre-Clean
-      id: clean-prep
-      run: make -j1 -f Makefile clean ;
-    - name: Pre-build for Python ${{ matrix.python-version }} on ${{ matrix.os }}
-      run: make -j1 -f Makefile build ;
-      if: ${{ success() }}
     - name: Pre-install for Python ${{ matrix.python-version }} on ${{ matrix.os }}
       run: make -j1 -f Makefile user-install || true ;
       if: ${{ success() }}
     - name: Re-Generate Test Coverage for py${{ matrix.python-version }} on ${{ matrix.os }}
+      id: integration-pytest
       run: |
         make -j1 -f Makefile test-pytest ;
         cp -vf ./coverage.xml ./test-reports/coverage.xml || true ;
       shell: bash
     - name: Generate Doctest Coverage for py${{ matrix.python-version }} on ${{ matrix.os }}
+      id: integration-doctests
       run: make -f Makefile test-mat-doctests ;
-    - name: Generate Extra Coverage for py${{ matrix.python-version }} on ${{ matrix.os }}
+    - name: Generate Functional Test Coverage for py${{ matrix.python-version }} on ${{ matrix.os }}
+      id: integration-main
       run: |
         hash -p ./.github/tool_shlock_helper.sh shlock ;
         ./tests/check_integration_coverage || echo "::warning file=tests/check_integration_coverage,line=1,endLine=1,title=SKIPPED::SKIP Integration Tests." ;
       shell: bash
     - name: Upload Python ${{ matrix.python-version }} integration coverage to Codecov
+      id: integration-codecov-upload
       uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5.4.2
       with:
         token: ${{ secrets.CODECOV_TOKEN }}
@@ -916,27 +931,42 @@ jobs:
         override_commit: ${{ needs.check_mats.outputs.build_sha }}
         files: ./test-reports/coverage_supplement.xml,./test-reports/coverage_doctests.xml,./test-reports/coverage.xml
         directory: .
-        env_vars: OS,PYTHON_VERSION,CI_COMMIT_SHA
         flags: multicast
         name: multicast-github-${{ matrix.os }}-${{ matrix.python-version }}
         verbose: true
         fail_ci_if_error: false
     - name: Upload Extra Python ${{ matrix.python-version }} Artifact
+      id: integration-reports-upload
       uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
       with:
         name: Integration-Test-Report-${{ matrix.os }}-${{ matrix.python-version }}
         path: ./test-reports/
         if-no-files-found: ignore
-    - name: code-climate for ${{ matrix.python-version }}
-      if: ${{ !cancelled() && runner.os != 'Linux' }}
+        overwrite: true
+    - name: code-climate for ${{ matrix.python-version }} on ${{ matrix.os }}
+      if: ${{ !cancelled() && runner.os != 'Windows' }}
+      id: integration-codeclimate-upload
+      shell: bash
+      env:
+        CODECLIMATE_REPO_TOKEN: ${{ secrets.CODECLIMATE_REPO_TOKEN }}
+        CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
       run: |
-        if [ "$OS" == "macos-latest" ] ; then ./cc-test-reporter after-build --exit-code 0 || true ; else echo "::warning file=.github/workflows/Tests.yml,line=459,endLine=459,title=SKIPPED::SKIP Code-Climate" ; fi ;
-    - name: code-climate for ${{ matrix.python-version }}
-      if: ${{ !cancelled() && runner.os == 'Linux' }}
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          ./cc-test-reporter after-build --exit-code 0 || exit 1 ;
+        else
+          ./cc-test-reporter after-build --exit-code 1 || true ;
+        fi
+    - name: deepsource for ${{ matrix.python-version }} on ${{ matrix.os }}
+      if: ${{ !cancelled() && runner.os != 'Windows' }}
+      id: integration-deepsource-upload
+      shell: bash
+      env:
+        DEEPSOURCE_DSN: ${{ secrets.DEEPSOURCE_DSN }}
       run: |
-        ./cc-test-reporter after-build --exit-code 0 || true ;
+        ./bin/deepsource report --analyzer test-coverage --key python --value-file ./coverage.xml 2>/dev/null || true ;
     - name: Upload Python ${{ matrix.python-version }} integration test results to Codecov
       if: ${{ !cancelled() }}
+      id: integration-codecov-results-upload
       uses: codecov/test-results-action@f2dba722c67b86c6caa034178c6e4d35335f6706 # v1.1.0
       with:
         token: ${{ secrets.CODECOV_TOKEN }}
@@ -947,7 +977,7 @@ jobs:
         verbose: true
         fail_ci_if_error: false
     - name: Finalize coverage tools for ${{ matrix.python-version }} on ${{ matrix.os }}
-      id: purge-doctest-test-tools
+      id: purge-integration-test-tools
       if: ${{ !cancelled() && runner.os != 'Windows' }}
       uses: ./.github/actions/purge-test-reporter
       with:
@@ -956,6 +986,221 @@ jobs:
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
+    - name: "Generate Summary Filename"
+      id: output_integration_step_summary
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "integration-artifact-name=%s\n" multicast-integration-${VCS_COMMIT_ID}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "integration-artifact-name=%s" multicast-integration-${VCS_COMMIT_ID}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Evaluate Integration Tests"
+      id: integration_tests
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-main.outcome }}" == "failure" ]] ; then
+            THE_RESULT="failure"
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-pytest.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-doctests.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            if [[ "${THE_RESULT}" != "failure" ]] ; then
+              if [[ "${THE_RESULT}" != "neutral" ]] ; then
+                THE_RESULT="skipped"
+              else
+                THE_RESULT="neutral"
+              fi
+            else
+              THE_RESULT="failure"
+            fi
+          fi
+        fi
+        printf "%s\n" "integration_test_outcome=${THE_RESULT}" >> "$GITHUB_OUTPUT"
+        if [[ "${THE_RESULT}" != "failure" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Evaluate Integration Tests"
+      id: integration_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration_tests.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-reports-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize Tests"
+      id: integration_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        BUILD_LINK="[${VCS_COMMIT_ID}](https://github.com/reactive-firewall/multicast/commit/${VCS_COMMIT_ID})"
+        if [[ "${{ steps.integration_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n\n" "## :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for ${BUILD_LINK}" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n\n" "## :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`~" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Functional testing succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Functional testing failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Acceptance testing with \`pytest\` succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Acceptance testing with \`pytest\` failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Uploading integration testing reports artifact succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Uploading integration testing reports artifact failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Integrated Doctesting succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Integrated Doctesting failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        printf "\n%s\n\n" "<details><summary>Reporting Details</summary>" >> "$TESTS_STEP_SUMMARY"
+        printf "%s\n\n" "### :open_umbrella: Functional testing coverage reporting" >> "$TESTS_STEP_SUMMARY"
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to CodeCov succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-codecov-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to CodeCov failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to CodeCov was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to codeclimate succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-codeclimate-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to codeclimate failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to codeclimate was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to deepsource succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-deepsource-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to deepsource failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to deepsource was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        printf "\n%s\n\n" "</details>" >> "$TESTS_STEP_SUMMARY"
+        if [[ "${{ steps.integration-reports-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Uploading [integration coverage report artifact](${{ steps.integration-reports-upload.outputs.artifact-url }}) succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Uploading integration coverage report artifact failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+    - name: "Collect and Enumerate Generated Files"
+      id: output_summary_files
+      if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+      env:
+        TEST_MATCH_PATTERN: "Integration-Summary-Artifact-*.txt"
+        SCRIPT_NAME: ".github/actions/run-integration-tests/action.yml"
+      shell: bash
+      run: |
+        FILES=$(git ls-files -o --exclude-standard -- ${{ env.TEST_MATCH_PATTERN }} )
+        if [ -z "$FILES" ]; then
+          printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
+          printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
+          exit 1
+        else
+          printf "%s\n" "Test integration summary files found:"
+          printf "%s\n" "$FILES"
+          mkdir EXTRAS || :
+          printf "%s\n" "$FILES" | xargs -I{} cp -f "{}" "EXTRAS/{}" || :
+          # Replace line breaks with spaces for GitHub Action Output
+          FILES="${FILES//$'\n'/ }"
+          printf "%s\n" "files=$FILES" >> "$GITHUB_OUTPUT"
+          exit 0
+        fi
+    - name: "Upload integration Summary"
+      id: upload
+      if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+      with:
+        path: EXTRAS
+        name: ${{ steps.output_integration_step_summary.outputs.integration-artifact-name }}
+        if-no-files-found: error
+        compression-level: 9
+        overwrite: true
     - name: Post-purge
       id: post-uninstall
       run: make -j1 -f Makefile purge || true ;
@@ -965,6 +1210,108 @@ jobs:
       run: make -j1 -f Makefile clean || true ;
       if: ${{ !cancelled() }}
 
+  INTEGRATION_SUMMARY:
+    permissions:
+      actions: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, INTEGRATION]
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.INTEGRATION.outputs.integration_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/EXTRAS
+          pattern: multicast-integration-${{ needs.check_mats.outputs.build_sha }}-part-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          TESTS_COMMENT_BODY: '${{ github.workspace }}/Integration-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.INTEGRATION.outputs.integration_outcome }}" == "success" ]]; then
+            printf "%s\n" "# :clipboard: Testing Summary" > "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "test_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "tests_summary=CI Tests Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${TESTS_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "test_success=false" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "tests_summary=Some Tests Unsuccessful" >> "$GITHUB_OUTPUT"
+          fi
+          for OS_TAG in "Linux" "macOS" "Windows" ; do
+            for TYPE_TAG in "Integration" ; do
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+              cat <./EXTRAS/"${TYPE_TAG}-Summary-Artifact-${OS_TAG}-${{ vars.PYTHON_OLD_MIN }}.txt" >> "${TESTS_COMMENT_BODY}" || :
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+              cat <./EXTRAS/"${TYPE_TAG}-Summary-Artifact-${OS_TAG}-${{ vars.PYTHON_OLD_EXTRA }}.txt" >> "${TESTS_COMMENT_BODY}" || :
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+              cat <./EXTRAS/"${TYPE_TAG}-Summary-Artifact-${OS_TAG}-${{ vars.PYTHON_DEFAULT }}.txt" >> "${TESTS_COMMENT_BODY}" || :
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+              cat <./EXTRAS/"${TYPE_TAG}-Summary-Artifact-${OS_TAG}-${{ vars.PYTHON_EXPERIMENTAL }}.txt" >> "${TESTS_COMMENT_BODY}" || :
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+            done ;
+          done ;
+          cat <"${TESTS_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY"
+          { printf "%s\n" 'tests_text<<EOF'; cat <"${TESTS_COMMENT_BODY}"; printf "%s\n" 'EOF'; } >> "$GITHUB_OUTPUT"
+      - name: "Upload INTEGRATION summary"
+        id: upload-integration-summary
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: ./Integration-Summary-Artifact.txt
+          name: INTEGRATION-COMMENT-BODY-${{ needs.check_mats.outputs.build_sha }}
+          if-no-files-found: error
+          compression-level: 3
+          retention-days: 2
+          overwrite: true
+      - name: checkout repository actions for check
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
+          ref: ${{ needs.check_mats.outputs.build_sha }}
+          sparse-checkout: '.github/actions/check-control'
+      - name: "Complete Tests GitHub Check"
+        id: complete_tests
+        if: ${{ (github.repository == 'reactive-firewall/multicast') && always() }}
+        uses: ./.github/actions/check-control
+        with:
+          name: "CI-TESTs"
+          check-id: ${{ needs.check_mats.outputs.check_id }}
+          title: "Extended Testing"
+          status: 'completed'
+          conclusion: ${{ needs.INTEGRATION.outputs.integration_test_outcome }}
+          summary: ${{ steps.report_status.outputs.tests_summary }}
+          text: ${{ steps.report_status.outputs.tests_text }}
+          sha: ${{ needs.check_mats.outputs.build_sha }}
+          workflow-run-id: ${{ needs.check_mats.outputs.tests_id }}
+          details-url: ${{ needs.check_mats.outputs.tests_url }}
+
+  INTEGRATION_REPORT:
+    permissions:
+      actions: read
+      contents: write
+    needs: [check_mats, INTEGRATION_SUMMARY]
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() }}
+    steps:
+      - name: "Download Status Summary Artifact"
+        id: download-integration-summary
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          name: INTEGRATION-COMMENT-BODY-${{ needs.check_mats.outputs.build_sha }}
+          github-token: ${{ github.token }}
+      - name: "INTEGRATION commit comment"
+        id: integration-commit-comment
+        if: ${{ success() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: peter-evans/commit-comment@5a6f8285b8f2e8376e41fe1b563db48e6cf78c09 # v3.0.0
+        with:
+          sha: ${{ needs.check_mats.outputs.build_sha }}
+          token: ${{ github.token }}
+          body-path: '${{ steps.download-integration-summary.outputs.download-path }}/Integration-Summary-Artifact.txt'
 
   EXTRAS-FOR-SETUP:
     permissions:
@@ -1008,7 +1355,7 @@ jobs:
         persist-credentials: false
         ref: ${{ needs.check_mats.outputs.build_sha }}
         sparse-checkout: '.github/actions/checkout-and-rebuild'
-    - name: Checkout repository for MATs with ${{ matrix.python-version }}
+    - name: Checkout repository for Tests with ${{ matrix.python-version }}
       id: fetch-build
       uses: ./.github/actions/checkout-and-rebuild
       with:
@@ -1084,7 +1431,7 @@ jobs:
         persist-credentials: false
         ref: ${{ needs.check_mats.outputs.build_sha }}
         sparse-checkout: '.github/actions/checkout-and-rebuild'
-    - name: Checkout repository for MATs with ${{ matrix.python-version }}
+    - name: Checkout repository for Tests with ${{ matrix.python-version }}
       id: fetch-build
       uses: ./.github/actions/checkout-and-rebuild
       with:
@@ -1146,7 +1493,7 @@ jobs:
         persist-credentials: false
         ref: ${{ needs.check_mats.outputs.build_sha }}
         sparse-checkout: '.github/actions/checkout-and-rebuild'
-    - name: Checkout repository for MATs with ${{ matrix.python-version }}
+    - name: Checkout repository for Tests with ${{ matrix.python-version }}
       id: fetch-build
       uses: ./.github/actions/checkout-and-rebuild
       with:
diff --git a/Makefile b/Makefile
index 70838b0a..132726ee 100644
--- a/Makefile
+++ b/Makefile
@@ -171,10 +171,14 @@ MANIFEST.in: init
 	$(QUIET)$(ECHO) "include HISTORY.md" >>"$@" ;
 	$(QUIET)$(ECHO) "recursive-include . *.txt" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .gitignore" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .git_skipList" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .gitattributes" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .gitmodules" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .deepsource.toml" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.ini" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.yml" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.yaml" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .*.conf" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude package.json" >>"$@" ;
 	$(QUIET)$(ECHO) "global-exclude .git" >>"$@" ;
 	$(QUIET)$(ECHO) "global-exclude codecov_env" >>"$@" ;
@@ -203,7 +207,7 @@ init: branding
 	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) -r requirements.txt 2>$(ERROR_LOG_PATH) || :
 	$(QUIET)$(ECHO) "$@: Done."
 
-install: init build
+install: init ./dist
 	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) dist/multicast-*-py3-*.whl
 	$(QUIET)$(WAIT)
 	$(QUIET)$(ECHO) "$@: Done."
@@ -233,6 +237,9 @@ purge: purge-coverage-artifacts purge-test-reports
 	$(QUIET)$(WAIT)
 	$(QUIET)$(ECHO) "$@: Done."
 
+./dist: build
+	$(QUIET)$(WAIT) ;
+
 test: just-test
 	$(QUIET)$(DO_FAIL) ;
 	$(QUIET)$(COVERAGE) combine 2>$(ERROR_LOG_PATH) || : ;
@@ -461,9 +468,7 @@ must_be_root:
 	$(QUIET)runner=`whoami` ; \
 	if test $$runner != "root" ; then $(ECHO) "You are not root." ; exit 1 ; fi
 
-user-install: build
-	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user "pip>=24.3.1" "setuptools>=75.0" "wheel>=0.44" "build>=1.1.1" 2>$(ERROR_LOG_PATH) || true
-	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user -r "https://raw.githubusercontent.com/reactive-firewall/multicast/stable/requirements.txt" 2>$(ERROR_LOG_PATH) || true
+user-install: ./dist
 	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user dist/multicast-*-py3-*.whl
 	$(QUIET)$(WAIT)
 	$(QUIET)$(ECHO) "$@: Done."
diff --git a/tests/check_spelling b/tests/check_spelling
index 2717c9ee..9a9303ef 100755
--- a/tests/check_spelling
+++ b/tests/check_spelling
@@ -154,6 +154,7 @@ declare -a SPECIFIC_TYPOS=(
 	"boundry:boundary"  # from #384
 	"rappidly:rapidly"  # from #392
 	"compleated:completed"  # from #338
+	"compleate:complete"  # from #402
 )
 
 function cleanup() {


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 6**

<details>
<summary>🔭 Outside diff range comments (2)</summary><blockquote>

<details>
<summary>Makefile (1)</summary><blockquote>

`72-82`: _🧹 Nitpick (assertive)_

**Simplify Python version fallback**  
The nested `ifeq "$(PYTHON_VERSION)" ""` block works but can be simplified for readability and reliability. Consider using GNU Make’s conditional assignment instead of nested directives:

```diff
-PYTHON ?= 
-ifeq "$(PYTHON)" ""
-	ifeq "$(PYTHON_VERSION)" ""
-		PYTHON_VERSION=3
-	endif
-	PY_CMD=$(COMMAND) python$(PYTHON_VERSION)
-	ifneq "$(PY_CMD)" ""
-		PY_ARGS=-B
-	else
-		PY_CMD=$(COMMAND) python
-	endif
-	PYTHON=$(PY_CMD) $(PY_ARGS)
-endif
+PYTHON_VERSION ?= 3
+PY_CMD := $(COMMAND) python$(PYTHON_VERSION)
+PY_ARGS := -B
+PYTHON := $(PY_CMD) $(PY_ARGS)
```  
This uses `?=` for a cleaner default and avoids indent-sensitive `ifeq` blocks.

</blockquote></details>
<details>
<summary>.github/workflows/Tests.yml (1)</summary><blockquote>

`392-399`: _⚠️ Potential issue_

**Fix artifact pattern variable in coverage summary**  
The summary collection step references an undefined `env.MATS_MATCH_PATTERN`. It should use `env.COV_MATCH_PATTERN`:

```diff
- FILES=$(git ls-files -o --exclude-standard -- ${{ env.MATS_MATCH_PATTERN }} )
+ FILES=$(git ls-files -o --exclude-standard -- ${{ env.COV_MATCH_PATTERN }} )
```  
This ensures coverage summary files are correctly gathered.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: ASSERTIVE**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 161dc6f3bec9ba1643c50edd44e9943b011b85b3 and dcd09c453b83cafa3cb33163be3d8015b706928f.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `.github/actions/setup-py-reqs/action.yml` (1 hunks)
* `.github/workflows/CI-DOCS.yml` (4 hunks)
* `.github/workflows/Tests.yml` (17 hunks)
* `Makefile` (5 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (1)</summary>

<details>
<summary>`.github/**`: * When the project is hosted on GitHub: All GitHub-specific configurations, templates,
  and tools should be found in the '.github' directory tree.
* 'actionlint' err...</summary>

> `.github/**`: * When the project is hosted on GitHub: All GitHub-specific configurations, templates,
>   and tools should be found in the '.github' directory tree.
> * 'actionlint' erroneously generates false positives when dealing with
>   GitHub's `${{ ... }}` syntax in conditionals.
> * 'actionlint' erroneously generates incorrect solutions when suggesting the removal of
>   valid `${{ ... }}` syntax.

- `.github/actions/setup-py-reqs/action.yml`
- `.github/workflows/CI-DOCS.yml`
- `.github/workflows/Tests.yml`

</details>

</details><details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>📓 Common learnings</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>

</details><details>
<summary>🪛 actionlint (1.7.7)</summary>

<details>
<summary>.github/workflows/CI-DOCS.yml</summary>

219-219: property "coverage" is not defined in object type {check_mats: {outputs: {build_artifact_digest: string; build_artifact_filename: string; build_artifact_id: string; build_artifact_url: string; build_environment: string; build_id: string; build_ref: string; build_ref_name: string; build_sha: string; build_url: string; check_id: string; docs_check_url: string; docs_id: string; mats_environment: string; mats_id: string; mats_ref: string; mats_ref_name: string; mats_sha: string; mats_success: string; mats_url: string; should_run: string; trigger_id: string}; result: string}; docs: {outputs: {docs_artifact_digest: string; docs_artifact_id: string; docs_artifact_url: string; docs_outcome: string}; result: string}}

(expression)

---

271-271: property "coverage" is not defined in object type {check_mats: {outputs: {build_artifact_digest: string; build_artifact_filename: string; build_artifact_id: string; build_artifact_url: string; build_environment: string; build_id: string; build_ref: string; build_ref_name: string; build_sha: string; build_url: string; check_id: string; docs_check_url: string; docs_id: string; mats_environment: string; mats_id: string; mats_ref: string; mats_ref_name: string; mats_sha: string; mats_success: string; mats_url: string; should_run: string; trigger_id: string}; result: string}; docs: {outputs: {docs_artifact_digest: string; docs_artifact_id: string; docs_artifact_url: string; docs_outcome: string}; result: string}}

(expression)

</details>
<details>
<summary>.github/workflows/Tests.yml</summary>

3-3: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

---

800-800: property "python-version" is not defined in object type {}

(expression)

---

863-863: property "integration_test_outcome" is not defined in object type {conclusion: string; outcome: string; outputs: {string => string}}

(expression)

---

1496-1496: property "python-version" is not defined in object type {}

(expression)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

<details>
<summary>.github/workflows/Tests.yml</summary>

[error] 876-876: wrong indentation: expected 6 but found 4

(indentation)

---

[warning] 877-877: too few spaces before comment: expected 2

(comments)

---

[warning] 927-927: too few spaces before comment: expected 2

(comments)

---

[warning] 940-940: too few spaces before comment: expected 2

(comments)

---

[warning] 1197-1197: too few spaces before comment: expected 2

(comments)

---

[warning] 1223-1223: too few spaces before comment: expected 2

(comments)

---

[warning] 1262-1262: too few spaces before comment: expected 2

(comments)

---

[warning] 1271-1271: too few spaces before comment: expected 2

(comments)

---

[warning] 1303-1303: too few spaces before comment: expected 2

(comments)

---

[warning] 1310-1310: too few spaces before comment: expected 2

(comments)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: CI-TESTs

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>Makefile (2)</summary>

`176-184`: **Updated `MANIFEST.in` exclusions for CI artifacts**  
Adding exclusions for `.git_skipList`, `.gitattributes`, `.gitmodules`, and `*.conf` aligns the manifest with your CI/CD cleanup needs. This keeps package artifacts clean.

---

`213-217`: **Ensure wheel build before installation**  
Tying both `install` and `user-install` to `./dist` ensures that a fresh wheel is always built prior to pip installation. This strengthens your CI reproducibility.  



Also applies to: 474-478

</details>
<details>
<summary>.github/workflows/CI-DOCS.yml (2)</summary>

`12-14`: **Principle of least privilege with global permissions**  
Setting `permissions: {}` at the top and granting only what each job needs is excellent for security.

---

`15-20`: **Trigger exclusively on `CI-MATs` completion**  
Switching the trigger to a `workflow_run` for `"CI-MATs"` ensures documentation runs only after the MATs job completes. This tightens your pipeline dependencies.

</details>
<details>
<summary>.github/workflows/Tests.yml (4)</summary>

`112-119`: **Improve clarity by naming the check ID step**  
Adding `id: output_tests_check_id` to the check-queuing step enhances readability and aligns with other workflows.

---

`179-185`: **Use `setup-py-reqs` for coverage dependencies**  
Replacing ad-hoc pip calls with your composite action (`.github/actions/setup-py-reqs`) standardizes dependency installation across matrix jobs.

---

`808-815`: **Apply `setup-py-reqs` in STYLE job**  
Using the new composite action for style dependencies mirrors the approach in COVERAGE and DOCTESTS, reducing duplication.

---

`891-896`: **Adopt `setup-py-reqs` in INTEGRATION job**  
Switching the integration job to use `setup-py-reqs` aligns dependency management with other jobs and simplifies updates.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T01:45:03Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>Makefile (1)</summary><blockquote>

`240-241`: **Remove unnecessary trailing semicolon**  
The semicolon after the `$(QUIET)$(WAIT)` command is superfluous and should be removed for clarity:  
```diff
- $(QUIET)$(WAIT) ;
+ $(QUIET)$(WAIT)
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: ASSERTIVE**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between dcd09c453b83cafa3cb33163be3d8015b706928f and d6de790bca4cceacf84cd117999edd53b41cfa7f.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `Makefile` (4 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>📓 Common learnings</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>Makefile (1)</summary>

`174-176`: **Exclude additional Git metadata files**  
Adding `.git_skipList`, `.gitattributes`, and `.gitmodules` to `MANIFEST.in` prevents these repository artefacts from being packaged in releases.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T01:50:34Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T02:07:27Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T02:08:00Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T02:19:53Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T02:20:12Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T02:25:00Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T02:25:20Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T02:25:48Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T02:26:11Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T02:33:04Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T02:33:34Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T02:34:23Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T02:36:15Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T02:39:54Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T02:40:28Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:05Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:07Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:09Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:11Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:13Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:15Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:17Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:19Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:21Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:23Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:25Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:27Z
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-17T02:56:29Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T03:43:56Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T03:45:51Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T04:03:56Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T04:04:34Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 4**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>.github/workflows/CI-DOCS.yml (1)</summary><blockquote>

`263-263`: _🧹 Nitpick (assertive)_

**Typo in step name: "Compleate" should be "Complete".**

There's a spelling error in the step name "Compleate DOCs GitHub Check". While you've added this typo to the spell-checker regression tests, it should also be fixed here.

```diff
-      - name: "Compleate DOCs GitHub Check"
+      - name: "Complete DOCs GitHub Check"
```

</blockquote></details>
<details>
<summary>.github/workflows/Tests.yml (1)</summary><blockquote>

`3-4`: **Retain `description` key intentionally**  
Per your preference, keeping the top-level `description` field is acceptable: GitHub ignores unsupported keys in workflows. Likewise, the `run-name` is expressive for clarity.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.7)</summary>

3-3: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: ASSERTIVE**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between d6de790bca4cceacf84cd117999edd53b41cfa7f and 3515736a729697ae1c552b2d69f3e72b916b16c8.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `.github/actions/run-minimal-acceptance-tests/action.yml` (1 hunks)
* `.github/actions/setup-py-reqs/action.yml` (1 hunks)
* `.github/workflows/CI-DOCS.yml` (4 hunks)
* `.github/workflows/Tests.yml` (18 hunks)
* `tests/check_spelling` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`tests/*`: When reviewing **test** code: 1. Prioritize portability over clarity, especially when dealing with cross-Python
   compatibility. However, with the priority in mind, do ...</summary>

> `tests/*`: When reviewing **test** code: 1. Prioritize portability over clarity, especially when dealing with cross-Python
>    compatibility. However, with the priority in mind, do still consider improvements
>    to clarity when relevant.
> 2. As a general guideline, consider the code style advocated in the PEP 8 standard
>    (excluding the use of spaces for indentation) and evaluate suggested changes
>    for code style compliance.
> 3. As a style convention, consider the code style advocated in
>    [CEP-8](https://gist.github.com/reactive-firewall/b7ee98df9e636a51806e62ef9c4ab161)
>    and evaluate suggested changes for code style compliance, pointing out any
>    violations discovered.
> 4. As a style convention, consider the code style advocated in
>    [CEP-9](https://gist.github.com/reactive-firewall/d840ee9990e65f302ce2a8d78ebe73f6)
>    and evaluate suggested changes for nomenclature compliance, pointing out any
>    violations discovered, along with suggestions generated to correct the nomenclature.
> 5. As a general guideline, try to provide any relevant, official, and supporting
>    documentation links to any tool's suggestions in review comments. This guideline is
>    important for posterity.
> 6. As a project rule, Python source files with names prefixed by the string
>    "test_" and located in the project's "tests" directory are the project's unit-testing
>    code. It is safe, albeit a heuristic, to assume these are considered part of the
>    project's minimal acceptance testing unless a justifying exception to this assumption
>    is documented.
> 7. As a project rule, any files without extensions and with names prefixed by either the
>    string "check_" or the string "test_", and located in the project's "tests" directory,
>    are the project's non-unit test code. "Non-unit test" in this context refers to any
>    type of testing other than unit testing, such as (but not limited to)
>    functional testing, style linting, regression testing, etc. It can also be assumed
>    that non-unit testing code is usually (but not always) written as Bash shell scripts.

- `tests/check_spelling`

</details>
<details>
<summary>`.github/**`: * When the project is hosted on GitHub: All GitHub-specific configurations, templates,
  and tools should be found in the '.github' directory tree.
* 'actionlint' err...</summary>

> `.github/**`: * When the project is hosted on GitHub: All GitHub-specific configurations, templates,
>   and tools should be found in the '.github' directory tree.
> * 'actionlint' erroneously generates false positives when dealing with
>   GitHub's `${{ ... }}` syntax in conditionals.
> * 'actionlint' erroneously generates incorrect solutions when suggesting the removal of
>   valid `${{ ... }}` syntax.

- `.github/actions/run-minimal-acceptance-tests/action.yml`
- `.github/workflows/CI-DOCS.yml`
- `.github/actions/setup-py-reqs/action.yml`
- `.github/workflows/Tests.yml`

</details>

</details><details>
<summary>🧠 Learnings (2)</summary>

<details>
<summary>📓 Common learnings</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>
<details>
<summary>.github/workflows/Tests.yml (1)</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/workflows/Tests.yml:3-4
Timestamp: 2025-05-17T02:36:14.525Z
Learning: Reactive-firewall prefers to keep the `description` key in GitHub workflow files despite it not being officially supported, as it's considered harmless since GitHub simply ignores it rather than causing failures.
```

</details>

</details><details>
<summary>🪛 actionlint (1.7.7)</summary>

<details>
<summary>.github/workflows/Tests.yml</summary>

3-3: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

---

800-800: property "python-version" is not defined in object type {}

(expression)

---

863-863: property "integration_test_outcome" is not defined in object type {conclusion: string; outcome: string; outputs: {string => string}}

(expression)

---

1496-1496: property "python-version" is not defined in object type {}

(expression)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

<details>
<summary>.github/workflows/Tests.yml</summary>

[error] 876-876: wrong indentation: expected 6 but found 4

(indentation)

---

[warning] 877-877: too few spaces before comment: expected 2

(comments)

---

[warning] 927-927: too few spaces before comment: expected 2

(comments)

---

[warning] 940-940: too few spaces before comment: expected 2

(comments)

---

[warning] 1197-1197: too few spaces before comment: expected 2

(comments)

---

[warning] 1223-1223: too few spaces before comment: expected 2

(comments)

---

[warning] 1262-1262: too few spaces before comment: expected 2

(comments)

---

[warning] 1271-1271: too few spaces before comment: expected 2

(comments)

---

[warning] 1303-1303: too few spaces before comment: expected 2

(comments)

---

[warning] 1310-1310: too few spaces before comment: expected 2

(comments)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: CI-TESTs

</details>

<details>
<summary>🔇 Additional comments (32)</summary><blockquote>

<details>
<summary>tests/check_spelling (1)</summary>

`157-157`: **Good addition of the typo pair for regression testing.**

Adding "compleate:complete" to the regression testing framework is a good practice for preventing this typo from reappearing in the future. This aligns with the fix for the typo found in the CI-DOCS.yml workflow.

</details>
<details>
<summary>.github/actions/run-minimal-acceptance-tests/action.yml (1)</summary>

`94-99`: **Fixed Python version selection logic.**

The conditional logic has been properly corrected to first check if `PYTHON_VERSION_INPUT` is non-empty before using it. This ensures the Python version input is correctly processed and falls back to the existing environment variable only when no input is provided.

</details>
<details>
<summary>.github/workflows/CI-DOCS.yml (2)</summary>

`220-227`: **Corrected output reference in conditional check.**

The conditional now correctly references `needs.DOCS.outputs.docs_outcome` instead of a coverage job output, fixing the condition to properly check the documentation job's outcome.

---

`15-20`: **Improved workflow trigger and structure.**

The workflow has been restructured to trigger exclusively upon completion of the "CI-MATs" workflow, creating a better dependency chain between workflows. The addition of the `check_mats` job to fetch and process artifacts from the triggering workflow provides a clean foundation for subsequent jobs.

</details>
<details>
<summary>.github/actions/setup-py-reqs/action.yml (2)</summary>

`1-62`: **Well-structured GitHub Action for dependency management.**

This new composite GitHub Action effectively standardizes Python dependency installation across the CI workflows. The action has clear inputs and outputs, proper error handling, and comprehensive reporting capabilities.

---

`127-166`: **Well-commented dependency evaluation logic.**

The dependency evaluation section includes detailed comments that clearly explain the decision-making process at each step. This is excellent practice for maintaining complex conditional logic and helps future contributors understand the flow.

</details>
<details>
<summary>.github/workflows/Tests.yml (26)</summary>

`112-112`: **Consistent step ID for test check control**  
Using `output_tests_check_id` aligns with other jobs and makes check updates idempotent. Good use of your custom `check-control` action.

---

`171-185`: **Standardize Python dependency setup with custom action**  
Switching manual `pip install` to your `.github/actions/setup-py-reqs` composite action here is consistent and reduces duplication. Verified that `with:` parameters (`sha` and `python-version`) match upstream usage.

---

`336-336`: **Enhance coverage summary details**  
Adding a collapsible `<details>` block improves readability of detailed metrics without cluttering summaries.

---

`392-392`: **Capture summary artifacts dynamically**  
Using `git ls-files -o --exclude-standard` with `COV_MATCH_PATTERN` correctly discovers all coverage summary files.

---

`727-728`: **Upload aggregated coverage summary**  
Introducing `upload-coverage-summary` step with controlled artifact naming and retention improves traceability for coverage comment body.

---

`809-815`: **Standardize style job dependency installation**  
Utilizing `.github/actions/setup-py-reqs` here aligns the `STYLE` job with other jobs, removing ad hoc `pip install` commands. Parameters look correct.

---

`882-882`: **Reuse existing checkout-and-rebuild action**  
Your pattern of reusing `./.github/actions/checkout-and-rebuild` for integration tests checkout is consistent with other jobs.

---

`891-897`: **Consolidate integration dependencies with composite action**  
Switching to your `setup-py-reqs` action here streamlines environment setup. The `sha` and `python-version` inputs are correctly propagated.

---

`911-911`: **Explicit ID for Pytest step**  
Assigning `id: integration-pytest` allows for clear outcome capture and aligns with naming elsewhere.

---

`917-917`: **Explicit ID for doctest coverage**  
The `integration-doctests` ID is descriptive and matches the rest of the pattern.

---

`920-920`: **Descriptive ID for functional tests**  
Using `integration-main` clearly differentiates the functional test step.

---

`926-926`: **Consistent Codecov integration**  
Your usage of `codecov/codecov-action` for integration coverage follows the established pattern.

---

`939-945`: **Ensure artifacts are always overwritten**  
Setting `overwrite: true` for `integration-reports-upload` guarantees that re-runs don’t leave stale artifacts. The naming is consistent with other artifact uploads.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

[warning] 940-940: too few spaces before comment: expected 2

(comments)

</details>

</details>

---

`947-947`: **Collect Code Climate reports conditionally**  
Maintaining the guard for non-Windows runners and using the same reporter command ensures parity across jobs.

---

`960-960`: **Consistent Deepsource upload**  
Your `integration-deepsource-upload` step matches patterns in other jobs and gracefully ignores errors.

---

`969-969`: **Track test results separately**  
Separating `codecov/test-results-action` for test results artifacts improves visibility of functional test outcomes.

---

`980-980`: **Cleanup after integration tests**  
`purge-integration-test-tools` reuses your purge action to revert test environment changes.

---

`990-1001`: **Generate integration summary artifact name**  
Using `uuidgen` fallback logic maintains consistency with other jobs. Setting `TESTS_STEP_SUMMARY` ensures downstream steps know where to find the summary.

---

`1002-1003`: **ID for integration tests evaluation**  
Defining an `integration_tests` step for aggregating multiple test outcomes is clear and necessary for downstream reporting.

---

`1064-1067`: **Finalize integration outcome aggregation**  
The `integration_outcome` step consolidates test and upload outcomes correctly. Step ID and logic appear correct.

---

`1179-1179`: **Enumerate integration summary artifacts**  
Pattern `Integration-Summary-Artifact-*.txt` is correct per the `TESTS_STEP_SUMMARY` naming convention.

---

`1259-1264`: **Persist integration summary artifact**  
Uploading `Integration-Summary-Artifact.txt` with retention and overwrite policies ensures the summary is available for the final reporting job.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

[warning] 1262-1262: too few spaces before comment: expected 2

(comments)

</details>

</details>

---

`1276-1284`: **Complete extended testing check**  
Using your `check-control` action with consolidated summary and conclusion ties the workflow together neatly.

---

`1308-1314`: **Post Integration commit comment**  
The separation into `INTEGRATION_SUMMARY` and `INTEGRATION_REPORT` jobs adds clarity. Fetching the artifact and posting it as a commit comment aligns with the CI/CD objectives.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

[warning] 1310-1310: too few spaces before comment: expected 2

(comments)

</details>

</details>

---

`1358-1358`: **Reuse checkout-and-rebuild for legacy setup tests**  
Maintaining the same action for initialization keeps `EXTRAS-FOR-SETUP` consistent with other jobs.

---

`1434-1434`: **Standardize pip dependency checks**  
Using `checkout-and-rebuild` before pip dependency testing aligns this job with the overall pattern.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T04:31:07Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 7**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>.github/workflows/CI-DOCS.yml (1)</summary><blockquote>

`262-270`: **Typo in GitHub Check step name persists.**  
The step name `"Compleate DOCs GitHub Check"` still contains `"Compleate"`. It should be corrected to `"Complete DOCs GitHub Check"`.

</blockquote></details>
<details>
<summary>.github/workflows/Tests.yml (1)</summary><blockquote>

`3-4`: **Retain top-level `description` despite spec warning**  
The `description` key is intentionally kept as it’s harmless (GitHub ignores unsupported keys) per project preference. The `run-name` field is correctly used to customize the workflow display name.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.7)</summary>

3-3: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: ASSERTIVE**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 3515736a729697ae1c552b2d69f3e72b916b16c8 and 57f55927600bf1605cd665b70d1a7f405edcfe5a.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `.github/actions/run-minimal-acceptance-tests/action.yml` (1 hunks)
* `.github/actions/setup-py-reqs/action.yml` (1 hunks)
* `.github/workflows/CI-DOCS.yml` (4 hunks)
* `.github/workflows/Tests.yml` (18 hunks)
* `tests/check_spelling` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`tests/*`: When reviewing **test** code: 1. Prioritize portability over clarity, especially when dealing with cross-Python
   compatibility. However, with the priority in mind, do ...</summary>

> `tests/*`: When reviewing **test** code: 1. Prioritize portability over clarity, especially when dealing with cross-Python
>    compatibility. However, with the priority in mind, do still consider improvements
>    to clarity when relevant.
> 2. As a general guideline, consider the code style advocated in the PEP 8 standard
>    (excluding the use of spaces for indentation) and evaluate suggested changes
>    for code style compliance.
> 3. As a style convention, consider the code style advocated in
>    [CEP-8](https://gist.github.com/reactive-firewall/b7ee98df9e636a51806e62ef9c4ab161)
>    and evaluate suggested changes for code style compliance, pointing out any
>    violations discovered.
> 4. As a style convention, consider the code style advocated in
>    [CEP-9](https://gist.github.com/reactive-firewall/d840ee9990e65f302ce2a8d78ebe73f6)
>    and evaluate suggested changes for nomenclature compliance, pointing out any
>    violations discovered, along with suggestions generated to correct the nomenclature.
> 5. As a general guideline, try to provide any relevant, official, and supporting
>    documentation links to any tool's suggestions in review comments. This guideline is
>    important for posterity.
> 6. As a project rule, Python source files with names prefixed by the string
>    "test_" and located in the project's "tests" directory are the project's unit-testing
>    code. It is safe, albeit a heuristic, to assume these are considered part of the
>    project's minimal acceptance testing unless a justifying exception to this assumption
>    is documented.
> 7. As a project rule, any files without extensions and with names prefixed by either the
>    string "check_" or the string "test_", and located in the project's "tests" directory,
>    are the project's non-unit test code. "Non-unit test" in this context refers to any
>    type of testing other than unit testing, such as (but not limited to)
>    functional testing, style linting, regression testing, etc. It can also be assumed
>    that non-unit testing code is usually (but not always) written as Bash shell scripts.

- `tests/check_spelling`

</details>
<details>
<summary>`.github/**`: * When the project is hosted on GitHub: All GitHub-specific configurations, templates,
  and tools should be found in the '.github' directory tree.
* 'actionlint' err...</summary>

> `.github/**`: * When the project is hosted on GitHub: All GitHub-specific configurations, templates,
>   and tools should be found in the '.github' directory tree.
> * 'actionlint' erroneously generates false positives when dealing with
>   GitHub's `${{ ... }}` syntax in conditionals.
> * 'actionlint' erroneously generates incorrect solutions when suggesting the removal of
>   valid `${{ ... }}` syntax.

- `.github/actions/run-minimal-acceptance-tests/action.yml`
- `.github/workflows/CI-DOCS.yml`
- `.github/actions/setup-py-reqs/action.yml`
- `.github/workflows/Tests.yml`

</details>

</details><details>
<summary>🧠 Learnings (2)</summary>

<details>
<summary>📓 Common learnings</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>
<details>
<summary>.github/workflows/Tests.yml (1)</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/workflows/Tests.yml:3-4
Timestamp: 2025-05-17T02:36:14.525Z
Learning: Reactive-firewall prefers to keep the `description` key in GitHub workflow files despite it not being officially supported, as it's considered harmless since GitHub simply ignores it rather than causing failures.
```

</details>

</details><details>
<summary>🪛 actionlint (1.7.7)</summary>

<details>
<summary>.github/workflows/Tests.yml</summary>

3-3: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

---

1496-1496: property "python-version" is not defined in object type {}

(expression)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

<details>
<summary>.github/workflows/Tests.yml</summary>

[error] 876-876: wrong indentation: expected 6 but found 4

(indentation)

---

[warning] 877-877: too few spaces before comment: expected 2

(comments)

---

[warning] 927-927: too few spaces before comment: expected 2

(comments)

---

[warning] 940-940: too few spaces before comment: expected 2

(comments)

---

[warning] 1197-1197: too few spaces before comment: expected 2

(comments)

---

[warning] 1223-1223: too few spaces before comment: expected 2

(comments)

---

[warning] 1262-1262: too few spaces before comment: expected 2

(comments)

---

[warning] 1271-1271: too few spaces before comment: expected 2

(comments)

---

[warning] 1303-1303: too few spaces before comment: expected 2

(comments)

---

[warning] 1310-1310: too few spaces before comment: expected 2

(comments)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (27)</summary><blockquote>

<details>
<summary>tests/check_spelling (1)</summary>

`156-158`: **Approve addition of new typo correction "compleate:complete".**  
The new specific typo pair covers another common misspelling and fits consistently with the existing regression tests.

</details>
<details>
<summary>.github/actions/run-minimal-acceptance-tests/action.yml (1)</summary>

`94-100`: **Python version input logic is correct.**  
The step now properly prefers a non-empty `PYTHON_VERSION_INPUT` and falls back to the existing `PYTHON_VERSION`, then exports it to both outputs and environment.

</details>
<details>
<summary>.github/workflows/CI-DOCS.yml (5)</summary>

`12-13`: **Default permissions scoped to none.**  
Explicitly denying all permissions at the workflow level enhances security by ensuring only explicitly granted permissions are used.

---

`15-19`: **Trigger on CI-MATs completion only.**  
Switching to `workflow_run` for the `"CI-MATs"` workflow ensures this docs workflow runs only after builds and tests finish, reducing redundant executions.

---

`28-29`: **Lock `check_mats` to Documentation environment.**  
Assigning a dedicated `"Documentation"` environment provides better isolation and resource controls for this initial job.

---

`122-124`: **DOCS job conditional execution and environment.**  
The `DOCS` job correctly respects `needs.check_mats.outputs.should_run` and is scoped to `"Documentation"`, preventing unwanted runs and maintaining environment isolation.

---

`220-227`: **Reporting uses actual `docs_outcome`.**  
The `report_status` step now correctly checks `${{ needs.DOCS.outputs.docs_outcome }}` for success versus failure, replacing any outdated references to coverage outcomes.

</details>
<details>
<summary>.github/actions/setup-py-reqs/action.yml (1)</summary>

`79-85`: **Setup Python logic is clear and correct.**  
The condition properly prioritizes the provided `python-version` input before falling back to the existing environment variable, and both the output and `GITHUB_ENV` export are handled correctly.

</details>
<details>
<summary>.github/workflows/Tests.yml (19)</summary>

`171-171`: **Consistent checkout naming in COVERAGE job**  
Renaming the step to `Checkout repository for Tests with ${{ matrix.python-version }}` aligns with other jobs and clearly communicates intent.

---

`179-185`: **Centralize dependency installation with `setup-py-reqs`**  
Switching to the new custom action at `./.github/actions/setup-py-reqs` removes ad-hoc `pip install` invocations, promotes reuse, and keeps dependency logic in one place.

---

`336-336`: **Add collapsible section header for coverage details**  
The `<details><summary>` wrapper improves readability by hiding verbose details until expanded.

---

`392-392`: **Aggregate coverage summary artifacts**  
Using `git ls-files` to locate and copy summary files is a robust way to feed them into subsequent steps and outputs.

---

`465-465`: **Standardize checkout in DOCTESTS job**  
Mirroring the coverage job’s checkout ensures the same workspace state and reduces divergence between jobs.

---

`474-480`: **Use `setup-py-reqs` for DOCTESTS dependencies**  
Leveraging the shared action for installing Python requirements keeps the setup uniform and DRY across jobs.

---

`605-605`: **Collapse DOCTESTS details with `<details>`**  
Adding a collapsible section for doctest details maintains consistency with coverage summaries and declutters the summary output.

---

`652-652`: **Collect doctest summary artifacts**  
The pattern using `git ls-files` is consistent with coverage and reliably gathers generated summary files.

---

`727-727`: **Upload combined coverage summary**  
Uploading the merged coverage summary artifact ensures it’s available for the `COVERAGE_REPORT` job and any external reporting.

---

`800-800`: **Align STYLE job checkout with others**  
Using `checkout-and-rebuild` here keeps the job orchestration consistent and reuses the build context setup.

---

`808-814`: **Adopt `setup-py-reqs` in STYLE job**  
Centralizing all dependency installs through the same action simplifies maintenance and reduces version drift.

---

`861-874`: **Expose detailed INTEGRATION outputs**  
Capturing each step’s outcome and artifact details provides the granularity needed for downstream summary and reporting jobs.

---

`882-882`: **Reuse `checkout-and-rebuild` for INTEGRATION**  
This maintains the single point of configuration for repo checkout semantics and build context across all test jobs.

---

`891-897`: **Install integration dependencies via `setup-py-reqs`**  
Ensures the integration environment matches coverage and doctest setups, reducing duplication of pip commands.

---

`989-999`: **Generate a unique integration summary artifact name**  
Using `uuidgen` (with a fallback for Windows) and a consistent naming pattern helps avoid collisions and clearly tags summary artifacts.

---

`1179-1179`: **Enumerate integration summary files**  
The `git ls-files` approach reliably discovers artifacts, ensuring the summary step has the correct inputs.

---

`1213-1221`: **Conditionally trigger INTEGRATION_SUMMARY**  
The `if` expression correctly gates the summary job on a non-cancelled integration run and a valid trigger.

---

`1222-1227`: **Download all integration artifacts**  
Using `actions/download-artifact` with patterns and merge enables consolidation of parts for summary compilation.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

[warning] 1223-1223: too few spaces before comment: expected 2

(comments)

</details>

</details>

---

`1259-1264`: **Archive integration summary artifact**  
Uploading the final `Integration-Summary-Artifact.txt` ensures the report is available for the `INTEGRATION_REPORT` job.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

[warning] 1262-1262: too few spaces before comment: expected 2

(comments)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T04:53:44Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T05:00:15Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T05:01:09Z
user: login: reactive-firewall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-17T05:02:12Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T05:02:44Z
user: login: coderabbitai[bot]
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-17T05:05:16Z

Review comments:
diff_hunk: @@ -233,6 +240,9 @@
 	$(QUIET)$(WAIT)
 	$(QUIET)$(ECHO) "$@: Done."
 
+./dist: build
+	$(QUIET)$(WAIT) ;
+
path: Makefile
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Remove unnecessary semicolon**  
The trailing semicolon in the `./dist` recipe is superfluous and can be removed for clarity:

```diff
-	$(QUIET)$(WAIT) ;
+	$(QUIET)$(WAIT)
```  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
./dist: build
	$(QUIET)$(WAIT)
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In the Makefile at lines 243 to 245, remove the trailing semicolon from the
./dist recipe line to eliminate the unnecessary character and improve clarity.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-17T01:45:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -82,3 +194,108 @@ jobs:
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=false" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "  * :x: Generating Documentation Failed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "docs_summary=Generating Documentation Unsuccessful" >> "$GITHUB_OUTPUT"
+          fi
+          cat <"${DOCUMENTATION_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY"
+          { printf "%s\n" 'docs_text<<EOF'; cat <"${DOCUMENTATION_COMMENT_BODY}"; printf "%s\n" 'EOF'; } >> "$GITHUB_OUTPUT"
+      - name: "Upload DOCs summary"
+        id: upload-docs-summary
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: ./DOCUMENTATION-Summary-Artifact.txt
+          name: DOCUMENTATION-COMMENT-BODY-${{ needs.check_mats.outputs.build_sha }}
+          if-no-files-found: error
+          compression-level: 3
+          retention-days: 2
+          overwrite: true
+      - name: "Upload DOCs Bundle"
+        id: upload-docs-bundle
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: Multicast-Documentation
+          name: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-ALL
+          if-no-files-found: error
+          compression-level: 9
+          overwrite: true
+      - name: checkout repository actions for check
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
+          ref: ${{ needs.check_mats.outputs.build_sha }}
+          sparse-checkout: '.github/actions/check-control'
+      - name: "Compleate DOCs GitHub Check"
path: .github/workflows/CI-DOCS.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Typo in GitHub Check step name**  
`"Compleate DOCs GitHub Check"` contains a typo. Consider changing it to `"Complete DOCs GitHub Check"` for professionalism.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/CI-DOCS.yml around lines 259 to 262, the step name
"Compleate DOCs GitHub Check" contains a typo. Change "Compleate" to "Complete"
to correct the spelling and improve professionalism.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T01:45:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -82,3 +194,108 @@
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
path: .github/workflows/CI-DOCS.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix condition to check documentation job outcome**  
The `report_status` step is mistakenly checking `${{ needs.COVERAGE.outputs.coverage_outcome }}` instead of the documentation job’s output. It should reference `${{ needs.DOCS.outputs.docs_outcome }}`.  
  
```diff
- if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+ if [[ "${{ needs.DOCS.outputs.docs_outcome }}" == "success" ]]; then
```  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
          if [[ "${{ needs.DOCS.outputs.docs_outcome }}" == "success" ]]; then
            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
          else
            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/CI-DOCS.yml around lines 220 to 227, the condition
incorrectly checks the coverage job outcome variable
needs.COVERAGE.outputs.coverage_outcome instead of the documentation job's
output. Update the condition to check needs.DOCS.outputs.docs_outcome to
correctly reflect the documentation job's result.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->

✅ Addressed in commit 3515736

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-17T01:45:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
path: .github/actions/setup-py-reqs/action.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Align `author` metadata with repository conventions**  
The action’s `author: 'Mr. Walls'` could be updated to the GitHub handle or organization (`reactive-firewall` or similar) to maintain clear attribution across the project.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/actions/setup-py-reqs/action.yml between lines 3 and 7, update the
author metadata from 'Mr. Walls' to the appropriate GitHub handle or
organization name such as 'reactive-firewall' to align with repository
conventions and ensure consistent attribution.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T01:45:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
path: .github/actions/setup-py-reqs/action.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Invert logic for Python version assignment**  
The current block checks for _empty_ input and then uses it, which is backwards. You want to prefer a non-empty input. For example:

```diff
- if [[ -z $PYTHON_VERSION_INPUT ]]; then
-   printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
-   PYTHON_VERSION=${PYTHON_VERSION_INPUT}
- else
-   printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
- fi
+ if [[ -n $PYTHON_VERSION_INPUT ]]; then
+   PYTHON_VERSION=$PYTHON_VERSION_INPUT
+ else
+   PYTHON_VERSION=$(python --version | awk '{print $2}')
+ fi
+ printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
```  
This ensures the provided `inputs.python-version` is actually used.  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
        if [[ -n $PYTHON_VERSION_INPUT ]]; then
          PYTHON_VERSION=$PYTHON_VERSION_INPUT
        else
          PYTHON_VERSION=$(python --version | awk '{print $2}')
        fi
        printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/actions/setup-py-reqs/action.yml around lines 79 to 85, the logic
incorrectly checks if PYTHON_VERSION_INPUT is empty and then uses it, which is
backwards. Fix this by inverting the condition to check if PYTHON_VERSION_INPUT
is non-empty first; if so, assign PYTHON_VERSION to PYTHON_VERSION_INPUT and
output it, otherwise use the existing PYTHON_VERSION variable. This ensures the
provided input is properly prioritized and used.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T01:45:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,7 @@
 ---
 name: CI-TESTS
+description: "Continuous Integration for post-MATs additional testing, and validation."
+run-name: Extended Testing
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Remove unsupported `description` key**  
Workflow files don’t recognize a top-level `description` (it’s for reusable workflows). You may remove it or migrate to documentation.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.7)</summary>

3-3: unexpected key "description" for "workflow" section. expected one of "concurrency", "defaults", "env", "jobs", "name", "on", "permissions", "run-name"

(syntax-check)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml at lines 3 to 4, remove the top-level
'description' key because it is not supported in workflow files and only applies
to reusable workflows. Simply delete the 'description' line to fix the issue.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T01:45:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -203,7 +207,7 @@
 	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) -r requirements.txt 2>$(ERROR_LOG_PATH) || :
 	$(QUIET)$(ECHO) "$@: Done."
 
-install: init build
+install: init ./dist
path: Makefile
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Declare new targets as phony**  
The new targets `install`, `user-install`, and `./dist` should be added to the `.PHONY` list so that Make doesn’t skip their recipes when a corresponding file or directory already exists. Please update the declaration near the top (around the existing `.PHONY:` line) to include these names:  
```diff
 .PHONY: all clean test cleanup branding init help clean-docs must_be_root must_have_flake must_have_pytest uninstall cleanup-dev-backups \
-         build ...
+         build install user-install ./dist
```  



Also applies to: 471-471

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In the Makefile at lines 210 and 471, the new targets `install`, `user-install`,
and `./dist` are not declared as phony. Locate the existing `.PHONY:`
declaration near the top of the Makefile and add these target names to the list
to ensure Make always runs their recipes regardless of existing files or
directories.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T01:50:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -171,10 +171,14 @@
 	$(QUIET)$(ECHO) "include HISTORY.md" >>"$@" ;
 	$(QUIET)$(ECHO) "recursive-include . *.txt" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .gitignore" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .git_skipList" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .gitattributes" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .gitmodules" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .deepsource.toml" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.ini" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.yml" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.yaml" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .*.conf" >>"$@" ;
path: Makefile
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Correct the `.conf` exclusion pattern**  
The pattern `exclude .*.conf` only matches hidden files (e.g., `.app.conf`) rather than all `.conf` files. To exclude all configuration files, update it to:  
```diff
- $(QUIET)$(ECHO) "exclude .*.conf" >>"$@" ;
+ $(QUIET)$(ECHO) "exclude *.conf" >>"$@" ;
```

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In the Makefile at line 181, the exclusion pattern "exclude .*.conf" only
matches hidden .conf files. Change the pattern to "exclude *.conf" to correctly
exclude all files ending with .conf, not just hidden ones.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T01:50:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -171,10 +171,14 @@
 	$(QUIET)$(ECHO) "include HISTORY.md" >>"$@" ;
 	$(QUIET)$(ECHO) "recursive-include . *.txt" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .gitignore" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .git_skipList" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .gitattributes" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .gitmodules" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .deepsource.toml" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.ini" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.yml" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.yaml" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .*.conf" >>"$@" ;
path: Makefile
user: login: reactive-firewall
body: This pattern of `.*.conf` is intentional.

<details><summary>TL;DR</summary>

🙅🏻 While I appreciate the idea, your suggestion seems to introduce abstractions that may violate the [Avoid Hasty Abstraction](https://web.archive.org/web/20250413022457/https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction) principle.

Namely: you are incorrectly assuming here that the goal is to exclude all `.conf` files , which is a falsehood, instead of considering this rule is only to exclude files like `.yamllint.conf`

while I could have gone with:
```suggestion
	$(QUIET)$(ECHO) "exclude .yamllint.conf" >>"$@" ;
```
and improved readability, it would have increased maintainability as we'd have to update it in the future if we added another dot-file config (eg. `.somefile.conf`). Further your suggestion would prevent the use of the perfectly reasonable '.conf' suffix from potentially being used, (which is at the very-least still unclear at this point :shrug:)

</details>
created_at: 2025-05-17T02:07:27Z
author_association: COLLABORATOR
diff_hunk: @@ -171,10 +171,14 @@
 	$(QUIET)$(ECHO) "include HISTORY.md" >>"$@" ;
 	$(QUIET)$(ECHO) "recursive-include . *.txt" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .gitignore" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .git_skipList" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .gitattributes" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .gitmodules" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .deepsource.toml" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.ini" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.yml" >>"$@" ;
 	$(QUIET)$(ECHO) "exclude .*.yaml" >>"$@" ;
+	$(QUIET)$(ECHO) "exclude .*.conf" >>"$@" ;
path: Makefile
user: login: coderabbitai[bot]
body: @reactive-firewall Thank you for the clarification! I see now that the `.*.conf` pattern is intentionally targeting only hidden configuration files (like `.yamllint.conf`) while preserving the ability to use regular `.conf` files. Your approach strikes a good balance between maintainability and specificity.

I apologize for my misunderstanding and appreciate the detailed explanation of your reasoning.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: Makefile:181-181
Timestamp: 2025-05-17T02:07:58.886Z
Learning: In MANIFEST.in files, reactive-firewall prefers using patterns like `.*.conf` to specifically exclude hidden configuration files while allowing regular files with the same extension to be included, following the principle of avoiding hasty abstractions and maintaining future flexibility.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall Thank you for the clarification! I see now that the `.*.conf` pattern is intentionally targeting only hidden configuration files (like `.yamllint.conf`) while preserving the ability to use regular `.conf` files. Your approach strikes a good balance between maintainability and specificity.

I apologize for my misunderstanding and appreciate the detailed explanation of your reasoning.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: Makefile:181-181
Timestamp: 2025-05-17T02:07:58.886Z
Learning: In MANIFEST.in files, reactive-firewall prefers using patterns like `.*.conf` to specifically exclude hidden configuration files while allowing regular files with the same extension to be included, following the principle of avoiding hasty abstractions and maintaining future flexibility.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T02:08:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -82,3 +194,108 @@ jobs:
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=false" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "  * :x: Generating Documentation Failed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "docs_summary=Generating Documentation Unsuccessful" >> "$GITHUB_OUTPUT"
+          fi
+          cat <"${DOCUMENTATION_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY"
+          { printf "%s\n" 'docs_text<<EOF'; cat <"${DOCUMENTATION_COMMENT_BODY}"; printf "%s\n" 'EOF'; } >> "$GITHUB_OUTPUT"
+      - name: "Upload DOCs summary"
+        id: upload-docs-summary
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: ./DOCUMENTATION-Summary-Artifact.txt
+          name: DOCUMENTATION-COMMENT-BODY-${{ needs.check_mats.outputs.build_sha }}
+          if-no-files-found: error
+          compression-level: 3
+          retention-days: 2
+          overwrite: true
+      - name: "Upload DOCs Bundle"
+        id: upload-docs-bundle
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: Multicast-Documentation
+          name: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-ALL
+          if-no-files-found: error
+          compression-level: 9
+          overwrite: true
+      - name: checkout repository actions for check
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
+          ref: ${{ needs.check_mats.outputs.build_sha }}
+          sparse-checkout: '.github/actions/check-control'
+      - name: "Compleate DOCs GitHub Check"
path: .github/workflows/CI-DOCS.yml
user: login: reactive-firewall
body: Oops, good catch, I'll include this change in my next batch of changes, :thinking: I'll add this to the tests/check_spelling while I'm at it.
created_at: 2025-05-17T02:19:53Z
author_association: COLLABORATOR
diff_hunk: @@ -82,3 +194,108 @@ jobs:
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=false" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "  * :x: Generating Documentation Failed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "docs_summary=Generating Documentation Unsuccessful" >> "$GITHUB_OUTPUT"
+          fi
+          cat <"${DOCUMENTATION_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY"
+          { printf "%s\n" 'docs_text<<EOF'; cat <"${DOCUMENTATION_COMMENT_BODY}"; printf "%s\n" 'EOF'; } >> "$GITHUB_OUTPUT"
+      - name: "Upload DOCs summary"
+        id: upload-docs-summary
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: ./DOCUMENTATION-Summary-Artifact.txt
+          name: DOCUMENTATION-COMMENT-BODY-${{ needs.check_mats.outputs.build_sha }}
+          if-no-files-found: error
+          compression-level: 3
+          retention-days: 2
+          overwrite: true
+      - name: "Upload DOCs Bundle"
+        id: upload-docs-bundle
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: Multicast-Documentation
+          name: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-ALL
+          if-no-files-found: error
+          compression-level: 9
+          overwrite: true
+      - name: checkout repository actions for check
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
+          ref: ${{ needs.check_mats.outputs.build_sha }}
+          sparse-checkout: '.github/actions/check-control'
+      - name: "Compleate DOCs GitHub Check"
path: .github/workflows/CI-DOCS.yml
user: login: coderabbitai[bot]
body: @reactive-firewall Great plan! Adding it to the spelling check will help catch similar issues in the future. Looking forward to seeing these improvements in your next batch of changes.

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall Great plan! Adding it to the spelling check will help catch similar issues in the future. Looking forward to seeing these improvements in your next batch of changes.

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T02:20:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -82,3 +194,108 @@
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
path: .github/workflows/CI-DOCS.yml
user: login: reactive-firewall
body: 🙈 I'll include this change in my next batch of changes
created_at: 2025-05-17T02:25:00Z
author_association: COLLABORATOR
diff_hunk: @@ -82,3 +194,108 @@
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
path: .github/workflows/CI-DOCS.yml
user: login: coderabbitai[bot]
body: @reactive-firewall Thanks for confirming! I'll look forward to seeing the fix in your next batch of changes. This will ensure the documentation workflow correctly checks the documentation job's outcome instead of the coverage job's outcome.



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>

---

<!-- This is an auto-generated comment: tweet message by coderabbit.ai -->

If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=Catch%20subtle%20CI%20bugs%20early!%20%40coderabbitai%20spotted%20a%20wrong%20job%20output%20check%E2%80%94fixing%20it%20ensures%20your%20docs%20status%20reflects%20the%20right%20job%20outcome.%20Boost%20your%20workflow%20accuracy!%20%F0%9F%93%88%F0%9F%90%87&url=https%3A%2F%2Fgithub.com%2Freactive-firewall%2Fmulticast%2Fpull%2F402%23discussion_r2093822450)?

Thank you for using CodeRabbit!

<!-- end of auto-generated comment: tweet message by coderabbit.ai -->


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall Thanks for confirming! I'll look forward to seeing the fix in your next batch of changes. This will ensure the documentation workflow correctly checks the documentation job's outcome instead of the coverage job's outcome.



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>

---

&lt;!-- This is an auto-generated comment: tweet message by coderabbit.ai --&gt;

If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=Catch%20subtle%20CI%20bugs%20early!%20%40coderabbitai%20spotted%20a%20wrong%20job%20output%20check%E2%80%94fixing%20it%20ensures%20your%20docs%20status%20reflects%20the%20right%20job%20outcome.%20Boost%20your%20workflow%20accuracy!%20%F0%9F%93%88%F0%9F%90%87&url=https%3A%2F%2Fgithub.com%2Freactive-firewall%2Fmulticast%2Fpull%2F402%23discussion_r2093822450)?

Thank you for using CodeRabbit!

&lt;!-- end of auto-generated comment: tweet message by coderabbit.ai --&gt;

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T02:25:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
path: .github/actions/setup-py-reqs/action.yml
user: login: reactive-firewall
body: 🙅🏻 The current implementation is fine.
created_at: 2025-05-17T02:25:48Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
path: .github/actions/setup-py-reqs/action.yml
user: login: coderabbitai[bot]
body: @reactive-firewall I understand and respect your preference. Thank you for the clarification.

⟋⌒⟋
(๑ฅ́˘ฅ̀๑)

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall I understand and respect your preference. Thank you for the clarification.

⟋⌒⟋
(๑ฅ́˘ฅ̀๑)

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T02:26:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
path: .github/actions/setup-py-reqs/action.yml
user: login: reactive-firewall
body: :thinking: you're only partially right, the logic is indeed backwards, but only in regards to checking the value for empty/non-empty

I'm thinking more like this:
```suggestion
        if [[ -n $PYTHON_VERSION_INPUT ]]; then
          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
        else
          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
        fi
        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
```

created_at: 2025-05-17T02:33:04Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
path: .github/actions/setup-py-reqs/action.yml
user: login: coderabbitai[bot]
body: @reactive-firewall You're absolutely right! Your solution is the correct approach for this situation. By inverting the condition to check for non-empty input first (`-n $PYTHON_VERSION_INPUT`), you fix the logic issue while maintaining the expected behavior of the script.

Your implementation properly:
1. Uses the provided input when available
2. Falls back to the existing `PYTHON_VERSION` variable otherwise
3. Preserves the original structure of the code

Thanks for sharing the improved solution!



ʕ •ᴥ•ʔ

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall You're absolutely right! Your solution is the correct approach for this situation. By inverting the condition to check for non-empty input first (`-n $PYTHON_VERSION_INPUT`), you fix the logic issue while maintaining the expected behavior of the script.

Your implementation properly:
1. Uses the provided input when available
2. Falls back to the existing `PYTHON_VERSION` variable otherwise
3. Preserves the original structure of the code

Thanks for sharing the improved solution!



ʕ •ᴥ•ʔ

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#148
File: tests/MulticastUDPClient.py:83-84
Timestamp: 2024-10-05T09:05:28.234Z
Learning: Reactive-firewall prefers to assign to `__module__` at the module level in their Python test modules.
```

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T02:33:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,5 +1,7 @@
 ---
 name: CI-TESTS
+description: "Continuous Integration for post-MATs additional testing, and validation."
+run-name: Extended Testing
path: .github/workflows/Tests.yml
user: login: reactive-firewall
body: 🙅🏻 The current implementation is fine. There's no harm either as they just ignore it.
created_at: 2025-05-17T02:34:23Z
author_association: COLLABORATOR
diff_hunk: @@ -1,5 +1,7 @@
 ---
 name: CI-TESTS
+description: "Continuous Integration for post-MATs additional testing, and validation."
+run-name: Extended Testing
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: @reactive-firewall I'll respect your decision to keep the `description` key. You're right that GitHub simply ignores unsupported keys in workflow files rather than causing failures, so there's no functional harm in keeping it.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/workflows/Tests.yml:3-4
Timestamp: 2025-05-17T02:36:14.525Z
Learning: Reactive-firewall prefers to keep the `description` key in GitHub workflow files despite it not being officially supported, as it's considered harmless since GitHub simply ignores it rather than causing failures.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall I'll respect your decision to keep the `description` key. You're right that GitHub simply ignores unsupported keys in workflow files rather than causing failures, so there's no functional harm in keeping it.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/workflows/Tests.yml:3-4
Timestamp: 2025-05-17T02:36:14.525Z
Learning: Reactive-firewall prefers to keep the `description` key in GitHub workflow files despite it not being officially supported, as it's considered harmless since GitHub simply ignores it rather than causing failures.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T02:36:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -203,7 +207,7 @@
 	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) -r requirements.txt 2>$(ERROR_LOG_PATH) || :
 	$(QUIET)$(ECHO) "$@: Done."
 
-install: init build
+install: init ./dist
path: Makefile
user: login: reactive-firewall
body: 🙅🏻 The current implementation is fine.

 * `./dist` is __Not__ phony though
 * `user-install` and `install` have edge-cases where they can be skipped
 * `build` is intentionally not listed as phony for CI/CD edge-cases where the build is downloaded instead of re-building every time.
created_at: 2025-05-17T02:39:54Z
author_association: COLLABORATOR
diff_hunk: @@ -203,7 +207,7 @@
 	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) -r requirements.txt 2>$(ERROR_LOG_PATH) || :
 	$(QUIET)$(ECHO) "$@: Done."
 
-install: init build
+install: init ./dist
path: Makefile
user: login: coderabbitai[bot]
body: @reactive-firewall Thank you for the clarification. I understand now - `./dist` is a physical directory target representing actual build artifacts, not a phony target. Your approach creates a more flexible dependency chain that allows for optimizations in CI/CD scenarios where builds might be downloaded rather than rebuilt from scratch.

I appreciate you explaining the intentional design behind these targets and their edge cases.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: Makefile:210-210
Timestamp: 2025-05-17T02:40:27.026Z
Learning: In reactive-firewall's Makefile design philosophy, `./dist` represents a real directory target (not phony), while `user-install` and `install` targets intentionally have edge cases where they can be skipped. The `build` target is intentionally not listed as phony to support CI/CD optimization where pre-built artifacts might be downloaded instead of rebuilt.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall Thank you for the clarification. I understand now - `./dist` is a physical directory target representing actual build artifacts, not a phony target. Your approach creates a more flexible dependency chain that allows for optimizations in CI/CD scenarios where builds might be downloaded rather than rebuilt from scratch.

I appreciate you explaining the intentional design behind these targets and their edge cases.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: Makefile:210-210
Timestamp: 2025-05-17T02:40:27.026Z
Learning: In reactive-firewall's Makefile design philosophy, `./dist` represents a real directory target (not phony), while `user-install` and `install` targets intentionally have edge cases where they can be skipped. The `build` target is intentionally not listed as phony to support CI/CD optimization where pre-built artifacts might be downloaded instead of rebuilt.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T02:40:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
path: .github/actions/setup-py-reqs/action.yml
body: The bash script in the 'Setup Python' step has a logical error. The condition checks if `PYTHON_VERSION_INPUT` is empty, but then tries to output that empty value. The intended logic appears to be inverted.
```suggestion
        if [[ -z $PYTHON_VERSION_INPUT ]]; then
          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
        else
          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
        fi
        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
```
created_at: 2025-05-17T02:56:05Z
author_association: NONE
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "artifact-name=%s\n" multicast-deps-${{ steps.output_sha.outputs.sha }}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            THE_RESULT="success"
+          else
+            THE_RESULT="skipped"
+          fi
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
path: .github/actions/setup-py-reqs/action.yml
body: The 'Evaluate Dependencies' step has complex nested if/else logic that's difficult to follow. Consider simplifying the logic or using separate variables for each dependency status to improve readability and maintainability.
```suggestion
        # Initialize result as success
        THE_RESULT="success"
        
        # Check build requirements
        if [[ "${{ steps.install_build_requirements.outcome }}" == "failure" ]] ; then
          THE_RESULT="failure"
        elif [[ ! -r requirements.txt ]] ; then
          THE_RESULT="skipped"
        fi
        
        # Check test requirements
        if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
          THE_RESULT="failure"
        fi
        
        # Check docs requirements
        if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
          THE_RESULT="failure"
        fi
        
        # Exit with appropriate code
        if [[ "${THE_RESULT}" == "success" ]] ; then
          exit 0
        else
          exit 1
        fi
```
created_at: 2025-05-17T02:56:07Z
author_association: NONE
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "artifact-name=%s\n" multicast-deps-${{ steps.output_sha.outputs.sha }}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            THE_RESULT="success"
+          else
+            THE_RESULT="skipped"
+          fi
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize DEPs"
+      id: deps_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.deps_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for [${BUILD_SHA}](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt)" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for \`${BUILD_SHA}\`~" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_build_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [tests/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/tests/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `tests/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [docs/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/docs/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `docs/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
path: .github/actions/setup-py-reqs/action.yml
body: In the 'Summarize DEPs' step, there's a potential issue with handling failure states. The script is using outcome directly in conditionals but should handle possible null or undefined values explicitly.
```suggestion
        # Set default outcomes for safety
        DEPS_OUTCOME="${{ steps.deps_outcome.outcome || 'failure' }}"
        BUILD_OUTCOME="${{ steps.install_build_requirements.outcome || 'skipped' }}"
        TEST_OUTCOME="${{ steps.install_test_requirements.outcome || 'skipped' }}"
        DOCS_OUTCOME="${{ steps.install_docs_requirements.outcome || 'skipped' }}"
        
        if [[ "${DEPS_OUTCOME}" == "success" ]] ; then
          printf "%s\n" "  * :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for [${BUILD_SHA}](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt)" > "$DEPS_STEP_SUMMARY"
          printf "%s\n" " :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
        else
          printf "%s\n" "  * :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for \`${BUILD_SHA}\`~" > "$DEPS_STEP_SUMMARY"
          printf "%s\n" " :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`~" >> "$GITHUB_STEP_SUMMARY"
        fi
        
        if [[ "${BUILD_OUTCOME}" == "success" ]] ; then
          printf "%s\n" "    * :ballot_box_with_check: Installing from [requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
        else
          printf "%s\n" "    * :x: Installing from \`requirements.txt\` failed" >> "$DEPS_STEP_SUMMARY"
        fi
```
created_at: 2025-05-17T02:56:09Z
author_association: NONE
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "artifact-name=%s\n" multicast-deps-${{ steps.output_sha.outputs.sha }}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            THE_RESULT="success"
+          else
+            THE_RESULT="skipped"
+          fi
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize DEPs"
+      id: deps_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.deps_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for [${BUILD_SHA}](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt)" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for \`${BUILD_SHA}\`~" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_build_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [tests/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/tests/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `tests/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [docs/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/docs/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `docs/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+    - name: "Collect and Enumerate Generated Files"
+      id: output_artifact_files
+      if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+      env:
+        DEPS_MATCH_PATTERN: "Dependencies-Summary-Artifact-*.txt"
+        SCRIPT_NAME: ".github/actions/setup-py-reqs/action.yml"
+      shell: bash
+      run: |
+        FILES=$(git ls-files -o --exclude-standard -- ${{ env.DEPS_MATCH_PATTERN }} )
+        if [ -z "$FILES" ]; then
+          printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
+          printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
+          exit 1
+        else
+          printf "%s\n" "DEPS summary files found:"
+          printf "%s\n" "$FILES"
+          mkdir DEPS || :
+          # Replace line breaks with spaces for GitHub Action Output
path: .github/actions/setup-py-reqs/action.yml
body: The 'Collect and Enumerate Generated Files' step doesn't handle file paths with spaces or special characters safely. This could lead to issues when running on different platforms or with unusual file names.
```suggestion
        # Use null-separated output to handle filenames with spaces and special characters
        FILES=$(git ls-files -z -o --exclude-standard -- ${{ env.DEPS_MATCH_PATTERN }} | tr '\0' '\n')
        if [ -z "$FILES" ]; then
          printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
          printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
          exit 1
        else
          printf "%s\n" "DEPS summary files found:"
          printf "%s\n" "$FILES"
          mkdir -p DEPS
          
          # Create a properly quoted list of files for output
          FILE_LIST=""
          while IFS= read -r file; do
            # Skip empty lines
            [ -z "$file" ] && continue
            # Add to list with proper quoting
            if [ -z "$FILE_LIST" ]; then
              FILE_LIST="\"$file\""
            else
              FILE_LIST="$FILE_LIST \"$file\""
            fi
          done <<< "$FILES"
          
          printf "%s\n" "files=$FILE_LIST" >> "$GITHUB_OUTPUT"
          exit 0
        fi
```
created_at: 2025-05-17T02:56:11Z
author_association: NONE
diff_hunk: @@ -82,3 +194,108 @@ jobs:
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
path: .github/workflows/CI-DOCS.yml
body: The DOCS_SUMMARY job references 'needs.COVERAGE.outputs.coverage_outcome' multiple times, but there's no COVERAGE job in this workflow. This will cause the workflow to fail with reference errors.
```suggestion
      - id: report_status
        env:
          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
        run: |
          if [[ "${{ needs.DOCS.outputs.docs_outcome }}" == "success" ]]; then
            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
          else
```
created_at: 2025-05-17T02:56:13Z
author_association: NONE
diff_hunk: @@ -82,3 +194,108 @@ jobs:
         id: post-end
         run: make -j1 -f Makefile clean || true ;
         if: ${{ !cancelled() }}
+
+  DOCS_SUMMARY:
+    permissions:
+      actions: read
+      contents: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, DOCS]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.DOCS.outputs.docs_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/Multicast-Documentation
+          pattern: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-*-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          DOCUMENTATION_COMMENT_BODY: '${{ github.workspace }}/DOCUMENTATION-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.COVERAGE.outputs.coverage_outcome }}" == "success" ]]; then
+            printf "%s\n\n" "# :book: Documentation Summary" > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "  * :ballot_box_with_check: Generating Documentation Passed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "docs_summary=Generating Documentation Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "documentation_success=false" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "  * :x: Generating Documentation Failed" >> "${DOCUMENTATION_COMMENT_BODY}"
+            printf "%s\n" "docs_summary=Generating Documentation Unsuccessful" >> "$GITHUB_OUTPUT"
+          fi
+          cat <"${DOCUMENTATION_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY"
+          { printf "%s\n" 'docs_text<<EOF'; cat <"${DOCUMENTATION_COMMENT_BODY}"; printf "%s\n" 'EOF'; } >> "$GITHUB_OUTPUT"
+      - name: "Upload DOCs summary"
+        id: upload-docs-summary
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: ./DOCUMENTATION-Summary-Artifact.txt
+          name: DOCUMENTATION-COMMENT-BODY-${{ needs.check_mats.outputs.build_sha }}
+          if-no-files-found: error
+          compression-level: 3
+          retention-days: 2
+          overwrite: true
+      - name: "Upload DOCs Bundle"
+        id: upload-docs-bundle
+        if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        with:
+          path: Multicast-Documentation
+          name: Multicast-Documentation-${{ needs.check_mats.outputs.build_sha }}-ALL
+          if-no-files-found: error
+          compression-level: 9
+          overwrite: true
+      - name: checkout repository actions for check
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
+          ref: ${{ needs.check_mats.outputs.build_sha }}
+          sparse-checkout: '.github/actions/check-control'
+      - name: "Compleate DOCs GitHub Check"
+        id: compleate_docs
+        if: ${{ (github.repository == 'reactive-firewall/multicast') && always() }}
+        uses: ./.github/actions/check-control
+        with:
+          name: "CI-DOCS"
+          check-id: ${{ needs.check_mats.outputs.check_id }}
+          title: "Documentation Testing"
+          status: 'completed'
+          conclusion: ${{ needs.COVERAGE.outputs.coverage_outcome }}
+          summary: ${{ steps.report_status.outputs.docs_summary }}
+          text: ${{ steps.report_status.outputs.docs_text }}
+          sha: ${{ needs.check_mats.outputs.build_sha }}
+          workflow-run-id: ${{ needs.check_mats.outputs.docs_id }}
+          details-url: ${{ needs.check_mats.outputs.docs_check_url }}
+
+  DOCS_REPORT:
+    permissions:
+      actions: read
+      contents: write
+    needs: [check_mats, DOCS_SUMMARY]
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() }}
path: .github/workflows/CI-DOCS.yml
body: In the 'Compleate DOCs GitHub Check' step, it references 'needs.COVERAGE.outputs.coverage_outcome' for the conclusion parameter, which doesn't exist in this workflow.
```suggestion
      - name: "Compleate DOCs GitHub Check"
        id: compleate_docs
        if: ${{ (github.repository == 'reactive-firewall/multicast') && always() }}
        uses: ./.github/actions/check-control
        with:
          name: "CI-DOCS"
          check-id: ${{ needs.check_mats.outputs.check_id }}
          title: "Documentation Testing"
          status: 'completed'
          conclusion: ${{ needs.DOCS.outputs.docs_outcome }}
          summary: ${{ steps.report_status.outputs.docs_summary }}
          text: ${{ steps.report_status.outputs.docs_text }}
          sha: ${{ needs.check_mats.outputs.build_sha }}
          workflow-run-id: ${{ needs.check_mats.outputs.docs_id }}
          details-url: ${{ needs.check_mats.outputs.docs_check_url }}
```
created_at: 2025-05-17T02:56:15Z
author_association: NONE
diff_hunk: @@ -965,6 +1210,108 @@ jobs:
       run: make -j1 -f Makefile clean || true ;
       if: ${{ !cancelled() }}
 
+  INTEGRATION_SUMMARY:
+    permissions:
+      actions: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, INTEGRATION]
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.INTEGRATION.outputs.integration_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/EXTRAS
+          pattern: multicast-integration-${{ needs.check_mats.outputs.build_sha }}-part-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          TESTS_COMMENT_BODY: '${{ github.workspace }}/Integration-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.INTEGRATION.outputs.integration_outcome }}" == "success" ]]; then
+            printf "%s\n" "# :open_umbrella: Code Coverage Summary" > "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "coverage_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "tests_summary=Coverage Tests Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${TESTS_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "coverage_success=false" >> "$GITHUB_OUTPUT"
path: .github/workflows/Tests.yml
body: In the INTEGRATION_SUMMARY job, the 'report_status' step is incorrectly using 'needs.COVERAGE.outputs.coverage_outcome' instead of 'needs.INTEGRATION.outputs.integration_outcome'.
```suggestion
      - id: report_status
        env:
          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
          TESTS_COMMENT_BODY: '${{ github.workspace }}/Integration-Summary-Artifact.txt'
        run: |
          if [[ "${{ needs.INTEGRATION.outputs.integration_outcome }}" == "success" ]]; then
            printf "%s\n" "# :open_umbrella: Code Coverage Summary" > "${TESTS_COMMENT_BODY}"
            printf "%s\n" "coverage_success=true" >> "$GITHUB_OUTPUT"
            printf "%s\n" "tests_summary=Coverage Tests Passed" >> "$GITHUB_OUTPUT"
          else
            printf "%s\n\n" "# Known flaws." > "${TESTS_COMMENT_BODY}"
            printf "%s\n" "> [!WARNING]" >> "${TESTS_COMMENT_BODY}"
            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to minimal acceptance testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${TESTS_COMMENT_BODY}"
            printf "%s\n" "coverage_success=false" >> "$GITHUB_OUTPUT"
            printf "%s\n" "tests_summary=Coverage Tests Unsuccessful" >> "$GITHUB_OUTPUT"
          fi
```
created_at: 2025-05-17T02:56:17Z
author_association: NONE
diff_hunk: @@ -233,6 +237,9 @@
 	$(QUIET)$(WAIT)
 	$(QUIET)$(ECHO) "$@: Done."
 
+./dist: build
+	$(QUIET)$(WAIT) ;
path: Makefile
body: The 'dist' target is now referenced as './dist', which is inconsistent with other targets in the Makefile. Consider standardizing on either path-based targets or pure name targets for better maintainability.
```suggestion
dist: build
	$(QUIET)$(WAIT) ;
	$(QUIET)test -d ./dist || mkdir -p ./dist
```
created_at: 2025-05-17T02:56:19Z
author_association: NONE
diff_hunk: @@ -461,9 +468,7 @@
 	$(QUIET)runner=`whoami` ; \
 	if test $$runner != "root" ; then $(ECHO) "You are not root." ; exit 1 ; fi
 
-user-install: build
-	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user "pip>=24.3.1" "setuptools>=75.0" "wheel>=0.44" "build>=1.1.1" 2>$(ERROR_LOG_PATH) || true
-	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user -r "https://raw.githubusercontent.com/reactive-firewall/multicast/stable/requirements.txt" 2>$(ERROR_LOG_PATH) || true
+user-install: ./dist
 	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user dist/multicast-*-py3-*.whl
 	$(QUIET)$(WAIT)
 	$(QUIET)$(ECHO) "$@: Done."
path: Makefile
body: The 'user-install' target has been simplified but may now omit important dependency installation steps. Consider restoring the pip upgrade and requirements installation steps to ensure a complete environment.
```suggestion
user-install: dist
	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user "pip>=24.3.1" "setuptools>=75.0" "wheel>=0.44" "build>=1.1.1" 2>$(ERROR_LOG_PATH) || true
	$(QUIET)$(PYTHON) -m pip install $(PIP_COMMON_FLAGS) $(PIP_ENV_FLAGS) --user dist/multicast-*-py3-*.whl
	$(QUIET)$(WAIT)
	$(QUIET)$(ECHO) "$@: Done."
```
created_at: 2025-05-17T02:56:21Z
author_association: NONE
diff_hunk: @@ -956,6 +986,221 @@ jobs:
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
+    - name: "Generate Summary Filename"
+      id: output_integration_step_summary
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "integration-artifact-name=%s\n" multicast-integration-${VCS_COMMIT_ID}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "integration-artifact-name=%s" multicast-integration-${VCS_COMMIT_ID}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Evaluate Integration Tests"
+      id: integration_tests
+      if: ${{ always() }}
+      shell: bash
path: .github/workflows/Tests.yml
body: The 'output_integration_step_summary' step in the INTEGRATION job has different implementations for Windows vs. non-Windows platforms for generating UUIDs. Consider using a more consistent approach or extracting this to a reusable action.
```suggestion
        # Use a consistent approach for UUID generation across platforms
        if command -v uuidgen &>/dev/null; then
          UUID=$(uuidgen)
        else
          # Fallback for systems without uuidgen
          UUID=$(python -c 'import uuid; print(uuid.uuid4())')
        fi
        
        printf "integration-artifact-name=%s\n" "multicast-integration-${VCS_COMMIT_ID}-part-${UUID}" >> "$GITHUB_OUTPUT"
        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
```
created_at: 2025-05-17T02:56:23Z
author_association: NONE
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "artifact-name=%s\n" multicast-deps-${{ steps.output_sha.outputs.sha }}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            THE_RESULT="success"
+          else
+            THE_RESULT="skipped"
+          fi
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize DEPs"
+      id: deps_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.deps_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for [${BUILD_SHA}](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt)" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for \`${BUILD_SHA}\`~" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_build_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [tests/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/tests/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `tests/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [docs/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/docs/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `docs/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+    - name: "Collect and Enumerate Generated Files"
+      id: output_artifact_files
+      if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+      env:
+        DEPS_MATCH_PATTERN: "Dependencies-Summary-Artifact-*.txt"
+        SCRIPT_NAME: ".github/actions/setup-py-reqs/action.yml"
+      shell: bash
+      run: |
+        FILES=$(git ls-files -o --exclude-standard -- ${{ env.DEPS_MATCH_PATTERN }} )
+        if [ -z "$FILES" ]; then
+          printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
+          printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
+          exit 1
+        else
+          printf "%s\n" "DEPS summary files found:"
+          printf "%s\n" "$FILES"
+          mkdir DEPS || :
path: .github/actions/setup-py-reqs/action.yml
body: There's a security concern in the 'Collect and Enumerate Generated Files' step where the output of git ls-files is directly used in a printf command without proper escaping, which could lead to command injection if there are specially crafted filenames.
```suggestion
        FILES=$(git ls-files -o --exclude-standard -- ${{ env.DEPS_MATCH_PATTERN }} )
        if [ -z "$FILES" ]; then
          printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
          printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
          exit 1
        else
          printf "%s\n" "DEPS summary files found:"
          # Use printf with format specifier for each line to avoid command injection
          while IFS= read -r line; do
            printf "%s\n" "$line"
          done <<< "$FILES"
          
          mkdir DEPS || :
          # Replace line breaks with spaces for GitHub Action Output
          # Use JSON to properly encode the list of files
          FILES_JSON=$(printf '%s\n' "$FILES" | jq -R -s -c 'split("\n") | map(select(length > 0))')
          printf "%s\n" "files=$FILES_JSON" >> "$GITHUB_OUTPUT"
          exit 0
        fi
```
created_at: 2025-05-17T02:56:25Z
author_association: NONE
diff_hunk: @@ -9,22 +9,108 @@ run-name: Generate and lint documentation for ${{ github.ref_name }} by @${{ git
 # Required Secrets:
 # - DOCS_BUILD_REF: Automatic
 
+# Declare default permissions as none.
 permissions: {}
 
 on:  # yamllint disable-line rule:truthy
-  push:
-    branches: ["main", "master", "stable"]
-    tags: ["v*"]
-    paths: ["docs/**", ".github/workflows/CI-DOCS.yml", "**/*.md", "README.md", "LICENSE.md"]
-  pull_request:
-    types: [opened, reopened, ready_for_review]
-    branches: ["feature-*", "patch-*", "HOTFIX-*"]
-    paths: ["docs/**", ".github/workflows/CI-DOCS.yml", "**/*.md", "multicast/*.py"]
-  pull_request_target:
-    types: [opened, edited, reopened, ready_for_review]
-    branches: ["main", "master", "stable"]
+  workflow_run:
+    workflows: ["CI-MATs"]
+    types:
+      - completed
 
 jobs:
+  check_mats:
+    permissions:
+      actions: read
+      pull-requests: read
+      checks: write
+    environment: "Documentation"
+    runs-on: ubuntu-latest
+    env:
+      GH_TOKEN: ${{ github.token }}
+    outputs:
+      should_run: ${{ steps.check.outputs.should_run }}
+      trigger_id: ${{ steps.get_trigger_id.outputs.trigger_id }}
+      build_id: ${{ steps.load_build_info.outputs.build_id }}
+      build_url: ${{ steps.load_build_info.outputs.build_url }}
+      build_ref: ${{ steps.load_build_info.outputs.build_ref }}
+      build_ref_name: ${{ steps.load_build_info.outputs.build_ref_name }}
+      build_sha: ${{ steps.load_build_info.outputs.build_sha }}
+      build_artifact_filename: ${{ steps.load_build_info.outputs.build_artifact_filename }}
+      build_artifact_url: ${{ steps.load_build_info.outputs.build_artifact_url }}
+      build_artifact_id: ${{ steps.load_build_info.outputs.build_artifact_id }}
+      build_artifact_digest: ${{ steps.load_build_info.outputs.build_artifact_digest }}
+      build_environment: ${{ steps.load_build_info.outputs.build_environment }}
+      mats_environment: ${{ steps.load_build_info.outputs.mats_environment }}
+      mats_id: ${{ steps.load_build_info.outputs.mats_id }}
+      mats_url: ${{ steps.load_build_info.outputs.mats_url }}
+      mats_ref: ${{ steps.load_build_info.outputs.mats_ref }}
+      mats_ref_name: ${{ steps.load_build_info.outputs.mats_ref_name }}
+      mats_sha: ${{ steps.load_build_info.outputs.mats_sha }}
+      mats_success: ${{ steps.load_build_info.outputs.mats_success }}
+      docs_id: ${{ steps.output_run_id.outputs.docs_id }}
+      docs_check_url: ${{ steps.output_run_id.outputs.docs_url }}
+      check_id: ${{ steps.output_docs_check_id.outputs.check-id }}
+    steps:
+      - id: check
+        run: |
+          if [[ "${{ github.event.workflow_run.conclusion }}" == "success" ]]; then
+            echo "should_run=true" >> "$GITHUB_OUTPUT"
+          else
+            echo "should_run=false" >> "$GITHUB_OUTPUT"
+          fi
+      - id: get_trigger_id
+        if: ${{ (steps.check.outputs.should_run == 'true') && success() }}
+        run: |
+          ID_VALUE=$(gh api "${{ github.event.workflow_run.url }}" --jq '.id')
+          if [[ -n "$ID_VALUE" ]]; then
+            echo "trigger_id=$ID_VALUE" >> "$GITHUB_OUTPUT"
+          else
+            echo "trigger_id=null" >> "$GITHUB_OUTPUT"  # Default fallback
+          fi
+      - name: "Fetch MATs Info"
+        if: ${{ (github.repository == 'reactive-firewall/multicast') && success() }}
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
path: .github/workflows/CI-DOCS.yml
body: In the 'check_mats' job, there's no explicit error handling if artifact downloads fail. Consider adding error handling when fetching artifacts from the previous workflow run to provide clearer failure messages.
```suggestion
      - name: "Fetch MATs Info"
        id: fetch_mats_info
        if: ${{ (github.repository == 'reactive-firewall/multicast') && success() }}
        continue-on-error: true
        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
        with:
          path: "multicast-info.txt"
          pattern: multicast-info-*
          repository: reactive-firewall/multicast
          merge-multiple: true
          github-token: ${{ env.GH_TOKEN }}
          run-id: ${{ steps.get_trigger_id.outputs.trigger_id }}
      - name: "Check if artifact download was successful"
        if: ${{ steps.fetch_mats_info.outcome != 'success' }}
        run: |
          echo "::error::Failed to download artifacts from previous workflow. Cannot proceed with documentation generation."
          exit 1
```
created_at: 2025-05-17T02:56:27Z
author_association: NONE
diff_hunk: @@ -965,6 +1210,108 @@ jobs:
       run: make -j1 -f Makefile clean || true ;
       if: ${{ !cancelled() }}
 
+  INTEGRATION_SUMMARY:
+    permissions:
+      actions: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, INTEGRATION]
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.INTEGRATION.outputs.integration_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
path: .github/workflows/Tests.yml
body: The 'INTEGRATION_SUMMARY' job is missing error handling if the artifact download fails. Consider adding error handling to provide better diagnostic information.
```suggestion
      - name: Download All Artifacts
        id: download_integration_artifacts
        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
        continue-on-error: true
        with:
          path: ${{ github.workspace }}/EXTRAS
          pattern: multicast-integration-${{ needs.check_mats.outputs.build_sha }}-part-*
          merge-multiple: true
      - name: Check artifact download status
        if: ${{ steps.download_integration_artifacts.outcome != 'success' }}
        run: |
          echo "::warning::Failed to download integration artifacts. Summary may be incomplete."
          mkdir -p ${{ github.workspace }}/EXTRAS
```
created_at: 2025-05-17T02:56:29Z
author_association: NONE
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "artifact-name=%s\n" multicast-deps-${{ steps.output_sha.outputs.sha }}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            THE_RESULT="success"
+          else
+            THE_RESULT="skipped"
+          fi
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
path: .github/actions/setup-py-reqs/action.yml
user: login: reactive-firewall
body: :thinking: I'm leaning more towards just adding comments like so:
```suggestion
      if: ${{ !cancelled() }}
      shell: bash
      run: |
        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
          if [[ ( -r requirements.txt ) ]] ; then
            # Initialize result as success b/c nothing failed ... yet
            THE_RESULT="success"
          else
            # Initialize result as skipped b/c nothing could be done without requirements.txt
            THE_RESULT="skipped"
          fi
        else
          # Initialize result as failure right away
          THE_RESULT="failure"
        fi
        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
          # keep result as success b/c something succeeded and nothing failed ... yet
          THE_RESULT="success"
        else
          # check for actual failure
          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
             # force result as failure b/c something failed
             THE_RESULT="failure"
          fi
        fi
        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
          # keep result as success b/c something succeeded and nothing failed ... at all
          THE_RESULT="success"
        else
          # check for actual failure
          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
             # force result as failure b/c something failed
             THE_RESULT="failure"
          fi
        fi
        # hint to help with debugging
        printf "::debug:: %s\n" "The "
        if [[ "${THE_RESULT}" == "success" ]] ; then
          exit 0
        else
          # exit as failure b/c either a soft-fail (skip/cancelled/etc.) or actual failure
          exit 1
        fi
```
created_at: 2025-05-17T03:43:56Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "artifact-name=%s\n" multicast-deps-${{ steps.output_sha.outputs.sha }}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            THE_RESULT="success"
+          else
+            THE_RESULT="skipped"
+          fi
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize DEPs"
+      id: deps_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.deps_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for [${BUILD_SHA}](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt)" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for \`${BUILD_SHA}\`~" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_build_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [tests/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/tests/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `tests/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [docs/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/docs/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `docs/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
path: .github/actions/setup-py-reqs/action.yml
user: login: reactive-firewall
body: 🙅🏻 The current implementation is fine.
created_at: 2025-05-17T03:45:51Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "artifact-name=%s\n" multicast-deps-${{ steps.output_sha.outputs.sha }}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            THE_RESULT="success"
+          else
+            THE_RESULT="skipped"
+          fi
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize DEPs"
+      id: deps_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.deps_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for [${BUILD_SHA}](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt)" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for \`${BUILD_SHA}\`~" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_build_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [tests/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/tests/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `tests/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [docs/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/docs/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `docs/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+    - name: "Collect and Enumerate Generated Files"
+      id: output_artifact_files
+      if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+      env:
+        DEPS_MATCH_PATTERN: "Dependencies-Summary-Artifact-*.txt"
+        SCRIPT_NAME: ".github/actions/setup-py-reqs/action.yml"
+      shell: bash
+      run: |
+        FILES=$(git ls-files -o --exclude-standard -- ${{ env.DEPS_MATCH_PATTERN }} )
+        if [ -z "$FILES" ]; then
+          printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
+          printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
+          exit 1
+        else
+          printf "%s\n" "DEPS summary files found:"
+          printf "%s\n" "$FILES"
+          mkdir DEPS || :
path: .github/actions/setup-py-reqs/action.yml
user: login: reactive-firewall
body: @coderabbitai, what do you have to say about this suggestion, is the risk real? if so please explain why and how an actual command injection works with at least 2 specific examples demonstrating the exploit; if not a real risk, please explain why not.
created_at: 2025-05-17T04:03:56Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,221 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -z $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "artifact-name=%s\n" multicast-deps-${{ steps.output_sha.outputs.sha }}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            THE_RESULT="success"
+          else
+            THE_RESULT="skipped"
+          fi
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize DEPs"
+      id: deps_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.deps_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for [${BUILD_SHA}](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt)" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\` for \`${BUILD_SHA}\`~" > "$DEPS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Installing dependencies succeeded with python version \`${PYTHON_VERSION}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_build_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [tests/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/tests/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `tests/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Installing from [docs/requirements.txt](https://github.com/reactive-firewall/multicast/blob/${BUILD_SHA}/docs/requirements.txt) succeeded" >> "$DEPS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Installing from `docs/requirements.txt` failed" >> "$DEPS_STEP_SUMMARY"
+        fi
+    - name: "Collect and Enumerate Generated Files"
+      id: output_artifact_files
+      if: ${{ !cancelled() && (github.repository == 'reactive-firewall/multicast') }}
+      env:
+        DEPS_MATCH_PATTERN: "Dependencies-Summary-Artifact-*.txt"
+        SCRIPT_NAME: ".github/actions/setup-py-reqs/action.yml"
+      shell: bash
+      run: |
+        FILES=$(git ls-files -o --exclude-standard -- ${{ env.DEPS_MATCH_PATTERN }} )
+        if [ -z "$FILES" ]; then
+          printf "::warning file=%s:: %s\n" "${SCRIPT_NAME}" "No summary files found."
+          printf "%s\n" "files=" >> "$GITHUB_OUTPUT"
+          exit 1
+        else
+          printf "%s\n" "DEPS summary files found:"
+          printf "%s\n" "$FILES"
+          mkdir DEPS || :
path: .github/actions/setup-py-reqs/action.yml
user: login: coderabbitai[bot]
body: @reactive-firewall After analyzing the code, I don't believe there's a real command injection risk in the current implementation. Here's why:

The key factor is that all uses of the `$FILES` variable are properly quoted with double quotes in printf statements. When variables are properly quoted in this way, their contents are treated as a single text argument, not as executable code.

For command injection to work, you would need one of these scenarios:

**Example 1: Unquoted variable in a command**
```bash
# Vulnerable (unquoted):
echo $FILES
# If FILES contained "file.txt; rm -rf /" this would execute the rm command

# Your code (safe because of quotes):
printf "%s\n" "$FILES"
# Even if FILES contained malicious content, it would just be printed
```

**Example 2: Variable interpolation in eval or similar**
```bash
# Vulnerable:
eval "ls $FILES"
# If FILES was 'x.txt; rm -rf /' this would run the destructive command

# Your code doesn't use eval or similar constructs that interpret the content
```

The suggestion to iterate through files line-by-line and use JSON encoding is a good practice for handling filenames with special characters (like newlines), but it's addressing a potential formatting issue rather than a security vulnerability.

Your current implementation is safe from command injection in the context it's being used.

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall After analyzing the code, I don't believe there's a real command injection risk in the current implementation. Here's why:

The key factor is that all uses of the `$FILES` variable are properly quoted with double quotes in printf statements. When variables are properly quoted in this way, their contents are treated as a single text argument, not as executable code.

For command injection to work, you would need one of these scenarios:

**Example 1: Unquoted variable in a command**
```bash
# Vulnerable (unquoted):
echo $FILES
# If FILES contained "file.txt; rm -rf /" this would execute the rm command

# Your code (safe because of quotes):
printf "%s\n" "$FILES"
# Even if FILES contained malicious content, it would just be printed
```

**Example 2: Variable interpolation in eval or similar**
```bash
# Vulnerable:
eval "ls $FILES"
# If FILES was 'x.txt; rm -rf /' this would run the destructive command

# Your code doesn't use eval or similar constructs that interpret the content
```

The suggestion to iterate through files line-by-line and use JSON encoding is a good practice for handling filenames with special characters (like newlines), but it's addressing a potential formatting issue rather than a security vulnerability.

Your current implementation is safe from command injection in the context it's being used.

---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T04:04:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,239 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -n $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "artifact-name=%s\n" multicast-integration-${BUILD_SHA}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "artifact-name=%s" multicast-integration-${BUILD_SHA}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Install Build Dependencies"
+      id: install_build_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-build-reqs"
+        make -j1 -f Makefile init || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Test Dependencies"
+      id: install_test_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-test-reqs"
+        make -j1 -f Makefile test-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Install Documentation Dependencies"
+      id: install_docs_requirements
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        printf "%s\n" "::group::prep-docs-reqs"
+        make -j1 -f Makefile docs-reqs || exit 1
+        printf "%s\n" "::endgroup::"
+    - name: "Evaluate Dependencies"
+      id: deps_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.install_build_requirements.outcome }}" != "failure" ]] ; then
+          if [[ ( -r requirements.txt ) ]] ; then
+            # Initialize result as success b/c nothing failed ... yet
+            THE_RESULT="success"
+          else
+            # Initialize result as skipped b/c nothing could be done without requirements.txt
+            THE_RESULT="skipped"
+          fi
+        else
+          # Initialize result as failure right away
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.install_test_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          # keep result as success b/c something succeeded and nothing failed ... yet
+          THE_RESULT="success"
+        else
+          # check for actual failure
+          if [[ "${{ steps.install_test_requirements.outcome }}" == "failure" ]] ; then
+             # force result as failure b/c something failed
+             THE_RESULT="failure"
+          fi
+        fi
+        if [[ "${{ steps.install_docs_requirements.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          # keep result as success b/c something succeeded and nothing failed ... at all
+          THE_RESULT="success"
+        else
+          # check for actual failure
+          if [[ "${{ steps.install_docs_requirements.outcome }}" == "failure" ]] ; then
+             # force result as failure b/c something failed
+             THE_RESULT="failure"
+          fi
+        fi
+        # hint to help with debugging
+        printf "::debug:: %s\n" "The "
path: .github/actions/setup-py-reqs/action.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Incomplete debug message.**

The debug message on line 160 appears to be incomplete, printing only `"The "` which doesn't provide useful debugging information.

```diff
-        printf "::debug:: %s\n" "The "
+        printf "::debug:: %s\n" "The result of dependency evaluation: ${THE_RESULT}"
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
        printf "::debug:: %s\n" "The result of dependency evaluation: ${THE_RESULT}"
        if [[ "${THE_RESULT}" == "success" ]] ; then
          exit 0
        else
          exit 1
        fi
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/actions/setup-py-reqs/action.yml at line 160, the debug message is
incomplete and only prints "The ". Update this line to include a complete and
meaningful debug message that provides useful information for debugging
purposes, ensuring the message clearly describes the context or state being
logged.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 57f5592
created_at: 2025-05-17T04:31:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -797,19 +797,21 @@ jobs:
         persist-credentials: false
         ref: ${{ needs.check_mats.outputs.build_sha }}
         sparse-checkout: '.github/actions/checkout-and-rebuild'
-    - name: Checkout repository for MATs with ${{ matrix.python-version }}
+    - name: Checkout repository for Style with ${{ matrix.python-version }}
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Incorrect variable reference in `STYLE` job checkout**  
`matrix.python-version` isn’t defined for the `STYLE` job (no `matrix` strategy). Replace with the intended Python version variable (e.g., `${{ vars.PYTHON_DEFAULT }}` or `${{ env.PYTHON_VERSION }}`).

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.7)</summary>

800-800: property "python-version" is not defined in object type {}

(expression)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml at line 800, the checkout step in the STYLE job
incorrectly references the undefined variable `matrix.python-version`. Replace
this with the correct Python version variable such as `${{ vars.PYTHON_DEFAULT
}}` or `${{ env.PYTHON_VERSION }}` to properly specify the Python version
without relying on a matrix strategy.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 57f5592
created_at: 2025-05-17T04:31:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -956,6 +986,221 @@
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
+    - name: "Generate Summary Filename"
+      id: output_integration_step_summary
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "integration-artifact-name=%s\n" multicast-integration-${VCS_COMMIT_ID}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "integration-artifact-name=%s" multicast-integration-${VCS_COMMIT_ID}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Evaluate Integration Tests"
+      id: integration_tests
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-main.outcome }}" == "failure" ]] ; then
+            THE_RESULT="failure"
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-pytest.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-doctests.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            if [[ "${THE_RESULT}" != "failure" ]] ; then
+              if [[ "${THE_RESULT}" != "neutral" ]] ; then
+                THE_RESULT="skipped"
+              else
+                THE_RESULT="neutral"
+              fi
+            else
+              THE_RESULT="failure"
+            fi
+          fi
+        fi
+        printf "%s\n" "integration_test_outcome=${THE_RESULT}" >> "$GITHUB_OUTPUT"
+        if [[ "${THE_RESULT}" != "failure" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Evaluate Integration Tests"
+      id: integration_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration_tests.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-reports-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize Tests"
+      id: integration_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        BUILD_LINK="[${VCS_COMMIT_ID}](https://github.com/reactive-firewall/multicast/commit/${VCS_COMMIT_ID})"
+        if [[ "${{ steps.integration_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n\n" "## :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for ${BUILD_LINK}" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n\n" "## :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`~" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Updated integration summary formatting**  
Refreshed headings and bullet points better align with the new summary schema introduced for coverage and doctests.  
  
Consider extracting common summary-formatting logic into a reusable snippet to reduce duplication across jobs.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml around lines 1108 to 1116, the integration
summary formatting is duplicated for success and failure cases. Refactor by
extracting the common summary-formatting logic into a reusable snippet or
function to avoid repetition. This snippet should handle the construction of the
summary messages with appropriate headings, bullet points, and variable
interpolation, then be called from each job to maintain consistency and reduce
code duplication.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-17T04:31:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -856,14 +858,28 @@
       VCS_COMMIT_ID: ${{ needs.check_mats.outputs.build_sha }}
       CODECLIMATE_REPO_TOKEN: ${{ secrets.CODECLIMATE_REPO_TOKEN }}
       CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
+    outputs:
+      integration_outcome: ${{ steps.integration_outcome.outcome }}
+      integration_test_outcome: ${{ steps.integration_tests.integration_test_outcome }}
+      integration_pytest_outcome: ${{ steps.integration-pytest.outcome }}
+      integration_doctest_outcome: ${{ steps.integration-doctests.outcome }}
+      integration_function_outcome: ${{ steps.integration-main.outcome }}
+      integration_upload_codecov_test_outcome: ${{ steps.integration-codecov-results-upload.outcome }}
+      integration_upload_codecov_coverage_outcome: ${{ steps.integration-codecov-upload.outcome }}
+      integration_upload_codeclimate_outcome: ${{ steps.integration-codeclimate-upload.outcome }}
+      integration_upload_deepsource_outcome: ${{ steps.integration-deepsource-upload.outcome }}
+      integration_upload_artifact_outcome: ${{ steps.integration-reports-upload.outcome }}
+      integration_artifact_url: ${{ steps.integration-reports-upload.outputs.artifact-url }}
+      integration_artifact_id: ${{ steps.integration-reports-upload.outputs.artifact-id }}
+      integration_artifact_digest: ${{ steps.integration-reports-upload.outputs.artifact-digest }}
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix job output reference for `integration_test_outcome`**  
In the `outputs` block, `integration_test_outcome` is currently set as `${{ steps.integration_tests.integration_test_outcome }}`, missing `.outputs`. This will not capture the custom output.  


Apply this change:
```diff
- integration_test_outcome: ${{ steps.integration_tests.integration_test_outcome }}
+ integration_test_outcome: ${{ steps.integration_tests.outputs.integration_test_outcome }}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
    outputs:
      integration_outcome: ${{ steps.integration_outcome.outcome }}
      integration_test_outcome: ${{ steps.integration_tests.outputs.integration_test_outcome }}
      integration_pytest_outcome: ${{ steps.integration-pytest.outcome }}
      integration_doctest_outcome: ${{ steps.integration-doctests.outcome }}
      integration_function_outcome: ${{ steps.integration-main.outcome }}
      integration_upload_codecov_test_outcome: ${{ steps.integration-codecov-results-upload.outcome }}
      integration_upload_codecov_coverage_outcome: ${{ steps.integration-codecov-upload.outcome }}
      integration_upload_codeclimate_outcome: ${{ steps.integration-codeclimate-upload.outcome }}
      integration_upload_deepsource_outcome: ${{ steps.integration-deepsource-upload.outcome }}
      integration_upload_artifact_outcome: ${{ steps.integration-reports-upload.outcome }}
      integration_artifact_url: ${{ steps.integration-reports-upload.outputs.artifact-url }}
      integration_artifact_id: ${{ steps.integration-reports-upload.outputs.artifact-id }}
      integration_artifact_digest: ${{ steps.integration-reports-upload.outputs.artifact-digest }}
```

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.7)</summary>

863-863: property "integration_test_outcome" is not defined in object type {conclusion: string; outcome: string; outputs: {string => string}}

(expression)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml around lines 861 to 874, the output reference for
integration_test_outcome is missing the .outputs suffix, so it should be changed
from ${{ steps.integration_tests.integration_test_outcome }} to ${{
steps.integration_tests.outputs.integration_test_outcome }} to correctly capture
the custom output from that step.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 57f5592
created_at: 2025-05-17T04:31:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,239 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -n $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "artifact-name=%s\n" multicast-integration-${BUILD_SHA}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "artifact-name=%s" multicast-integration-${BUILD_SHA}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
path: .github/actions/setup-py-reqs/action.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Optional: Simplify artifact-name generation for readability.**  
You can consolidate the UUID logic into a single variable and a single `printf` call to reduce repetition:

```diff
-        if [[ ${{ runner.os }} != 'Windows' ]] ; then
-          printf "artifact-name=%s\n" multicast-integration-${BUILD_SHA}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
-        else
-          printf "artifact-name=%s" multicast-integration-${BUILD_SHA}-part- >> "$GITHUB_OUTPUT"
-          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
-        fi
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          ARTIFACT_ID=$(uuidgen)
+        else
+          ARTIFACT_ID=$(printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x" \
+            $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) \
+            $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM)
+        fi
+        printf "artifact-name=%s\n" "multicast-integration-${BUILD_SHA}-part-${ARTIFACT_ID}" >> "$GITHUB_OUTPUT"
```  
This refactor maintains the same output while improving readability.  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
      run: |
        if [[ ${{ runner.os }} != 'Windows' ]] ; then
          ARTIFACT_ID=$(uuidgen)
        else
          ARTIFACT_ID=$(printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x" \
            $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) \
            $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM)
        fi
        printf "artifact-name=%s\n" "multicast-integration-${BUILD_SHA}-part-${ARTIFACT_ID}" >> "$GITHUB_OUTPUT"
        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
```

</details>

<!-- suggestion_end -->

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/actions/setup-py-reqs/action.yml around lines 90 to 97, the
artifact-name generation uses separate printf calls and conditional logic that
can be simplified. Refactor by generating the UUID or unique suffix once into a
variable depending on the OS, then use a single printf statement to output the
full artifact-name. This reduces repetition and improves readability while
preserving the same output format.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T04:53:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -107,7 +109,7 @@ jobs:
           ref: ${{ steps.load_build_info.outputs.build_sha }}
           sparse-checkout: '.github/actions/check-control'
       - name: "Queue Tests GitHub Check"
-        id: output_mats_check_id
+        id: output_tests_check_id
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Consider kebab-case for `id`**  
The step ID `output_tests_check_id` mixes snake_case and hyphens. For consistency with other steps, consider renaming it to `output-tests-check-id`.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml at line 112, the step ID uses snake_case mixed
with hyphens as `output_tests_check_id`. Rename this ID to use consistent
kebab-case by changing it to `output-tests-check-id` to match the style of other
step IDs in the workflow.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-17T04:53:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -965,6 +1210,108 @@
       run: make -j1 -f Makefile clean || true ;
       if: ${{ !cancelled() }}
 
+  INTEGRATION_SUMMARY:
+    permissions:
+      actions: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, INTEGRATION]
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.INTEGRATION.outputs.integration_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/EXTRAS
+          pattern: multicast-integration-${{ needs.check_mats.outputs.build_sha }}-part-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          TESTS_COMMENT_BODY: '${{ github.workspace }}/Integration-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.INTEGRATION.outputs.integration_outcome }}" == "success" ]]; then
+            printf "%s\n" "# :clipboard: Testing Summary" > "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "test_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "tests_summary=CI Tests Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${TESTS_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "test_success=false" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "tests_summary=Some Tests Unsuccessful" >> "$GITHUB_OUTPUT"
+          fi
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Generate INTEGRATION summary header**  
The step creates a clear pass/fail header and sets outputs for comment body and summary. Consider aligning the messaging keys (`test_success`, `tests_summary`) with other jobs for consistency.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml around lines 1233 to 1243, the output keys
`test_success` and `tests_summary` used in this step should be aligned with the
naming conventions used in other jobs for consistency. Review the keys used in
other workflow jobs and update these keys accordingly to match, ensuring
uniformity in output naming across the workflow.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-17T04:53:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -956,6 +986,221 @@
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
+    - name: "Generate Summary Filename"
+      id: output_integration_step_summary
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "integration-artifact-name=%s\n" multicast-integration-${VCS_COMMIT_ID}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "integration-artifact-name=%s" multicast-integration-${VCS_COMMIT_ID}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Evaluate Integration Tests"
+      id: integration_tests
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-main.outcome }}" == "failure" ]] ; then
+            THE_RESULT="failure"
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-pytest.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-doctests.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            if [[ "${THE_RESULT}" != "failure" ]] ; then
+              if [[ "${THE_RESULT}" != "neutral" ]] ; then
+                THE_RESULT="skipped"
+              else
+                THE_RESULT="neutral"
+              fi
+            else
+              THE_RESULT="failure"
+            fi
+          fi
+        fi
+        printf "%s\n" "integration_test_outcome=${THE_RESULT}" >> "$GITHUB_OUTPUT"
+        if [[ "${THE_RESULT}" != "failure" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Evaluate raw integration test outcomes**  
The nested logic correctly handles success, failure, and skipped statuses from functional, pytest, and doctest steps. Consider refactoring the shell logic into a small helper script or function to improve readability and reduce duplication.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml around lines 1001 to 1062, the current shell
script uses deeply nested if-else statements to evaluate integration test
outcomes, which reduces readability and maintainability. Refactor this logic by
extracting it into a separate helper script or defining a shell function that
takes test outcomes as input and returns the combined result. This will simplify
the main workflow step, reduce code duplication, and make the logic easier to
follow and update.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-17T04:53:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -965,6 +1210,108 @@
       run: make -j1 -f Makefile clean || true ;
       if: ${{ !cancelled() }}
 
+  INTEGRATION_SUMMARY:
+    permissions:
+      actions: read
+      pull-requests: read
+      checks: write
+    needs: [check_mats, INTEGRATION]
+    runs-on: ubuntu-latest
+    if: ${{ !cancelled() && (needs.check_mats.outputs.should_run == 'true') && (needs.INTEGRATION.outputs.integration_outcome != 'cancelled') }}
+    steps:
+      - name: Download All Artifacts
+        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+        with:
+          path: ${{ github.workspace }}/EXTRAS
+          pattern: multicast-integration-${{ needs.check_mats.outputs.build_sha }}-part-*
+          merge-multiple: true
+      - id: report_status
+        env:
+          BUILD_SHA: ${{ needs.check_mats.outputs.build_sha }}
+          TESTS_COMMENT_BODY: '${{ github.workspace }}/Integration-Summary-Artifact.txt'
+        run: |
+          if [[ "${{ needs.INTEGRATION.outputs.integration_outcome }}" == "success" ]]; then
+            printf "%s\n" "# :clipboard: Testing Summary" > "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "test_success=true" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "tests_summary=CI Tests Passed" >> "$GITHUB_OUTPUT"
+          else
+            printf "%s\n\n" "# Known flaws." > "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "> [!WARNING]" >> "${TESTS_COMMENT_BODY}"
+            printf "%s\n\n" "> This commit has known flaws. Each commit is subject to minimal acceptance testing, and then select commits are subject to extra testing to evaluate release candidates; This commit has been deemed _not ready_ for release." >> "${TESTS_COMMENT_BODY}"
+            printf "%s\n" "test_success=false" >> "$GITHUB_OUTPUT"
+            printf "%s\n" "tests_summary=Some Tests Unsuccessful" >> "$GITHUB_OUTPUT"
+          fi
+          for OS_TAG in "Linux" "macOS" "Windows" ; do
+            for TYPE_TAG in "Integration" ; do
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+              cat <./EXTRAS/"${TYPE_TAG}-Summary-Artifact-${OS_TAG}-${{ vars.PYTHON_OLD_MIN }}.txt" >> "${TESTS_COMMENT_BODY}" || :
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+              cat <./EXTRAS/"${TYPE_TAG}-Summary-Artifact-${OS_TAG}-${{ vars.PYTHON_OLD_EXTRA }}.txt" >> "${TESTS_COMMENT_BODY}" || :
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+              cat <./EXTRAS/"${TYPE_TAG}-Summary-Artifact-${OS_TAG}-${{ vars.PYTHON_DEFAULT }}.txt" >> "${TESTS_COMMENT_BODY}" || :
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+              cat <./EXTRAS/"${TYPE_TAG}-Summary-Artifact-${OS_TAG}-${{ vars.PYTHON_EXPERIMENTAL }}.txt" >> "${TESTS_COMMENT_BODY}" || :
+              printf "\n" >> "${TESTS_COMMENT_BODY}"
+            done ;
+          done ;
+          cat <"${TESTS_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY"
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Loop OS and Python tiers for summary inclusion**  
The nested `for` loops correctly append each summary artifact. You could abstract the path construction and looping into a reusable snippet to reduce duplication across summary jobs.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml around lines 1244 to 1257, the nested for loops
append summary artifacts for each OS and Python tier but contain repetitive code
for constructing file paths and appending content. Refactor by creating a
reusable snippet or function that takes OS and Python version variables as
parameters to build the file paths and append the summaries, then call this
snippet within the loops to reduce duplication and improve maintainability.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-17T04:53:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -956,6 +986,221 @@
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
+    - name: "Generate Summary Filename"
+      id: output_integration_step_summary
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "integration-artifact-name=%s\n" multicast-integration-${VCS_COMMIT_ID}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "integration-artifact-name=%s" multicast-integration-${VCS_COMMIT_ID}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Evaluate Integration Tests"
+      id: integration_tests
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-main.outcome }}" == "failure" ]] ; then
+            THE_RESULT="failure"
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-pytest.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-doctests.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            if [[ "${THE_RESULT}" != "failure" ]] ; then
+              if [[ "${THE_RESULT}" != "neutral" ]] ; then
+                THE_RESULT="skipped"
+              else
+                THE_RESULT="neutral"
+              fi
+            else
+              THE_RESULT="failure"
+            fi
+          fi
+        fi
+        printf "%s\n" "integration_test_outcome=${THE_RESULT}" >> "$GITHUB_OUTPUT"
+        if [[ "${THE_RESULT}" != "failure" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Evaluate Integration Tests"
+      id: integration_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration_tests.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-reports-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize Tests"
+      id: integration_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        BUILD_LINK="[${VCS_COMMIT_ID}](https://github.com/reactive-firewall/multicast/commit/${VCS_COMMIT_ID})"
+        if [[ "${{ steps.integration_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n\n" "## :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for ${BUILD_LINK}" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n\n" "## :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`~" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Functional testing succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Functional testing failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Acceptance testing with \`pytest\` succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Acceptance testing with \`pytest\` failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Uploading integration testing reports artifact succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Uploading integration testing reports artifact failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Integrated Doctesting succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Integrated Doctesting failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        printf "\n%s\n\n" "<details><summary>Reporting Details</summary>" >> "$TESTS_STEP_SUMMARY"
+        printf "%s\n\n" "### :open_umbrella: Functional testing coverage reporting" >> "$TESTS_STEP_SUMMARY"
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to CodeCov succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-codecov-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to CodeCov failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to CodeCov was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to codeclimate succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-codeclimate-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to codeclimate failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to codeclimate was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to deepsource succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-deepsource-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to deepsource failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to deepsource was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        printf "\n%s\n\n" "</details>" >> "$TESTS_STEP_SUMMARY"
+        if [[ "${{ steps.integration-reports-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Uploading [integration coverage report artifact](${{ steps.integration-reports-upload.outputs.artifact-url }}) succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Uploading integration coverage report artifact failed" >> "$TESTS_STEP_SUMMARY"
+        fi
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Consolidate integration summary generation**  
The formatting steps produce a rich markdown summary but contain repetition. Extracting common summary patterns (headings, icons, bullet templates) into a reusable action or a small shared script would DRY up this block.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml from lines 1108 to 1170, the integration summary
generation code repeats similar patterns for success and failure messages with
icons and bullet points. To fix this, refactor by extracting the repeated
formatting logic into a reusable shell function or a separate script that
accepts parameters like step name, outcome, and message. Replace the repeated
printf blocks with calls to this function or script to reduce duplication and
improve maintainability.
```

</details>

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T04:53:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -956,6 +986,221 @@
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
+    - name: "Generate Summary Filename"
+      id: output_integration_step_summary
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "integration-artifact-name=%s\n" multicast-integration-${VCS_COMMIT_ID}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "integration-artifact-name=%s" multicast-integration-${VCS_COMMIT_ID}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Evaluate Integration Tests"
+      id: integration_tests
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-main.outcome }}" == "failure" ]] ; then
+            THE_RESULT="failure"
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-pytest.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-doctests.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            if [[ "${THE_RESULT}" != "failure" ]] ; then
+              if [[ "${THE_RESULT}" != "neutral" ]] ; then
+                THE_RESULT="skipped"
+              else
+                THE_RESULT="neutral"
+              fi
+            else
+              THE_RESULT="failure"
+            fi
+          fi
+        fi
+        printf "%s\n" "integration_test_outcome=${THE_RESULT}" >> "$GITHUB_OUTPUT"
+        if [[ "${THE_RESULT}" != "failure" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Evaluate Integration Tests"
+      id: integration_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration_tests.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-reports-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Aggregate overall integration outcome**  
This block combines all upload and test results into a final pass/fail exit code. It may benefit from simplifying the condition checks (e.g., using an array of statuses) to make future maintenance easier.

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
In .github/workflows/Tests.yml around lines 1063 to 1102, the current script
uses repetitive if-else statements to aggregate integration test and upload
outcomes into a final result. Simplify this by creating an array of the relevant
step outcomes and iterating over it to check conditions, updating THE_RESULT
accordingly. This will reduce code duplication and improve maintainability while
preserving the logic that THE_RESULT should only be "success" if all required
steps meet their success criteria.
```

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-17T04:53:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -956,6 +986,221 @@
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
+    - name: "Generate Summary Filename"
+      id: output_integration_step_summary
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "integration-artifact-name=%s\n" multicast-integration-${VCS_COMMIT_ID}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "integration-artifact-name=%s" multicast-integration-${VCS_COMMIT_ID}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Evaluate Integration Tests"
+      id: integration_tests
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-main.outcome }}" == "failure" ]] ; then
+            THE_RESULT="failure"
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-pytest.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-doctests.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            if [[ "${THE_RESULT}" != "failure" ]] ; then
+              if [[ "${THE_RESULT}" != "neutral" ]] ; then
+                THE_RESULT="skipped"
+              else
+                THE_RESULT="neutral"
+              fi
+            else
+              THE_RESULT="failure"
+            fi
+          fi
+        fi
+        printf "%s\n" "integration_test_outcome=${THE_RESULT}" >> "$GITHUB_OUTPUT"
+        if [[ "${THE_RESULT}" != "failure" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Evaluate Integration Tests"
+      id: integration_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration_tests.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-reports-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize Tests"
+      id: integration_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        BUILD_LINK="[${VCS_COMMIT_ID}](https://github.com/reactive-firewall/multicast/commit/${VCS_COMMIT_ID})"
+        if [[ "${{ steps.integration_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n\n" "## :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for ${BUILD_LINK}" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n\n" "## :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`~" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Functional testing succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Functional testing failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Acceptance testing with \`pytest\` succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Acceptance testing with \`pytest\` failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Uploading integration testing reports artifact succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Uploading integration testing reports artifact failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Integrated Doctesting succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Integrated Doctesting failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        printf "\n%s\n\n" "<details><summary>Reporting Details</summary>" >> "$TESTS_STEP_SUMMARY"
+        printf "%s\n\n" "### :open_umbrella: Functional testing coverage reporting" >> "$TESTS_STEP_SUMMARY"
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to CodeCov succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-codecov-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to CodeCov failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to CodeCov was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to codeclimate succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-codeclimate-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to codeclimate failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to codeclimate was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to deepsource succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-deepsource-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to deepsource failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to deepsource was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        printf "\n%s\n\n" "</details>" >> "$TESTS_STEP_SUMMARY"
+        if [[ "${{ steps.integration-reports-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Uploading [integration coverage report artifact](${{ steps.integration-reports-upload.outputs.artifact-url }}) succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Uploading integration coverage report artifact failed" >> "$TESTS_STEP_SUMMARY"
+        fi
path: .github/workflows/Tests.yml
user: login: reactive-firewall
body: @coderabbitai please open a followup GHI titled "v2.1.x Chore - DRY up CI/CD summary code" to track this work on a separate branch.
created_at: 2025-05-17T05:00:15Z
author_association: COLLABORATOR
diff_hunk: @@ -956,6 +986,221 @@
         coveralls-token: ${{ github.server_url == 'https://github.com' && secrets.COVERALLS_REPO_TOKEN || '' }}
         codeclimate-token: ${{ github.server_url == 'https://github.com' && secrets.CODECLIMATE_REPO_TOKEN || '' }}
         cc-test-reporter-id: ${{ github.server_url == 'https://github.com' && secrets.CC_TEST_REPORTER_ID || '' }}
+    - name: "Generate Summary Filename"
+      id: output_integration_step_summary
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "integration-artifact-name=%s\n" multicast-integration-${VCS_COMMIT_ID}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "integration-artifact-name=%s" multicast-integration-${VCS_COMMIT_ID}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "TESTS_STEP_SUMMARY=Integration-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
+    - name: "Evaluate Integration Tests"
+      id: integration_tests
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-main.outcome }}" == "failure" ]] ; then
+            THE_RESULT="failure"
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-pytest.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            THE_RESULT="skipped"
+          fi
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          if [[ "${{ steps.integration-doctests.outcome }}" == "failure" ]] ; then
+            if [[ "${THE_RESULT}" == "failure" ]] ; then
+              THE_RESULT="failure"
+            else
+              if [[ "${THE_RESULT}" != "success" ]] ; then
+                THE_RESULT="failure"
+              else
+                THE_RESULT="neutral"
+              fi
+            fi
+          else
+            if [[ "${THE_RESULT}" != "failure" ]] ; then
+              if [[ "${THE_RESULT}" != "neutral" ]] ; then
+                THE_RESULT="skipped"
+              else
+                THE_RESULT="neutral"
+              fi
+            else
+              THE_RESULT="failure"
+            fi
+          fi
+        fi
+        printf "%s\n" "integration_test_outcome=${THE_RESULT}" >> "$GITHUB_OUTPUT"
+        if [[ "${THE_RESULT}" != "failure" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Evaluate Integration Tests"
+      id: integration_outcome
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ "${{ steps.integration_tests.outcome }}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${{ steps.integration-reports-upload.outcome }}" != "failure" && "${THE_RESULT}" == "success" ]] ; then
+          THE_RESULT="success"
+        else
+          THE_RESULT="failure"
+        fi
+        if [[ "${THE_RESULT}" == "success" ]] ; then
+          exit 0
+        else
+          exit 1
+        fi
+    - name: "Summarize Tests"
+      id: integration_report
+      if: ${{ always() }}
+      shell: bash
+      run: |
+        BUILD_LINK="[${VCS_COMMIT_ID}](https://github.com/reactive-firewall/multicast/commit/${VCS_COMMIT_ID})"
+        if [[ "${{ steps.integration_outcome.outcome }}" == "success" ]] ; then
+          printf "%s\n\n" "## :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for ${BUILD_LINK}" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :ballot_box_with_check: Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`" >> "$GITHUB_STEP_SUMMARY"
+        else
+          printf "%s\n\n" "## :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\` for \`${VCS_COMMIT_ID}\`~" > "$TESTS_STEP_SUMMARY"
+          printf "%s\n" " :x: ~Integration Acceptance Testing succeeded with python version \`${PYTHON_VERSION}\` on \`${{ runner.os }}\`~" >> "$GITHUB_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-main.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Functional testing succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Functional testing failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-pytest.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Acceptance testing with \`pytest\` succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Acceptance testing with \`pytest\` failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-codecov-results-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :ballot_box_with_check: Uploading integration testing reports artifact succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "    * :x: Uploading integration testing reports artifact failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        if [[ "${{ steps.integration-doctests.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Integrated Doctesting succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Integrated Doctesting failed" >> "$TESTS_STEP_SUMMARY"
+        fi
+        printf "\n%s\n\n" "<details><summary>Reporting Details</summary>" >> "$TESTS_STEP_SUMMARY"
+        printf "%s\n\n" "### :open_umbrella: Functional testing coverage reporting" >> "$TESTS_STEP_SUMMARY"
+        if [[ "${{ steps.integration-codecov-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to CodeCov succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-codecov-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to CodeCov failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to CodeCov was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        if [[ "${{ steps.integration-codeclimate-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to codeclimate succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-codeclimate-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to codeclimate failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to codeclimate was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        if [[ "${{ steps.integration-deepsource-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "    * :arrow_up: Uploading integration coverage report to deepsource succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          if [[ "${{ steps.integration-deepsource-upload.outcome }}" == "failed" ]] ; then
+            printf "%s\n" "    * :no_entry: Uploading integration coverage report to deepsource failed" >> "$TESTS_STEP_SUMMARY"
+          else
+            printf "%s\n" "    * :black_square_button: Uploading integration coverage report to deepsource was skipped" >> "$TESTS_STEP_SUMMARY"
+          fi
+        fi
+        printf "\n%s\n\n" "</details>" >> "$TESTS_STEP_SUMMARY"
+        if [[ "${{ steps.integration-reports-upload.outcome }}" == "success" ]] ; then
+          printf "%s\n" "  * :ballot_box_with_check: Uploading [integration coverage report artifact](${{ steps.integration-reports-upload.outputs.artifact-url }}) succeeded" >> "$TESTS_STEP_SUMMARY"
+        else
+          printf "%s\n" "  * :x: Uploading integration coverage report artifact failed" >> "$TESTS_STEP_SUMMARY"
+        fi
path: .github/workflows/Tests.yml
user: login: coderabbitai[bot]
body: <details>
<summary>🧩 Analysis chain</summary>

@reactive-firewall I've created a GitHub issue titled "v2.1.x Chore - DRY up CI/CD summary code" to track the refactoring work for the repetitive summary generation code. The issue includes details about the current pattern, proposed solutions, and implementation recommendations. It's assigned to you as requested.

---

🏁 Script executed:
```
#!/bin/bash
# Create a GitHub issue to track the DRY up work for CI/CD summary code

gh issue create \
  --title "v2.1.x Chore - DRY up CI/CD summary code" \
  --body "## Description

The current integration summary generation code in \`.github/workflows/Tests.yml\` contains repetitive patterns for success and failure messages with similar formatting logic, icons, and bullet points structures.

This issue tracks the work to refactor this code to reduce duplication and improve maintainability.

## Current Pattern

The code between lines ~1108-1170 in \`.github/workflows/Tests.yml\` repeatedly uses similar patterns:

1. Conditional checks for step outcomes
2. Formatted messages with icons (\`:ballot_box_with_check:\`, \`:x:\`, etc.)
3. Nested conditions for different statuses (success, failure, skipped)
4. Similar bullet point formatting

## Proposed Solution

Extract the repeated formatting logic into either:
1. A reusable shell function within the workflow
2. A separate script in the \`.github/actions/\` directory
3. A composite action that handles status reporting

The solution should accept parameters like:
- Step name
- Outcome status
- Message text
- URL (if applicable)

## Implementation Plan

This work should be done on a separate branch from the main development branch.

## Related PR
https://github.com/reactive-firewall/multicast/pull/402#discussion_r2093915566" \
  --assignee reactive-firewall
```

Length of output: 1378

---



</details>

@reactive-firewall I've successfully created the GitHub issue to track the DRY up work for CI/CD summary code. You can find it at: [Issue #403](https://github.com/reactive-firewall/multicast/issues/403).

The issue has been assigned to you and includes the description of the repetitive patterns in the integration summary generation code along with proposed solutions for refactoring.



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>

---

<!-- This is an auto-generated comment: tweet message by coderabbit.ai -->

If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=%40coderabbitai%20spotted%20repeated%20summary%20code%20in%20CI%2FCD%20workflows!%20Refactor%20with%20a%20reusable%20function%20to%20DRY%20up%20and%20boost%20maintainability.%20Cleaner%20code%2C%20easier%20updates!%20%F0%9F%A7%B9%F0%9F%9A%80%20Try%20%40coderabbitai%20now!&url=https%3A%2F%2Fgithub.com%2Freactive-firewall%2Fmulticast%2Fpull%2F402%23discussion_r2093915566)?

Thank you for using CodeRabbit!

<!-- end of auto-generated comment: tweet message by coderabbit.ai -->


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer><details>
<summary>🧩 Analysis chain</summary>

@reactive-firewall I've created a GitHub issue titled "v2.1.x Chore - DRY up CI/CD summary code" to track the refactoring work for the repetitive summary generation code. The issue includes details about the current pattern, proposed solutions, and implementation recommendations. It's assigned to you as requested.

---

🏁 Script executed:
```
#!/bin/bash
# Create a GitHub issue to track the DRY up work for CI/CD summary code

gh issue create \
  --title "v2.1.x Chore - DRY up CI/CD summary code" \
  --body "## Description

The current integration summary generation code in \`.github/workflows/Tests.yml\` contains repetitive patterns for success and failure messages with similar formatting logic, icons, and bullet points structures.

This issue tracks the work to refactor this code to reduce duplication and improve maintainability.

## Current Pattern

The code between lines ~1108-1170 in \`.github/workflows/Tests.yml\` repeatedly uses similar patterns:

1. Conditional checks for step outcomes
2. Formatted messages with icons (\`:ballot_box_with_check:\`, \`:x:\`, etc.)
3. Nested conditions for different statuses (success, failure, skipped)
4. Similar bullet point formatting

## Proposed Solution

Extract the repeated formatting logic into either:
1. A reusable shell function within the workflow
2. A separate script in the \`.github/actions/\` directory
3. A composite action that handles status reporting

The solution should accept parameters like:
- Step name
- Outcome status
- Message text
- URL (if applicable)

## Implementation Plan

This work should be done on a separate branch from the main development branch.

## Related PR
https://github.com/reactive-firewall/multicast/pull/402#discussion_r2093915566" \
  --assignee reactive-firewall
```

Length of output: 1378

---



</details>

@reactive-firewall I've successfully created the GitHub issue to track the DRY up work for CI/CD summary code. You can find it at: [Issue #403](https://github.com/reactive-firewall/multicast/issues/403).

The issue has been assigned to you and includes the description of the repetitive patterns in the integration summary generation code along with proposed solutions for refactoring.



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>

---

&lt;!-- This is an auto-generated comment: tweet message by coderabbit.ai --&gt;

If you found this review helpful, would you consider giving us a shout-out on [X](https://twitter.com/intent/tweet?related=CodeRabbitAI&text=%40coderabbitai%20spotted%20repeated%20summary%20code%20in%20CI%2FCD%20workflows!%20Refactor%20with%20a%20reusable%20function%20to%20DRY%20up%20and%20boost%20maintainability.%20Cleaner%20code%2C%20easier%20updates!%20%F0%9F%A7%B9%F0%9F%9A%80%20Try%20%40coderabbitai%20now!&url=https%3A%2F%2Fgithub.com%2Freactive-firewall%2Fmulticast%2Fpull%2F402%23discussion_r2093915566)?

Thank you for using CodeRabbit!

&lt;!-- end of auto-generated comment: tweet message by coderabbit.ai --&gt;

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T05:01:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,239 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -n $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "artifact-name=%s\n" multicast-integration-${BUILD_SHA}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "artifact-name=%s" multicast-integration-${BUILD_SHA}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
path: .github/actions/setup-py-reqs/action.yml
user: login: reactive-firewall
body: 🙅🏻 The current implementation is fine.
created_at: 2025-05-17T05:02:12Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,239 @@
+---
+name: 'Manage and install requirements'
+description: 'Performs steps to install from various requirement.txt files for the Multicast Project.'
+author: 'Mr. Walls'
+branding:
+  icon: 'download-cloud'
+  color: 'purple'
+inputs:
+  sha:
+    description: |
+      The commit to report dependencies for. Should already be cloned and checked-out beforehand.
+    required: true
+    default: ${{ github.server_url == 'https://github.com' && github.sha || 'HEAD' }}
+  token:
+    description: |
+      The token used to authenticate when fetching results from GitHub repositories.
+      When running this action on github.com, the default value is sufficient. When running on
+      GHES, you can pass a personal access token for github.com if you are experiencing
+      rate limiting.
+    default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
+    required: true
+  python-version:
+    description: |
+      The python version to use. The default is to use the value of the environment
+      variable 'PYTHON_VERSION'.
+    default: '3.12'
+    required: true
+outputs:
+  sha:
+    description: "The SHA of the commit checked-out"
+    value: ${{ steps.output_sha.outputs.sha || 'HEAD' }}
+  python-version:
+    description: "The python version that was used in the run"
+    value: ${{ steps.output_python.outputs.python-version || '' }}
+  deps_status:
+    description: "The outcome of evaluating the DEPs steps"
+    value: ${{ steps.deps_outcome.outcome || 'cancelled' }}
+  deps_build_status:
+    description: "The outcome of the requirements.txt install Group"
+    value: ${{ steps.install_build_requirements.outcome || 'cancelled' }}
+  deps_test_status:
+    description: "The outcome of the tests/requirements.txt install Group"
+    value: ${{ steps.install_test_requirements.outcome || 'cancelled' }}
+  deps_doc_status:
+    description: "The outcome of the docs/requirements.txt install Group"
+    value: ${{ steps.install_docs_requirements.outcome || 'cancelled' }}
+  artifact-name:
+    description: "The uploaded artifact-name"
+    value: ${{ steps.output_artifact_name.outputs.artifact-name }}
+  artifact-files:
+    description: "The uploaded artifact-files"
+    value: ${{ steps.output_artifact_files.outputs.files }}
+  artifact-id:
+    description: "The uploaded artifact-id"
+    value: ${{ steps.upload.outputs.artifact-id }}
+  artifact-url:
+    description: "The uploaded artifact-url"
+    value: ${{ steps.upload.outputs.artifact-url }}
+  artifact-digest:
+    description: "The uploaded artifact-digest"
+    value: ${{ steps.upload.outputs.artifact-digest }}
+
+runs:
+  using: composite
+  steps:
+    - name: "Calculate Commit SHA"
+      id: output_sha
+      shell: bash
+      run: |
+        printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
+        printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
+    - name: "Setup Python"
+      id: output_python
+      if: ${{ !cancelled() }}
+      env:
+        PYTHON_VERSION_INPUT: ${{ inputs.python-version }}
+      shell: bash
+      run: |
+        if [[ -n $PYTHON_VERSION_INPUT ]]; then
+          printf "python-version=%s\n" "${PYTHON_VERSION_INPUT}" >> "$GITHUB_OUTPUT"
+          PYTHON_VERSION=${PYTHON_VERSION_INPUT}
+        else
+          printf "python-version=%s\n" "${PYTHON_VERSION}" >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "PYTHON_VERSION=${PYTHON_VERSION}" >> "$GITHUB_ENV"
+    - name: "Prepare Artifact Name"
+      id: output_artifact_name
+      if: ${{ !cancelled() }}
+      shell: bash
+      run: |
+        if [[ ${{ runner.os }} != 'Windows' ]] ; then
+          printf "artifact-name=%s\n" multicast-integration-${BUILD_SHA}-part-$(uuidgen) >> "$GITHUB_OUTPUT"
+        else
+          printf "artifact-name=%s" multicast-integration-${BUILD_SHA}-part- >> "$GITHUB_OUTPUT"
+          printf "%04x%04x-%04x-%04x-%04x-%04x%04x%04x\n" $RANDOM $RANDOM $RANDOM $(($RANDOM & 0x0fff | 0x4000)) $(($RANDOM & 0x3fff | 0x8000)) $RANDOM $RANDOM $RANDOM >> "$GITHUB_OUTPUT"
+        fi
+        printf "%s\n" "DEPS_STEP_SUMMARY=Dependencies-Summary-Artifact-${{ runner.os }}-${PYTHON_VERSION}.txt" >> "$GITHUB_ENV"
path: .github/actions/setup-py-reqs/action.yml
user: login: coderabbitai[bot]
body: @reactive-firewall Understood. I'll respect your preference to keep the current implementation as is.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:90-97
Timestamp: 2025-05-17T05:02:42.826Z
Learning: Reactive-firewall prefers to maintain the original structure and approach in GitHub Action YAML files even when presented with alternative implementations that might improve readability, indicating a preference for consistency over refactoring.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@reactive-firewall Understood. I'll respect your preference to keep the current implementation as is.

---

<details>
<summary>✏️ Learnings added</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:90-97
Timestamp: 2025-05-17T05:02:42.826Z
Learning: Reactive-firewall prefers to maintain the original structure and approach in GitHub Action YAML files even when presented with alternative implementations that might improve readability, indicating a preference for consistency over refactoring.
```

> Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings).

</details>



---

<details>
<summary>🧠 Learnings used</summary>

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-09-19T03:43:24.037Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#115
File: multicast/hear.py:180-180
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers to re-use already loaded modules to keep memory overhead low when possible.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#379
File: .ast-grep/utils/python/structure/multicast-mtool-subclass-definitions/undecorated_function_definition.yml:8-12
Timestamp: 2025-04-23T04:07:24.393Z
Learning: Reactive-firewall follows the "Avoid Hasty Abstraction" principle, being cautious about changes that might introduce unnecessary abstractions or alter existing behavior, particularly in configuration files like ast-grep rule definitions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#139
File: tests/test_fuzz.py:73-73
Timestamp: 2024-10-08T21:59:27.171Z
Learning: Reactive-firewall prefers not to introduce new dependencies into the codebase when writing test functions.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#402
File: .github/actions/setup-py-reqs/action.yml:79-85
Timestamp: 2025-05-17T02:33:33.400Z
Learning: Reactive-firewall prefers to maintain the original structure of conditional statements when fixing logic errors in GitHub Action YAML files, and relies on environment variables with proper defaults rather than dynamic fallbacks when handling input parameters.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#235
File: .github/workflows/makefile-lint.yml:41-52
Timestamp: 2024-12-06T08:21:21.876Z
Learning: Reactive-firewall prefers to suppress errors in `apt-get install` commands when individual checks of the installed packages are performed afterwards, to allow for more granular error handling.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#118
File: tests/check_pip:92-197
Timestamp: 2024-10-08T21:59:30.537Z
Learning: Reactive-firewall prefers defining functions before they are called in Bash scripts to avoid errors due to Bash's sequential interpretation.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#392
File: multicast/send.py:312-320
Timestamp: 2025-05-05T20:10:48.364Z
Learning: Reactive-firewall prefers simpler implementations that maintain a component's single responsibility (like argparse), even when it means not explicitly handling all edge cases such as mutual exclusivity of command-line arguments.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#373
File: docs/utils.py:30-39
Timestamp: 2025-04-21T23:37:00.037Z
Learning: Reactive-firewall prefers explicit domain allowlists (adding specific domains/subdomains individually) over pattern-based domain validation for security reasons, following the "Avoid Hasty Abstraction" principle for security implementations.
```

---

```
Learnt from: reactive-firewall
PR: reactive-firewall/multicast#184
File: tests/test_hear_keyboard_interrupt.py:70-70
Timestamp: 2024-11-14T02:25:25.684Z
Learning: Reactive-firewall prefers to include suggested code changes or fixes in the issue's description when requested.
```

</details>

</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-17T05:02:44Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-17T01:37:34Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This set of changes introduces a new composite GitHub Action for Python dependency management, refactors and enhances the CI workflows for documentation and testing, and updates the Makefile for improved Python version handling and build artifact management. The workflows now feature improved artifact handling, step summaries, and conditional logic to tightly coordinate build, test, and documentation pipelines.

## Changes

| File(s)                                                                                     | Change Summary                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
|---------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| .github/actions/setup-py-reqs/action.yml                                                    | Added a new composite GitHub Action for managing and installing Python requirements, with configurable inputs, outputs, and detailed step logic for environment setup, dependency installation, artifact handling, and cleanup.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| .github/workflows/CI-DOCS.yml                                                               | Refactored the documentation workflow to trigger on completion of the "CI-MATs" workflow, added jobs for checking MATs status, summarizing documentation results, posting commit comments, and improved artifact and environment handling. Modified job dependencies and artifact management for better integration with the CI pipeline.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| .github/workflows/Tests.yml                                                                 | Overhauled the test workflow: introduced explicit dependency installation steps, improved artifact handling, added jobs for summarizing and reporting integration test results, enhanced outcome aggregation and step summaries, and fixed minor issues in step naming and permissions. Expanded the INTEGRATION job with detailed outputs and evaluation logic.                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| Makefile                                                                                    | Added support for configurable Python version via `PYTHON_VERSION`, adjusted targets to depend on new `./dist` marker, updated exclusion patterns in `MANIFEST.in`, and simplified the `user-install` target to install only the built wheel from the `dist` directory.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| .github/actions/run-minimal-acceptance-tests/action.yml                                    | Fixed logic for setting Python version output and environment variable to use input value only if explicitly provided, otherwise fallback to existing environment variable.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| tests/check_spelling                                                                        | Added a new specific typo pair "compleate:complete" to the known typos array for regression testing in spell check.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant GH as GitHub
    participant BUILD as CI-BUILD
    participant MATs as CI-MATs
    participant TESTS as CI-Tests
    participant DOCS as CI-DOCs

    GH->>BUILD: Trigger build workflow
    BUILD->>GH: Upload build artifact (.whl)
    GH->>MATs: Trigger MATs workflow
    MATs->>GH: Download build artifact
    MATs->>GH: Upload MATs summary artifact
    GH->>TESTS: Trigger Tests workflow
    TESTS->>GH: Download build and MATs artifacts
    TESTS->>TESTS: Run dependency install (setup-py-reqs)
    TESTS->>TESTS: Run tests & generate summaries
    TESTS->>GH: Upload test artifacts & summaries
    GH->>DOCS: Trigger Docs workflow (on MATs completion)
    DOCS->>GH: Download build and MATs artifacts
    DOCS->>DOCS: Run dependency install (setup-py-reqs)
    DOCS->>DOCS: Build docs & generate summaries
    DOCS->>GH: Upload docs artifacts & summaries
```

## Assessment against linked issues

| Objective                                                                                                                        | Addressed | Explanation                                                                                                               |
|----------------------------------------------------------------------------------------------------------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------|
| Decoupling and proper triggering of CI-Test, CI-Docs, and CI-MATs workflows (#338)                                               | ✅        |                                                                                                                           |
| Use of build artifacts and environment consistency across workflows (#338)                                                        | ✅        |                                                                                                                           |
| Improved CI/CD result summaries and commit comments for test and documentation outcomes (#338)                                   | ✅        |                                                                                                                           |
| Comments on GitHub PRs when relevant (#338)                                                                                      | ❌        | No evidence of PR comment posting in the provided changes; only commit comments are implemented.                          |
| CD-DOCs using the same environment as CI-DOCs (#338)                                                                             | ❓        | CD-DOCs workflow is not present or modified in this set of changes; not possible to verify from the provided information. |

## Suggested labels

`Python Lang`

## Poem

> In the warren of CI, the rabbits convene,  
> With wheels and docs, their code is so clean.  
> Artifacts hop from job to job,  
> Each summary written by a diligent mob.  
> With dependencies managed and tests all in sync,  
> This release is more robust than you think!  
> 🐇✨

<!-- walkthrough_end -->

<!-- announcements_start -->

> [!NOTE]
> <details>
> <summary>⚡️ AI Code Reviews for VS Code, Cursor, Windsurf</summary>
> 
> CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
> Learn more [here](http://coderabbit.ai/ide).
> 
> </details>

---

> [!NOTE]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpETZWaCrKNwSPbABsvkCiQBHbGlcSHFcLzpIACIbfGwMelwAd3x+ADNIAGEASQB6LIARSBzmXnwpNgxcRAAaaPtsAWZ1Gno5MNgPbERKPxI0MUkSMHT4f2S0H3RkW0gMRwE+gBYABgAmWsh0/AYe6X4sMlhMBngMIk6PJmrz7Hjkc5oiKnF8LEx6G/EFh8glbhefCyKqhAAUuQKhQAlJBUhQANbpIHJZA7Pi4Lo8Cj4ERiDQwBDIbDcWjUa5A3qPRAODxmADM9IAHBojABpEjyBgnC4Hc4MLzYJSQZiKeBjBjUeDvZAEK6QAAGGiI6lgTTy8KRKMQBRyYEKAHksgBlDQgrwK7bwSJhNLwMo4qT/XaOdhS96QUjkV7SrDJVXneWQoo8eDcEhec4kAkAQXmJGSkAA4uoABJNSAxoYek4yEhkdC0JT0CTwNCK5Wq9WDN4YHW9XAksDcWRgfwBHU131m5gW22QHm0G1WWSYj3cMMoOu4KZed11kX4fyQEjpdKicRSLzyWjYCjnS7B4oUBKIVkGdwVlWY9Wa5H4VF5aAhM/my13lEDtB5gsksltftylLYV7SAqIHCcFx+m4JcfkudFsnyEMaEQGotieEgXnJdB40TFNcHTARM2zBcaDKOcaC2T4pwFIUPH8CiolAx0SFBM9MyLdRfVnWQtkxDwAFk0ARVdrQ8XNICWAs0FoIQegAuVmGEjx+Mk7BrSSZxSFCSIaWxEZWO4TcSCooELjhVV+H4vgGPJL4eVIM83CxbhvF8dtglQ9AvEQO1qhxXcGAOctyETXIwhCA9/hIcNEjIBh5Cw7hYE6ah+DwSNyFlLF70TaiATIJQMDOA4lhSfMsAkZxpR6RC4SXLUH2QajnHEdIazqGjBVoKKBHUrx6Fa8UOr4kJ0AoNqRvQRJnT2UF53GyaxCcgwDSkKgfD4olPGmDyxqeALsCC5BmG8cRAQ8ZiKlY9hmvtKI0v8MYMCi1S0DwFgFuohiyzUSNcHkfBMlU8o8VwAByZAj2xXZpCpc8LGyFg2MaSDXAvLF3m3BRWHYQ5OlQVzdsCTzQlQdIcWYeV9hsgYhikUZxgTWctmSWA0hnIhSCSLEacVJglCoVR1G0d9LNUtgaTQUgYgAAQF0QKjAbQ2xIUsEz6fx1eSDQGncZdnA8DA0nSPdrJxtith6xA9hpX1OqXbZ81oARBgRGHgKif1MUDVS5iYXHqmQXoSPPfRjHAKBCoyHACGIMhlAAgPQS4Xh+GEDdhhkLlFGUYXNG0XQwEMEwoDgVBUEwWPCC9ROomT9guCoRMIKUqCOgVoW1ALnRw4j0wDErG8BDyLsZTyBsmxbVWO1H0PzQ4AxomXgxEZjPVa9ecDHDbwHMm5TBHOc1BQuTNMMyzWt5jQNh6GiISMGljxqPOVDZ36IImbYhp3oIJSUPlK/GcPgFpA2sKOdmWACpxWKvAA4CFVICTOvASUXkrA4jBpJeQ5RjqICiqdLw50bQeS/rdK0ukCQ5FCIMIKRlHgYFcjUbYjtVLJ3UJAY0qYYxUTwF0W4kor4EBEhgKiM0RxjkqpQPB7xWaWSUO1M6MhvxRA9KpfChEVwYFLDiDAoICSXjHlgeIuBGEnRIDOf85Z+TdVeliNhoROHcPARIyA61pFYH2LQK2MVCrxXkEA2cC036NipMwvgfUNKjVQqI+gtAXTzSviQ/wltpqDQmsNMQ0UZzWmDkdFK35r5sC2GMXSWwciFC2AAVRsAAGRif8eAjlNDOWfiRPwp4Zg4QDjBPBNB6qIlyhZTE8odg+AfFFES8hUIxUQIvAwUAqGMCmHsRizUZoNmytcZG7DHGdIEPgYZVdjGMNSZo7R7xQSuOqioSIrIFmhA2ZAEk8pxGQNcVI30ZzxgXLxlVfcNyTLRQUYQ16HMsTnBOY7EgAAPJAcEvk6MuX836tz5klFCLwGKhtmpPJekEZ+6T2qZMfmwJ5eDzKsO2Q4rhpzyyVMqeUqisl5JRQQgAdXOHE1E/A+DGwwGADliQmrtIwN6Jy9ypxvx8DIfqXiIrRNOXEuabor7QKKiVbOU4JD4ARFFISIkSkqS0uY5AYIFTnHUAqLYCoUK4BnogK1iolWIHtQqaEWwXjxAnOZIERA0SOwFNVAGdz0UriqoKckmz+DrXfmqvxkrgEUU+cYgOHgO5dAYLqilWIHAMFwTy7Y2hBTLjAXTFKASQFX2mdwU5IN/C9GKh4MBEttBYCSTdIOGhcDQtCIa7xNAKAtBeuZcsz0pj2BnCEmOubcHFKLXuQFjtEC6u4OGWgIbFmb0jThVuzh5D+BghNGOqk43FX8dOQJiTpCKPQsVGx5kZ1wwLe1a0C6pw9QEUuNZ9BMoIllGC+iEY1aYFCO2lGhrmqhFUogcMZwxj1ypRwrh9TMDG0nQcNR58iLVtRrvdAealw9QuNuDdoQmA+A3MgLdAFd1QQgyKag3Iorlm4NQAdIi4TOAXOKeY7wCUeB2AkOVoopCbKpk8NI5ZiwoLsg0/wYgly8VOZi1j9ad2saCmAXoqnZORi8mA+jBTjl4FI08wE+AZJRvI5EMQ280bkOCji7p9behpKWqEHotiPAKkMTqEkQIZLK0JTWS0hjZHDMoDiPgg5MqXB48bBzzVlyCcSKZ8MFB0TMGQAKAYCwa3NsMkuPdiX0DpAHY0PNcNTa+Edi+yI9ATx1i2MkioXm5MbkUwoaora2u0fkBB88l5vg4l8IM6xdFsvvB6rWcdMLRB4E+XKGL1xTgRiTTIirs7Tl1bfcE6QWwyAOH3OZco6X7Ak3ilFMBFb1scYPbBA8VFguZJi4905OXMDPOrexAxbT9jBy6NMG2+4jJRRhTQOswxsYITIOc3ReNJ7cC2ME2qwGI21mKWJL8iRYv1OM72pc/84LnnMJYGMhDE7237Ce0Qc4fQyhjjCw9AFHauQEJGBgmjwhwMQEYKAAA5BMZ8CIXzaUoQN/h6CBiVNeNUI9fMT3MVPVs7ZOzz17GLYZEK8CzIMJAXQipEAnEtGCVCx2iDNZJkzOV8j3qEK4HsCg/hqgWx2TSx2qYACiMYYR64NzanVZATdm7e+2m3q47ecGFxooRBYoVlABtCP3UAFQtgkWANxvpg+4HN5bz+kvvHAqj+DekGgACM6xwZJ6gAaPApjooS7oIvfXKejdoBN/YpDcZuSiBEvQYxSeW+KjT5AjPHz3gm9eR6TPHpPGD/9wCRAAB9FHDrIBgmuhtXwp6EoJsvcmvAqb58p8X0viJA0V+Tp6Cb8/DWrfJLITd0Bh+WAkGP06mZS/bWX+oNf9ftqP51IH8g499K0D9cAj9k8P9uBl8lUf8QkTclVXRusr188O0mEn8r4U1X938fNns7USUSATdCCY5/MLNixFoMlcBcChoiU7UIMTc9NQgwEyCZIHp8DEsaD8CwB4BaATdWCKDaCawShfch88D3MwA9w+wwQBD2D3NIBqkakuCJCeoml+DzM2C3MqCGkmlq8kYyh8Bel6IEgJ0ZkgUox6B0Rm8DcshENdlJQvAVl5woCp9JEKB3FztGxuAoCYwOCSCVNnBnCh8AAhWVKJXAepJAhJT5HfHnUA27KAwoHxGBXfbA0lNHbAIIg3JI2KdVc9KVW7XDYrajX0KA40HeYrejazTOD0aiMgV0enDAHwjggQqArISIT7fLLAR9PSaiHbfwJeFeeZAeIeOXDUBqXKHUXIfUI0U0BeQY6IVeMnDeBOLeegPrGOA+XkXnDGDwD8B8MIfcLmPoSYbLByKICmFgfoGDKbUFTwI3YKGaImdyC7VCZAD0GDUQcUFBSSKgYqLob9HgagWAf9Q4xpUgc3fGbpSILA4GLEaIaYgSGMaARABofYxMRrWMXCKcLicdIQQQfmDNBEJff+NfU4wsCguUJQAdIdS6OEjwKIlVT5fE7DdmbwBrEw12VzfGaDI6fNZtLEHPcEygKKdEkVfRbaFkp2CAgErJItKIW/U5JElEkUcxGSagcsIQ5abYSmeUBEvUZU1E/pRqDEhIZHE1dKExHXIZFKH2MxCxDU+pfFTyHCdRDMHvTNMJWaZAydRbSKC4QbLEGFOFKKBUQ0E0S0KU8k0UHqeDJININVfGBUD04k0k0LGaLGfdEwnjZMokkk6gNfTlGTABdhI3eIAacU0NY2RMf7eURU3ZaiNgB0mcHUq43M3vfMmoS0BCFM4xU5WHb5eHF3ZFAFH7OxIkvsnDckg9OcIKegb2fJRgeSK4wxL03svAU5fwRUzzbNDwT4uDH4xxCUhk+JJkj0RU77OESgQDJcIgTAeAAALyiEUmuk9FWNk2dSnDlHLDNyOkbEl3awU3blXCXG6A0KI0uAKSri1NCEIPnPFixHrJpTqK0UHMuXOB2FjE4hmxqzr2tOSGvIpOfLSCZ0MJPOVRQM+UVPrUUVpQ4IwvwEG1SGxJZOQAIoNiLCb0VHDONCX2NEqQEiRJsAAE10z6AwzZil8bBPcrADQbBoAlRuLJL+LBKYwRLLRGtmoys+h2zM1Oy19qIJKIyUBMg0MllG0KNBoZoeNGTKKPQSiPRySzLJQLL6tKFQguUMAAtaBmpphbLfTaj8DOpqNgoiioJV8HNJJlF+8sAmAY0ZY0jAUBDspUANiWo1Iccoh/Kvp8D6loTzEMMsQ3SiIUybSRlzhx0IrqI+sCQjLeLpLZL5KNKOk0BtK+BdLUyCyxKlKTQ+KBKhLRKrYHwvLyCo00rcrlNDCmFyxO8G4XcFz5Rsqq0KioJVEsQGJgMXd7FzwrBKAWg7YGd2KPAmcOd1BsZxc6cLioVBgUoWTC9I87i+UPAiAgRXYfBZBjyEUfkXdohChTy7KMA0SCkGwvT35WLPqxTqywhGlYAIhz1ngt42KEKPB9SwBDS0SJjPxGstgdy4smF8dQTht8Bt9/qAqsBbVmMZp7t0kAzSdMwKdGjQSacJd5x3jMhSKJoVE+A2cOcucuJpA+dIAAApAkmSYsLgDq/Sy0aXUY28TGpqXUGYk0HsC0NFEWoiGM74riuq6WrAGXKsEedEqYvUHilWy0QAFAIiLYlkj1UectgCaDtULEVflrl2d9t3tzj1iaAYC1yJyNyWoODXsLg1bRbOLaAJaeK+rVL1KpwrwDbxiBltRFbTa3wQ6iIxbtbI6Gq5KFLY79bh4E6TTjala5iNcFi+cRjZc5bE6Fbnw3iVbF5l5Fi14VjvRZMNiwEtij5di6oxT86xijanwXwzbONkBjhVt4LhlegY1RsEgSJx1qJbz7yHz5xx0/xI05koAYww6P9gcwxaxuqFRGswBCDLQmz1SWy5RVIxSug2CKAQ0bAyAb4HppgpTLzMVSwHhsY5wlh6sYgsg/bQMYpDD1BOsEJ0b+wETAHoIQGCA6NHY66agGhHYoHe8+z7tekwHHZjQAZIgGgey6d1APq0Uch/JFAjoogTqUF2Ed98jE0glvbiRyVIKlzUI2zEdmwVdAgDK2lfYsQFQsgDQAA1T3GwGMJMT3R1Iy6AT3Y0aAY0R1QynIfnGRpMMR6AHIA0fnSMwQTqGcwYfBT7cdR2fa5h0MGtG7C2T4cVSAAAMXgGhSiFTGgAEhqTCv60JzY16hzid0znMgVGAGpKLUQD0GAAnhWtkD0EtDlACaCZyVCb6yidjriuUBlnyl2FtVyXs2+xDVsN8dsxLFdptBIMDBSaoBlg2MNQUAozaUuKpgVGVN4uVKyFTCXysGRJkZsG0f7AEeEaX2adafaegE6e0YftYmujv13ESBA0JN71mThH3BoEtHS1Mc+TqflF6ZEbEYkajoGp0YEA3XJv4cEa2fEc912bUtEsgDuv6DgupnAtMJrXWeiEqQecNPcYaDlBeYeZOdEbOY+c3PGakB5gEwqt8GKsYCJJxguirW9pDUvAVGUdUfUc0e6ajOBsaReglBA2xnHsbXDp8J3oISISbTwtCBHLduyzQCMj3Cijib/sSrZsaAEC00YfXzTxCCGtszeOKTnpwvlTQlOWRT+AEMecQGhFZCH0fsBEGCiCUgWHHQnAsYvWlTKtUgVA4enlV1C1DigMfpEyiExTAA+w+CeP8DAAvMYclYN23ooPpcofDUyNhbMLNQwiwlrC/xfEPrdcaKX0SrdVSmoS5n8DvL6WJbDBtAAOolFcZa/MkytEfl8FYxpDyDq2uLOjKoVfxcgF9R+IQh6M6n6MBXIDwA2ntr4GXTDDXQnUjWta3p3pmpYExT4TwSdA2JwxKJHTlLEnoDbgRE8pgaPQWoLdTfnWXCLM/XcK9NNmKn5cya2A5YVSVXndOVFZycJYoMvLlGqMyR9aCQicSy2CYBbCuCpm/L1s9wAA1oAxGFHAK4GlNo2Hn+IqYoKgqyqEh4B8VClpBDmc9yG5ywhmLT5WLrCU8kXPc1HkTUWLn1KuBPLvL6EEb937MYLOpukxInMWA1ByB1iD25qIizNEOUBqE1lKC6C8qm2YTCqPAIXSqFrVIx1fA93BExpEq63FQIOoONGtGpKZKc6FR4PhriPVIWPPlxr5DqIekMDSOulEMCOeT1qgMqotqqUQ1t65JpkvaYoRDASSUoobg8Fpkz18McQ9Jwa0V9WJn05fJqOC1JchMZnLzbIFI0h3mNjRXqJ8rawQ0BJzhasHGMM0gcNylASbhpsqc5RDs31Ts+g5s9gr5BkA75Cg6iBzw1plBNorhehIXD5goixu2/6xPVExpqa4Int5D5Wn5QR7aX9SVpYXhMJ5x6kronRaGGNH5SBLlqJ9PzJDO4V41BgzOo1wp0SSclj6aB1WbqcsQLrAjawmWOaWduamheb2B+adioB1bZm9K0ym4n7b5HmRDFR8d9Kl8Uyl9eDLRAAkwhO7Jc9bePO7zKu5DW282b+YkcE6tqO/NRVa8GNc3yfjAEX34NCQ1aV24E4ddXw1rAlbTp6pkbkYUa4Azu05rV+4KOB4yZfGB5mVB4OHB68Kh+1Zh99Dh624JIVDkeEpqUkf27uZw1QczXQeAcwfgb4Agdu6Z4RBZ56VAfZ44VwZIGiAAG5vucMMfE1ceYD8fkBCfldofDFyfhbKeuOUWtHBON25XkELpLSTkKXdJrCxDiuMA/W6uiC/djfqhMJfXv9/XLf/cTel9F3cAzeIDX8FQHeU8nfl2Qg3fU1Pf9crfkOPWZ2SJ/ePevfFQneBDzvc44qHvXf7eg/Hfrf3XfQl9Y+FYE+ymn4I+2BA+g/ve0/fWs/4/Ix/4SB8+LeU/i+Q+M/Y+lAZl4gKAgpq/C/g+bf5xM/wKl8YL2+o/fv6/3g+/8DM+KBVba/o+S/u/++rvB+nf+/VCQhC/63N3vbp/MeQf19az5fIetXuGdXYeOPbXwI2WFrQuJaTfOHbUpHr/fe3i7+Z/awwAlJzgn/h/+Vs+lYBCP+u+X+yuLqX/tamv7Z8K+5ISQuBT/7p93guPZvnuE0zADp+n/AHuLiVg0VCEQAqAdalcgUBSAPBZ/r6DAC2piB+AYmg6mtSncne1aFfBE2gG28vWIAwgSP39ZMDP+S+MrlI1O59Yl8DBa1L/3U470QOqvFRpB3V785YOVzYdowzA6Kgyu8Ba/FAQVACECBKAvrKv35hUcCqifB1GilP70BhBRERFqIO44wds6TVMqt9lkEKgEO5BVQf/yIHqClBoAqlAD0Di4BPeTdCumACMD6pRIkQRuivBbrxw26NGA9p3XOI7EEWSJfnDkFsayNoAGgd/mEGNShByS69VziuGhS0RhQYtLiO8HHT4RVYjESwph3Xz50V8K6GpHCikZDw2M+4PqChFqHXgYy3gaQAGxajTB6M/8JjLuSBK4B2MioAAFQaAbg6QRSgixuzRNUhkMaKLkXjTkku6FxXUgqFvzRN42p8ZKO8HkAzg8B5iCsHkGtgeDPqp8JUIcJqEpC9hHlG2u8T1prDTkeCciPIEmDqBOoXYEdDij7Z9AEEiFWVHrxMyEhvMNMAgQUWmFXDR6i4WMnAnjJzDo4HoM4UcN1rTIZIMcVYbKm6rklHhgILWjCMzLxF5QbMfMKNl1LqtER97TrLjRwjAjIgW4cxvETF4f0aoyAJVvESZb7lvinODTAiCfiAkwMZCdZuWBax9JFCV5ZcC1mBYIwycDNablfVm6055uVOUtNCmZxc1PA7OH4ut3EAC00U0AVIZv0TSWg8ERAR+P+WuCe1Wy9TG7FwAtShB7hMTK0TiVCAaBzhqET3gLiFy7DtIVtCWs6KOFcA1hOovUcoN6AUAQRBo+wJi1/zLglhlhFYcCIdF2i0gwYygGGNnBcBfRNQ8usMR8GDwq68uEiDqGPpDp7QUwZWJViMirZiBL4OeD53mJeDghIVPDvZgiF5cohdiW4vyz4Yo1jQEPZxJAgaBTkCkMY/sKVR4yicGEG5A3t5isDCVoAqYXjls2NAwdlGVgSpLnRPiwDDIAMcoSfQDZAIBg/edmgnnkBmowAD5N1ASDZR8JFQM4ucQuNEZLjeOK4tcdLWQB8owAW4pTNBgYAg4HkFpVSPjmHwQJYBM+DAN1VUgDlnaw5IptONnHziJBi41FusIJj0J9eUwYIJQnpJTgTkqAT8ehF7SzglEnpOUJSIgmwpUIoZW8fBKXyISNeVyf5G7QlKoAlh/QNxDRy6wRcPQRNHwKKQQDcg+x0+cfFgFQCeJTk+OR2kdjaza5yW6Ey6LcOxiiTCRRwZUadThoexeCdASUZN0pwM5ZRDJeUYzUZzKjYIqonmhqNuBajNukAfnGkCWFsVCKSkYUHpIbx05puSolUf3hW7qjOcmouInw3JhiRWQXg7MUYEyZ5ALunxHiRcECHN1liIQuuE2LwwtjtiRgOMKfHZESgwgsgGCECXGAxB8q5IDgN52F4QjUeM3bzMaCsCe5cgtjHIFkCXzQBhKslO9s4CoBKY2YKCctEwyuq0xGuB1cmv6UuAIhqy3RcMFFMuCRYv0sdSlEoC5LRhCQuEntIVCjRMEY4JwCgLQAVhJBsphhQNvKD3pGQsh2Is4GpJTL+o+AgYejLuEhLQYxp/3FMlFBwRwwCQNkqyF0D4B2Typ9gH8fvUACYBMgFzYMADsTuR2Kl3LZdZ/2o2T8EdQYxKBxua8aUQty+lzdDJ7kkyZ5LVFrcLJPOQWq9M+lRdjJnNDGWZJ8kWSdwBk1mkFKGJ9xS4miQ8dXHilrELYjcPwGgBbgHsO4ucLuOoC0C9xi4BgWmfYku4+UOBasOBARVoA/4j0NMyOP8AYC0BVgAATgYDLAAArPSAEBMh6QkodqNrIECMgy8AANg1kkB6QtAJkKsDLyqyBAAAdlWCGzFZ6wJkJkHDi0zaAhspQDbMVmrABAkoZYJVkGDpAmQ/s2gGXjLxezFZisugLQHVkCBlgZeBgO1Btkuz+ZtM+kKrKtk2z6QhstADbPWCKyHZNstACQATmqzVZ6wAQOsHdmKz0g9IEgHnIECKyjZAgI2QwCZBFwS4ss1WcnLLmOybZhs1YD7PSBGzVgqs+WYbMNnWy7Zoc3OekDWCqy6AickgKrPLAyyIAruV3rwWXxaxxZdAJfNHH0BAA=== -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

<details open="true">
<summary>🧪 Generate Unit Tests</summary>

- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Create PR with Unit Tests
- [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Commit Unit Tests in branch `patch-ci-338`
- [ ] <!-- {"checkboxId": "07f1e7d6-8a8e-4e23-9900-8731c2c87f58", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Post Copyable Unit Tests in Comment

</details>

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=reactive-firewall/multicast&utm_content=402):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai generate unit tests` to generate unit tests for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: deepsource-io[bot]
created_at: 2025-05-17T01:37:40Z
body: <div><p>Here's the code health analysis summary for commits <code>161dc6f..57f5592</code>. <a href="https://app.deepsource.com/gh/reactive-firewall/multicast/run/ae9e2b3f-8b8a-4b3d-a942-4a71cf6ba340/">View details on DeepSource</a>&nbsp;↗.</p><h3>Analysis Summary</h3><table><thead><tr><th>Analyzer</th><th>Status</th><th>Summary</th><th>Link</th></tr></thead><tbody><tr><td><img src="https://static.deepsource.com/analyzer_logos/python.svg" alt="DeepSource Python Logo" width="16px" height="16px"/><strong>Python</strong></td><td><span>✅&nbsp;</span><span>Success</span></td><td></td><td><a href="https://app.deepsource.com/gh/reactive-firewall/multicast/run/ae9e2b3f-8b8a-4b3d-a942-4a71cf6ba340/python/">View Check</a>&nbsp;↗</td></tr><tr><td><img src="https://static.deepsource.com/analyzer_logos/test-coverage.svg" alt="DeepSource Test coverage Logo" width="16px" height="16px"/><strong>Test coverage</strong></td><td><span>✅&nbsp;</span><span>Success</span></td><td></td><td><a href="https://app.deepsource.com/gh/reactive-firewall/multicast/run/ae9e2b3f-8b8a-4b3d-a942-4a71cf6ba340/test-coverage/">View Check</a>&nbsp;↗</td></tr></tbody></table><h3>Code Coverage Report</h3><table><thead><tr><th>Metric</th><th>Aggregate</th><th>Python</th></tr></thead><tbody><tr><td><strong>Branch Coverage</strong></td><td><span>92.2%</span></td><td><span>92.2%</span></td></tr><tr><td><strong>Composite Coverage</strong></td><td><span>96.5%</span></td><td><span>96.5%</span></td></tr><tr><td><strong>Line Coverage</strong></td><td><span>96.8%</span><span>,&nbsp;✅ Above Threshold</span></td><td><span>96.8%</span><span>,&nbsp;✅ Above Threshold</span></td></tr></tbody></table><hr/><blockquote><div>💡 If you’re a repository administrator, you can configure the quality gates from the <a href="https://app.deepsource.com/gh/reactive-firewall/multicast/settings/reporting">settings</a>.</div></blockquote></div>

author_association: NONE
user: login: codecov[bot]
created_at: 2025-05-17T01:56:09Z
body: ## [Codecov](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 95.203%. Comparing base [(`161dc6f`)](https://app.codecov.io/gh/reactive-firewall/multicast/commit/161dc6f3bec9ba1643c50edd44e9943b011b85b3?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) to head [(`57f5592`)](https://app.codecov.io/gh/reactive-firewall/multicast/commit/57f55927600bf1605cd665b70d1a7f405edcfe5a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls).
> Report is 7 commits behind head on master.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/graphs/tree.svg?width=650&height=150&src=pr&token=UDKPGQLA11&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls)](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls)

```diff
@@            Coverage Diff            @@
##            master      #402   +/-   ##
=========================================
  Coverage   95.203%   95.203%           
=========================================
  Files           27        27           
  Lines         2189      2189           
  Branches       129       129           
=========================================
  Hits          2084      2084           
  Misses          66        66           
  Partials        39        39           
```

| [Flag](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | Coverage Δ | |
|---|---|---|
| [3.10](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `1.347% <ø> (ø)` | |
| [3.11](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `1.347% <ø> (ø)` | |
| [3.12](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `1.347% <ø> (ø)` | |
| [3.13](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `1.347% <ø> (ø)` | |
| [doctests](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `28.369% <ø> (ø)` | |
| [macos-latest](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `1.347% <ø> (ø)` | |
| [multicast](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `99.401% <ø> (ø)` | |
| [ubuntu-latest](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `1.347% <ø> (ø)` | |
| [unittests](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls) | `95.203% <ø> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls#carryforward-flags-in-the-pull-request-comment) to find out more.

------

[Continue to review full report in Codecov by Sentry](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402?dropdown=coverage&src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls). Last update [161dc6f...57f5592](https://app.codecov.io/gh/reactive-firewall/multicast/pull/402?dropdown=coverage&src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Mr.+Walls).

</details>
author_association: NONE
user: login: reactive-firewall
created_at: 2025-05-17T02:52:26Z
body: @codecov-ai-reviewer review
author_association: COLLABORATOR
user: login: ghost
created_at: 2025-05-17T02:52:31Z
body: On it! We are reviewing the PR and will provide feedback shortly.
author_association: NONE
user: login: ghost
created_at: 2025-05-17T02:56:01Z
body: ## PR Description

This pull request aims to improve the reliability and maintainability of the Multicast project's CI/CD pipeline by introducing a dedicated GitHub Action for managing Python dependencies and standardizing the workflow for documentation and integration testing.

<details>
<summary><b>Click to see more</b></summary>

### Key Technical Changes
The key technical changes include: 1) Creation of a composite GitHub Action (`setup-py-reqs`) to encapsulate the logic for installing Python dependencies from various `requirements.txt` files. This action handles Python version selection and artifact naming. 2) Refactoring the CI-DOCS workflow to depend on the successful completion of the CI-MATs workflow, ensuring that documentation builds are triggered only after core checks have passed. This includes fetching artifacts from the CI-MATs workflow to obtain build information. 3) Modifying the Tests workflow to utilize the new `setup-py-reqs` action for dependency installation, streamlining the setup process. 4) Enhancing reporting and artifact handling in both CI-DOCS and Tests workflows, providing more detailed summaries and improving the organization of generated artifacts. 5) Minor Makefile adjustments to improve dependency management and exclude unnecessary files from the distribution.

### Architecture Decisions
The architectural decisions include: 1) Adopting a composite GitHub Action to promote reusability and reduce redundancy in workflow configurations. 2) Implementing a workflow dependency model to ensure a logical sequence of CI/CD steps, where documentation and integration tests are triggered only after core checks have passed. 3) Standardizing artifact naming and upload procedures to facilitate easier tracking and retrieval of build outputs. 4) Using sparse-checkout to reduce the size of the checkout and improve performance.

### Dependencies and Interactions
This pull request introduces a dependency on the CI-MATs workflow for CI-DOCS. It interacts with the `actions/checkout`, `actions/setup-python`, and `actions/upload-artifact` GitHub Actions. It also relies on the `gh` CLI tool for fetching workflow run information. The changes affect the Makefile, potentially impacting the build and installation process.

### Risk Considerations
Potential risks include: 1) The new `setup-py-reqs` action might introduce unforeseen issues with dependency resolution or Python version compatibility. 2) The dependency on CI-MATs could delay documentation builds if the CI-MATs workflow experiences failures or delays. 3) The artifact handling changes might inadvertently break existing artifact retrieval processes. 4) The sparse-checkout might miss necessary files, causing build failures. 5) The changes to the Makefile could affect local development environments.

### Notable Implementation Details
Notable implementation details include: 1) The complex if/else logic in the `Evaluate Dependencies` step of the `setup-py-reqs` action, which requires careful review to ensure correctness. 2) The use of `git ls-files` in the `Collect and Enumerate Generated Files` step, which requires proper handling of file paths with spaces or special characters to prevent command injection vulnerabilities. 3) The different implementations for UUID generation on Windows vs. non-Windows platforms in the `output_integration_step_summary` step of the Tests workflow, which should be standardized for consistency.
</details>
author_association: NONE