Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 31 additions & 0 deletions .github/ISSUE_TEMPLATE/ai-task.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: AI Task
about: Track implementation tasks that use AI-assisted coding workflows.
title: "[AI] "
labels: ["ai", "automation"]
body:
- type: textarea
id: objective
attributes:
label: Objective
description: Clear success criteria for the AI-assisted task.
validations:
required: true
- type: textarea
id: scope
attributes:
label: Scope
description: In-scope files/modules and explicit out-of-scope boundaries.
validations:
required: true
- type: textarea
id: constraints
attributes:
label: Constraints
description: Product, security, and architectural constraints.
- type: textarea
id: validation
attributes:
label: Validation Plan
description: Tests/lint/manual checks required before merge.
validations:
required: true
23 changes: 23 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copilot Instructions — Argus_Overview

Start by reading `CLAUDE.md` and keep changes aligned with its constraints.

## Project Focus
- Python desktop app for EVE multiboxing.
- UI stack: PySide6.
- Platform abstraction is required: Linux and Windows implementations should stay in their platform modules.

## Guardrails
- Keep business logic out of UI widgets where possible.
- Do not hardcode user-specific paths or machine assumptions.
- Never commit secrets, tokens, or local environment artifacts.

## Preferred Commands
- `python -m pip install -e ".[dev,linux]"`
- `ruff check .`
- `ruff format .`
- `pytest -q`

## Validation Expectations
- Run lint + tests before proposing final changes.
- If touching platform-specific code, verify no regressions on the other platform layer.
120 changes: 120 additions & 0 deletions .github/workflows/ai-quality-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
name: AI Quality Gate

on:
pull_request:
branches: [main, develop, master]
paths:
- "**/*.py"
- "pyproject.toml"
- "requirements*.txt"
- ".pre-commit-config.yaml"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ai-quality-gate-${{ github.ref }}
cancel-in-progress: true

env:
RUFF_VERSION: "0.15.11"
MYPY_VERSION: "1.19.1"
PYTEST_VERSION: "8.4.2"
PYTEST_ASYNCIO_VERSION: "1.2.0"
PYTEST_COV_VERSION: "7.1.0"

jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
python_files: ${{ steps.collect.outputs.python_files }}
test_files: ${{ steps.collect.outputs.test_files }}
python_changed: ${{ steps.collect.outputs.python_changed }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Collect changed Python files
id: collect
shell: bash
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
else
BASE_SHA="${{ github.event.before }}"
HEAD_SHA="${{ github.sha }}"
fi

changed_files="$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")"
python_files="$(printf '%s\n' "$changed_files" | grep -E '\.py$' || true)"
test_files="$(printf '%s\n' "$python_files" | grep -E '^tests/.*\.py$' || true)"

if [[ -n "$python_files" ]]; then
echo "python_changed=true" >> "$GITHUB_OUTPUT"
else
echo "python_changed=false" >> "$GITHUB_OUTPUT"
fi

{
echo "python_files<<EOF_FILES"
printf '%s\n' "$python_files"
echo "EOF_FILES"
echo "test_files<<EOF_TESTS"
printf '%s\n' "$test_files"
echo "EOF_TESTS"
} >> "$GITHUB_OUTPUT"

quality-gate:
runs-on: ubuntu-latest
needs: detect-changes
if: needs.detect-changes.outputs.python_changed == 'true'
steps:
- uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
cache: "pip"

- name: Install dependencies
run: |
pip install --upgrade pip
pip install -e ".[dev,linux]"
pip install "ruff==${RUFF_VERSION}" "mypy==${MYPY_VERSION}" "pytest==${PYTEST_VERSION}" "pytest-asyncio==${PYTEST_ASYNCIO_VERSION}" "pytest-cov==${PYTEST_COV_VERSION}"

- name: Ruff on changed files
shell: bash
run: |
mapfile -t py_files < <(printf '%s\n' "${{ needs.detect-changes.outputs.python_files }}" | sed '/^\s*$/d')
if [[ ${#py_files[@]} -eq 0 ]]; then
echo "No changed Python files detected."
exit 0
fi
ruff check "${py_files[@]}"
ruff format --check "${py_files[@]}"

- name: Mypy on changed source files
shell: bash
run: |
mapfile -t mypy_files < <(printf '%s\n' "${{ needs.detect-changes.outputs.python_files }}" | grep -E '^src/.*\.py$' | grep -v '^src/argus_overview/platform/windows.py$' || true)
if [[ ${#mypy_files[@]} -eq 0 ]]; then
echo "No changed source files for mypy."
exit 0
fi
mypy "${mypy_files[@]}" --ignore-missing-imports --no-error-summary

- name: Pytest on changed tests only
shell: bash
env:
QT_QPA_PLATFORM: offscreen
run: |
mapfile -t test_files < <(printf '%s\n' "${{ needs.detect-changes.outputs.test_files }}" | sed '/^\s*$/d')
if [[ ${#test_files[@]} -eq 0 ]]; then
echo "No changed test files detected; skipping pytest in quality gate."
exit 0
fi
pytest -q "${test_files[@]}"
14 changes: 10 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ permissions:
contents: read
security-events: write

env:
RUFF_VERSION: "0.15.11"
MYPY_VERSION: "1.19.1"
PYTEST_VERSION: "8.4.2"
PYTEST_ASYNCIO_VERSION: "1.2.0"
PYTEST_COV_VERSION: "7.1.0"

jobs:
lint:
name: Lint & Format
Expand All @@ -40,7 +47,7 @@ jobs:
python-version: '3.12'

- name: Install ruff
run: pip install ruff
run: pip install "ruff==${RUFF_VERSION}"

- name: Run ruff linter
run: ruff check . --output-format=github
Expand All @@ -65,11 +72,10 @@ jobs:
pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi
pip install mypy types-requests types-cachetools
pip install "mypy==${MYPY_VERSION}" types-requests types-cachetools

- name: Run mypy
run: mypy . --ignore-missing-imports --no-error-summary --exclude 'src/argus_overview/platform/windows.py'
continue-on-error: true # Type checking is advisory, not blocking

test:
name: Test (Python ${{ matrix.python-version }})
Expand Down Expand Up @@ -97,7 +103,7 @@ jobs:
run: |
pip install --upgrade pip
pip install -e ".[dev,linux]"
pip install pytest pytest-cov pytest-asyncio
pip install "pytest==${PYTEST_VERSION}" "pytest-asyncio==${PYTEST_ASYNCIO_VERSION}" "pytest-cov==${PYTEST_COV_VERSION}"

- name: Run tests with coverage
env:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ ENV/
env/

# IDE
.vscode/
.vscode/*
!.vscode/extensions.json
.idea/
*.swp
*.swo
Expand Down
18 changes: 18 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-merge-conflict
- id: check-added-large-files
args: ["--maxkb=750"]
- id: detect-private-key

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.11
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
10 changes: 10 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"recommendations": [
"github.copilot",
"github.copilot-chat",
"ms-python.python",
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"ms-python.debugpy"
]
}
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ tar -xzf Argus-Overview-*-Linux.tar.gz && cd argus-overview-linux

> Cross-platform support (Windows native, Mac) planned for v3. Community interest in Qt/Rust port welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).

## First Launch

Argus is designed to get you from launch to usable cycling quickly:

1. Start Argus with your EVE clients already running when possible.
2. Let Argus auto-import detected clients on startup, or click `Import Windows` in the `Overview` tab.
3. Use `Cycle Control` to tune hotkeys and groups only after the windows you care about are visible.

If you prefer a hands-on setup flow, use `Add Window` in `Overview` for manual control and disable startup auto-import in `Settings`.

---

## Screenshots
Expand Down
2 changes: 1 addition & 1 deletion docs/FORUM_POST.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Argus is MIT-licensed open source. No account linking, no third-party servers, n
### Technical Details

Built with:
- Python 3.8+ / PySide6 (Qt)
- Python 3.10+ / PySide6 (Qt)
- Native X11 window management (python-xlib, wmctrl, xdotool)
- 1,500+ automated tests, 96% code coverage

Expand Down
2 changes: 1 addition & 1 deletion docs/REDDIT_LAUNCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ cd Argus_Overview && ./install.sh

**Requirements:**
- Linux with X11 (Wayland works via XWayland)
- Python 3.8+
- Python 3.10+
- wmctrl, xdotool, ImageMagick

**Windows users:** Check the releases page for the Windows .exe build.
Expand Down
4 changes: 2 additions & 2 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ PYTHON_VERSION=$(python3 --version 2>&1 | awk '{print $2}')
PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d. -f1)
PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d. -f2)

if [ "$PYTHON_MAJOR" -lt 3 ] || ([ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -lt 8 ]); then
echo "Error: Python 3.8 or higher is required. Found: $PYTHON_VERSION"
if [ "$PYTHON_MAJOR" -lt 3 ] || ([ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -lt 10 ]); then
echo "Error: Python 3.10 or higher is required. Found: $PYTHON_VERSION"
exit 1
fi
echo "✓ Python $PYTHON_VERSION found"
Expand Down
10 changes: 6 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ windows = [
"pywin32>=306",
]
dev = [
"ruff",
"ruff==0.15.11",
"isort",
"pytest",
"pytest-cov",
"mypy==1.19.1",
"pytest==8.4.2",
"pytest-asyncio==1.2.0",
"pytest-cov==7.1.0",
"bandit[toml]",
]

Expand All @@ -60,7 +62,7 @@ argus-overview = "main:main"

[tool.ruff]
line-length = 100
target-version = "py38"
target-version = "py310"
exclude = ["windows/", "build/", "dist/", ".venv/"]

[tool.ruff.lint]
Expand Down
18 changes: 14 additions & 4 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"

# Use venv python directly if available, otherwise system python
# Use venv python directly if available, otherwise system python.
export PYTHONPATH="$SCRIPT_DIR/src:$PYTHONPATH"

if [ -f "venv/bin/python3" ]; then
exec venv/bin/python3 src/main.py "$@"
PYTHON_CMD="venv/bin/python3"
elif [ -f ".venv/bin/python3" ]; then
exec .venv/bin/python3 src/main.py "$@"
PYTHON_CMD=".venv/bin/python3"
else
exec python3 src/main.py "$@"
PYTHON_CMD="python3"
fi

# Fail fast on unsupported runtimes before Qt initializes.
if ! "$PYTHON_CMD" -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 10) else 1)' 2>/dev/null; then
PY_VER="$("$PYTHON_CMD" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")' 2>/dev/null || echo "unknown")"
echo "Argus Overview requires Python 3.10+ (detected ${PY_VER} from ${PYTHON_CMD})." >&2
echo "Recreate your environment with Python 3.10+ and reinstall dependencies." >&2
exit 1
fi

exec "$PYTHON_CMD" src/main.py "$@"
Loading
Loading