Thanks for your interest in contributing! This document covers setup, the project's non-negotiable conventions, and the PR workflow.
- Windows 10/11 with PowerShell 5.1 or 7 (the scripts must run on 5.1)
- Python 3 on
PATH(used only for SQLite writes viaSet-SqliteKeys) - Git, and for shell-script changes: bash 4+ and ShellCheck
- Pester 5 and PSScriptAnalyzer for tests:
Install-Module Pester -MinimumVersion 5.0 -Scope CurrentUser -Force Install-Module PSScriptAnalyzer -Scope CurrentUser -Force
src/windows/ PowerShell resetters (unversioned names) + identity_utils.ps1
src/linux/ Bash resetters + id_reset_common.sh
tools/ standalone utilities (watchdog etc.)
tests/ Pester 5 suite (unit + repo integrity)
docs/ user guides (research notes stay local-only)
archive/ superseded versions — local-only, NEVER committed
# Lint (must produce zero Error-severity findings)
Invoke-ScriptAnalyzer -Path src,tools,tests -Recurse -Settings ./tests/PSScriptAnalyzerSettings.psd1 -Severity Error
# Test suite
Invoke-Pester -CI -Output Detailed# Shell scripts
shellcheck src/linux/*.sh ghost.sh
for f in src/linux/*.sh ghost.sh; do bash -n "$f"; doneThese are enforced in review (see AGENTS.md for the full rationale):
- Never silent-success. Every write is followed by a re-read + comparison.
Mismatch ⇒
FAILEDoutput + audit-log entry. No exceptions. - Backup before you touch. Every mutated file goes through
Backup-FileToTimestampDirinto the app'sID_Backups/<ts>dir, and the run emits a self-contained restore script (New-RestoreScript). - Preserve chat history and workspaces. Chat stores,
Local Storage,Backups\, andworkspaceStorageare never deleted (UPSERT-only at most). - PS 5.1 compatible. No ternary
? :, no$Inputvariable name,RandomNumberGenerator.Create().GetBytes()(not.Fill()), no-BOM UTF-8 writes via[System.IO.File]::WriteAllText. - Parameterized SQL only, temp
.pyscripts in$env:TEMP, Python detected viaGet-Command python→python3fallback. - Dot-source
identity_utils.ps1— shared logic lives there; per-IDE scripts are thin target manifests. - Scope isolation. Identity scripts touch app data only; MAC/hostname/
registry-source work belongs exclusively in
change_device_id.ps1.
- Scripts live at
src/<os>/<tool>.ps1with no version suffix — Git tags are the version record (CHANGELOG.mddocuments notable changes). - Never commit superseded versions. Test your replacement against the previous
behavior locally, then delete or move old files to
archive/(git-ignored). - New files should carry an SPDX header:
# SPDX-License-Identifier: Apache-2.0.
.envlocal (real tokens — see .env.example), archive/, docs/ research
notes, tools/block_qoder_domains.ps1, .context/, .qoder/, .trash/,
and anything containing machine IDs, audit logs, or credentials. If a file
would identify a device or account, it does not get committed.
- Fork / branch from
main(feat/<topic>orfix/<topic>). - Commits follow Conventional Commits
style (
feat:,fix:,docs:,chore:,refactor:) — matching the existing log. - Run the full local gate (lint + tests + shellcheck) before pushing.
- Open a PR using the template; CI must be green.
- Update
CHANGELOG.mdfor user-visible changes.
By contributing you agree that your contributions are licensed under the Apache License 2.0.