Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
74262d7
chore: apply shared repository quality baseline
Ayerdi Aug 12, 2026
194ad4d
ci: enforce English outside the bilingual Wiki
Ayerdi Aug 12, 2026
e47bb6c
ci: add repository quality checks
Ayerdi Aug 12, 2026
3741d92
docs: make the AutoSwitch README English-first
Ayerdi Aug 12, 2026
cfa00fc
docs: make Pages English-first
Ayerdi Aug 12, 2026
e894c44
docs: translate the complete changelog
Ayerdi Aug 12, 2026
7de8988
docs: add v1.2.5 release notes
Ayerdi Aug 12, 2026
753f364
ci: harden v1.2.5 publication
Ayerdi Aug 12, 2026
760fedf
docs: point the Wiki to v1.2.5
Ayerdi Aug 12, 2026
5c5b5f1
docs: update Spanish Wiki release marker
Ayerdi Aug 12, 2026
801adbe
ci: align AutoSwitch validation with repository standard
Ayerdi Aug 12, 2026
c526a94
release: add guarded publication script
Ayerdi Aug 12, 2026
028b76d
docs: add versioned Wiki publisher
Ayerdi Aug 12, 2026
458aff3
chore: add public repository configuration helper
Ayerdi Aug 12, 2026
017851f
docs: align the documentation index
Ayerdi Aug 12, 2026
444e8fd
fix: validate GitHub Wiki targets correctly
Ayerdi Aug 12, 2026
5047231
chore: run reviewed English cleanup
Ayerdi Aug 12, 2026
aaeb0d7
chore: retry reviewed English cleanup
Ayerdi Aug 12, 2026
7411a82
refactor: finish English runtime documentation
Ayerdi Aug 12, 2026
42355bf
ci: allow multilingual yes/no compatibility literals
Ayerdi Aug 12, 2026
4d3c48f
chore: remove temporary language cleanup
Ayerdi Aug 12, 2026
36eaaed
ci: strengthen language detection for unaccented Spanish
Ayerdi Aug 12, 2026
1cedac4
ci: refine strict language detection
Ayerdi Aug 12, 2026
e7c8cfb
chore: run final reviewed language cleanup
Ayerdi Aug 12, 2026
1e8b3e1
refactor: finish English runtime diagnostics
Ayerdi Aug 12, 2026
734e05e
chore: remove temporary final language cleanup
Ayerdi Aug 12, 2026
13ec1e9
fix: avoid language-guard false positive on tray comment
Ayerdi Aug 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Reproducible bug
description: Report an AutoSwitch defect with redacted diagnostics.
title: "[Bug]: "
labels: [bug]
body:
- type: markdown
attributes:
value: Do not include credentials, unrelated device IDs, private paths or complete unredacted logs.
- type: input
id: version
attributes:
label: AutoSwitch version
validations:
required: true
- type: input
id: headset
attributes:
label: Headset model and connection type
validations:
required: true
- type: dropdown
id: mode
attributes:
label: Detection mode
options: [WindowsEndpoint, LogitechGHub, Unknown / installation failed]
validations:
required: true
- type: textarea
id: steps
attributes:
label: Reproduction steps
validations:
required: true
- type: textarea
id: evidence
attributes:
label: Redacted endpoint/log evidence
description: Include only the smallest evidence needed to understand ON/OFF state behavior.
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Report a vulnerability privately
url: https://github.com/Ayerdi/PROX2-AutoSwitch/security/advisories/new
about: Do not publish exploitable security details in a public issue.
- name: Documentation / Wiki
url: https://github.com/Ayerdi/PROX2-AutoSwitch/wiki
about: Check installation, tray, reconfiguration and troubleshooting guides first.
22 changes: 22 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## What changes?

<!-- Describe the problem and the proposed change. -->

## Safety

- [ ] `Unknown` detection still never switches output.
- [ ] OFF debounce remains deliberate or the behavioral change is justified/tested.
- [ ] Downloads/checksums are not weakened.
- [ ] No machine-specific/private data is included.
- [ ] Windows PowerShell 5.1 compatibility is preserved or intentionally documented.

## Verification

- [ ] PowerShell syntax
- [ ] PSScriptAnalyzer
- [ ] Pester
- [ ] Relevant real-hardware evidence when detection behavior changes

## Documentation

<!-- List README/Wiki/SOURCES/AGENT updates when applicable. -->
13 changes: 7 additions & 6 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches: [main]
paths:
- 'site/**'
- '.github/workflows/pages.yml'
workflow_dispatch:

permissions:
Expand All @@ -20,11 +21,11 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure Pages
uses: actions/configure-pages@v5
- name: Upload site
uses: actions/upload-pages-artifact@v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: site
deploy:
Expand All @@ -36,4 +37,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
68 changes: 68 additions & 0 deletions .github/workflows/release-v1.2.5.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Publish v1.2.5

on:
push:
branches:
- main
paths:
- '.github/workflows/release-v1.2.5.yml'

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- name: Skip if release exists
id: existing
env:
GH_TOKEN: ${{ github.token }}
run: |
if gh release view v1.2.5 >/dev/null 2>&1; then
echo 'exists=true' >> "$GITHUB_OUTPUT"
else
echo 'exists=false' >> "$GITHUB_OUTPUT"
fi

- name: Repository quality checks
if: steps.existing.outputs.exists == 'false'
run: |
python3 scripts/check-repository.py
python3 scripts/check-language.py
bash scripts/run-gitleaks.sh

- name: Build deterministic release twice
if: steps.existing.outputs.exists == 'false'
run: |
bash scripts/build-release.sh 1.2.5
first="$(cut -d' ' -f1 dist/PROX2-AutoSwitch-v1.2.5.zip.sha256)"
first_copy="$(mktemp /tmp/autoswitch-v1.2.5.XXXXXX.zip)"
trap 'rm -f -- "${first_copy}"' EXIT
cp dist/PROX2-AutoSwitch-v1.2.5.zip "${first_copy}"
rm -f dist/*.zip dist/*.sha256
bash scripts/build-release.sh 1.2.5
second="$(cut -d' ' -f1 dist/PROX2-AutoSwitch-v1.2.5.zip.sha256)"
test "$first" = "$second"
cmp "${first_copy}" dist/PROX2-AutoSwitch-v1.2.5.zip
cmp dist/PROX2-AutoSwitch-v1.2.5.zip dist/Audio-AutoSwitch.zip

- name: Publish v1.2.5
if: steps.existing.outputs.exists == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create v1.2.5 \
dist/PROX2-AutoSwitch-v1.2.5.zip \
dist/PROX2-AutoSwitch-v1.2.5.zip.sha256 \
dist/Audio-AutoSwitch.zip \
dist/Audio-AutoSwitch.zip.sha256 \
--target "$GITHUB_SHA" \
--title 'v1.2.5 — English-first repository standard' \
--notes-file docs/RELEASE-NOTES-v1.2.5.md
56 changes: 0 additions & 56 deletions .github/workflows/release.yml

This file was deleted.

128 changes: 62 additions & 66 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,76 @@ name: validate

on:
push:
branches: [main]
branches:
- main
pull_request:

permissions:
contents: read

concurrency:
group: validate-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
validate-scripts:
runs-on: windows-latest
quality:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Repository quality
run: python3 scripts/check-repository.py
- name: English canonical language guard
run: python3 scripts/check-language.py
- name: Validate Bash scripts
run: bash -n scripts/*.sh
- name: Deterministic release build
run: |
bash scripts/build-release.sh 1.2.5
first="$(cut -d' ' -f1 dist/PROX2-AutoSwitch-v1.2.5.zip.sha256)"
cp dist/PROX2-AutoSwitch-v1.2.5.zip /tmp/autoswitch-first.zip
rm -f dist/*.zip dist/*.sha256
bash scripts/build-release.sh 1.2.5
second="$(cut -d' ' -f1 dist/PROX2-AutoSwitch-v1.2.5.zip.sha256)"
test "$first" = "$second"
cmp /tmp/autoswitch-first.zip dist/PROX2-AutoSwitch-v1.2.5.zip
cmp dist/PROX2-AutoSwitch-v1.2.5.zip dist/Audio-AutoSwitch.zip

powershell:
runs-on: windows-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Validate PowerShell syntax
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$scripts = Get-ChildItem -Path . -Filter '*.ps1' -File
if (-not $scripts) { Write-Error 'No .ps1 scripts found' }
foreach ($script in $scripts) {
$tokens = $null
$errors = $null
[System.Management.Automation.Language.Parser]::ParseFile(
$script.FullName, [ref]$tokens, [ref]$errors) | Out-Null
if ($errors.Count -gt 0) {
$errors | ForEach-Object { Write-Error "$($script.Name): $($_.Message) (line $($_.Extent.StartLineNumber))" }
exit 1
}
Write-Host "OK: $($script.Name)"
}

- name: Lint with PSScriptAnalyzer
shell: pwsh
$scripts=Get-ChildItem -Recurse -File | Where-Object { $_.Extension -in '.ps1','.psm1' }
foreach($script in $scripts){$tokens=$null;$errors=$null;[System.Management.Automation.Language.Parser]::ParseFile($script.FullName,[ref]$tokens,[ref]$errors)|Out-Null;if($errors.Count){$errors|ForEach-Object{Write-Error "$($script.FullName): $($_.Message)"};exit 1}}
- name: Install validation modules
shell: powershell
run: |
$ErrorActionPreference = 'Stop'
if (-not (Get-Module -ListAvailable -Name PSScriptAnalyzer)) {
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser -SkipPublisherCheck
}
$results = Invoke-ScriptAnalyzer -Path . -Recurse `
-Severity Error, Warning `
-ExcludeRule PSAvoidUsingWriteHost, PSAvoidUsingPlainTextForPassword, PSAvoidUsingCmdletAliases, PSAvoidUsingEmptyCatchBlock, PSUseApprovedVerbs, PSUseShouldProcessForStateChangingFunctions
if ($results) {
$results | ForEach-Object {
Write-Host "::error file=$($_.ScriptPath),line=$($_.Line)::$($_.RuleName): $($_.Message)"
}
exit 1
}
Write-Host "PSScriptAnalyzer: no Error/Warning findings."

- name: Verify scripts reference files present
shell: pwsh
Install-Module PSScriptAnalyzer -RequiredVersion 1.24.0 -Force -Scope CurrentUser -SkipPublisherCheck
Install-Module Pester -RequiredVersion 5.9.0 -Force -Scope CurrentUser -SkipPublisherCheck
- name: PSScriptAnalyzer
shell: powershell
run: |
$required = @(
'install.ps1',
'Install.cmd',
'Verify.cmd',
'Uninstall.cmd',
'Instalar-PROX2-AutoSwitch.ps1',
'Runtime-PROX2-AutoSwitch.ps1',
'Desinstalar-PROX2-AutoSwitch.ps1',
'Verificar-PROX2-AutoSwitch.ps1',
'Toggle-AudioEnhancements.ps1',
'lib/AutoSwitchCore.psm1'
)
$missing = $required | Where-Object { -not (Test-Path $_) }
if ($missing) { Write-Error "Missing: $($missing -join ', ')" }
Write-Host "All required files present."
Import-Module PSScriptAnalyzer -RequiredVersion 1.24.0
$r=Invoke-ScriptAnalyzer -Path . -Recurse -Severity Error,Warning -ExcludeRule PSAvoidUsingWriteHost,PSAvoidUsingPlainTextForPassword,PSAvoidUsingCmdletAliases,PSAvoidUsingEmptyCatchBlock,PSUseApprovedVerbs,PSUseShouldProcessForStateChangingFunctions
if($r){$r|Format-Table -AutoSize|Out-String|Write-Host;exit 1}
- name: Pester
shell: powershell
run: Import-Module Pester -RequiredVersion 5.9.0; Invoke-Pester -Path .\tests -CI

- name: Run Pester tests
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
if (-not (Get-Module -ListAvailable -Name Pester)) {
Install-Module -Name Pester -Force -Scope CurrentUser -SkipPublisherCheck
}
$config = New-PesterConfiguration
$config.Run.Path = 'tests'
$config.Output.Verbosity = 'Detailed'
$result = Invoke-Pester -Configuration $config
if ($result.FailedCount -gt 0) { exit 1 }
Write-Host "Pester: $($result.PassedCount) passed, $($result.FailedCount) failed."
secrets:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- run: bash scripts/run-gitleaks.sh
2 changes: 1 addition & 1 deletion AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ hardened to tolerate a recreated endpoint whose `Item ID` changes.
"Disable audio enhancements" switch).

12. **COM interop lives in C#**: PowerShell 5.1 cannot cast a COM RCW to a custom `[ComImport]` interface
(`New-Object`, `Activator` or `GetTypeFromCLSID` all fail with "No se puede convertir…"). The cast is
(`New-Object`, `Activator` or `GetTypeFromCLSID` all fail with "the COM interface cast fails at runtime"). The cast is
native in C#, so both the helper and `lib/AutoSwitchCore.psm1` compile the whole COM block with
`Add-Type` and expose a static method (`AutoSwitch.AudioEnhancements.SetSysFx`,
`AutoSwitch.EndpointFx.ReadSysFx`). Read the SysFx state with `IPolicyConfig::GetPropertyValue` on the
Expand Down
Loading