Skip to content
Merged
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
14 changes: 14 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## Summary

-

## Testing

-

## Regression protection

- [ ] Every fixed bug has a regression test that fails on the old behavior.
- [ ] Resource-sensitive changes include bounded-queue, failure, and cleanup coverage.
- [ ] UI/terminal changes were exercised in Electron, or the missing hardware test is explicit.
- [ ] Rollback and compatibility behavior is documented for protocol or persistence changes.
58 changes: 58 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: PR checks

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

concurrency:
group: pr-checks-${{ github.ref }}
cancel-in-progress: true

jobs:
quality:
name: Tests and regression protection
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r backend/requirements.txt -r mcp_server/requirements.txt pytest httpx

- name: Run backend tests
run: python -m pytest

- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: client/package-lock.json

- name: Install client dependencies
working-directory: client
run: npm ci

- name: Run client tests
working-directory: client
run: |
npm run test:chat
npm run test:electron

- name: Build client
working-directory: client
run: npm run build

- name: Run permanent regression suite
run: python scripts/run_regression_checks.py
48 changes: 44 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,20 +255,33 @@ GET /agents/runs/{run_id}/artifacts/{artifact_name}

## Testing

Run the backend test suite from the repository root:
Run the complete backend suite and the permanent historical-regression gate
from the repository root:

```bash
pytest
python -m pytest
python scripts/run_regression_checks.py
```

Run the client build checks:
Run the client unit suites and build checks:

```bash
cd client
npm run test:chat
npm run test:electron
npm run test:regression
npm run build
```

The tests use fake CLI agent fixtures so execution flow can be verified without hosted models or external agent tools.
The regression gate fails when either the backend or client regression corpus is
missing. It permanently covers the resource/freeze incidents behind terminal
remount and layout, output ACK recovery, bounded execution logs, and session
scan amplification. Tests use fake CLI agent fixtures, so these checks do not
launch hosted models or external agent tools.

Pull requests run the same suites in `.github/workflows/pr-checks.yml`. Changes
to terminal streaming, restore, graphics, process launch, session discovery, or
pane layout must add a regression case for the historical behavior they touch.

For the first public release gate, see
[`docs/release-0.1.0-checklist.md`](docs/release-0.1.0-checklist.md).
Expand Down Expand Up @@ -312,6 +325,14 @@ That backend-run flow is maintained for compatibility and tests. Athena's curren

The Electron main process manages embedded terminals through `node-pty`. The React UI renders them with `xterm.js`.

Mounted terminal views use a bounded, sequence-aware stream. Output is sent
only to subscribed visible views, retained until xterm's write callback
acknowledges it, and replayed from an atomic snapshot after a remount. If a
consumer falls behind its bounded budget, Athena sends an explicit reset and
truncation marker instead of silently joining incompatible VT fragments.
Collapsed, maximized-away, and off-workspace panes keep their PTY alive without
receiving raw renderer IPC.

The `New` menu can launch:

- Shell
Expand Down Expand Up @@ -560,6 +581,25 @@ which hermes

Quit all running Athena/AppImage instances before testing a newly built AppImage. Linux AppImages mount into `/tmp/.mount_ATHENA...`, so an older running instance can make it look like a rebuild did not change the UI.

### Athena is hot or slow on Linux

Open **Settings → Graphics** to inspect the active graphics mode. Athena keeps
hardware acceleration enabled on healthy Linux systems so terminal painting
does not overload the software compositor. A GPU-process crash or interrupted
accelerated launch quarantines the next launch into safe mode, preventing a
crash loop. The setting always requires a restart.

Environment overrides remain available for diagnosis:

```bash
CONTEXT_WORKSPACE_ENABLE_GPU=1 npm start
CONTEXT_WORKSPACE_SAFE_GRAPHICS=1 npm start
```

The explicit GPU override wins over quarantine and should only be used when you
can recover from a native graphics crash. Settings also shows terminal stream
subscribers, retries, resets, dropped/truncated characters, and event-loop lag.

### Embedded shell prints an `nvm` warning

If the app is launched through `npm run dev`, the embedded shell may inherit npm environment variables. With `nvm`, this can produce:
Expand Down
5 changes: 4 additions & 1 deletion backend/adapters/grok.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ def build_command(self, run: Run, artifacts: RunArtifacts) -> AdapterCommand:

def summarize_result(self, run: Run, artifacts: RunArtifacts) -> str:
if artifacts.stdout.exists():
result = artifacts.stdout.read_text(encoding="utf-8").strip()
# Run logs are bounded as raw process bytes. A byte-budget cutoff
# can land between UTF-8 code units, and third-party CLIs may emit
# non-UTF-8 diagnostics. Keep result summarization recoverable.
result = artifacts.stdout.read_text(encoding="utf-8", errors="replace").strip()
if result:
return result
return f"{run.agent_id} completed without a captured final message."
Expand Down
Loading
Loading