feat: cross-platform support (macOS/Linux), unified UI scaling, and comprehensive test suite - #37
Merged
Merged
Conversation
…n, but does run on mac, will speak to repo owner about getting on discord to see which features are needed
Implement a cohesive interface scaling system that replaces the font-only --aegis-font-scale with a unified --aegis-ui-scale variable. Previously, increasing the scale slider only affected font sizes while layout spacing remained fixed, creating visual imbalance. Now one slider controls text, spacing, padding, gaps, and container sizing together. Scaling tokens added to tokens.css: - 10 spacing tokens (--aegis-space-1 through --aegis-space-10, 2px–24px) - 6 sizing tokens for structural elements (header, footer, timeline, panel min-widths, modal min-width) - 4 column-width tokens for tabular layouts (time, action, agent, state) - All tokens use calc(Npx * var(--aegis-ui-scale)) pattern Converted ~106 hardcoded px values across 24+ Svelte components to use the new tokens. One-off constraints (e.g. max-height on scrollable areas) use inline calc() with --aegis-ui-scale. Left as literal px (intentionally not scaled): - 1px borders/dividers, border-radius (uses shape tokens), box-shadow - Canvas/SVG internals (devicePixelRatio handles canvas scaling) - Media query breakpoints, animation transforms, toggle switch internals Store changes (theme.js): - Renamed fontScale → uiScale, setFontScale → setUiScale - localStorage key migrated from aegis-font-scale to aegis-ui-scale with automatic fallback read of the old key - Backward-compatible re-exports preserved Config changes (config-manager.js): - Default settings key renamed fontScale → uiScale Radar high-contrast theme fix: - Added missing CSS custom property overrides for dark-hc and light-hc themes (previously only dark and light had radar-specific RGB values) - Fixed isLight detection to include light-hc variant - Added isHC flag that boosts alpha values for rings, crosshairs, sweep trail, agent dots, and labels in high-contrast modes - Dark HC: brighter line/label RGB, more vivid sweep color - Light HC: darker line/label RGB, stronger sweep contrast
Add 386 tests across 21 test files, bringing statement coverage from ~44% file coverage to 86% overall. All new tests validate real logic with no placeholders or stubs. New test files: - anomaly-detector (25 tests) — scoring weights, deviation warnings, dedup - ai-analysis (22 tests) — API calls, JSON extraction, error handling - exports (12 tests) — CSV escaping, JSON export, HTML report generation - tray-icon (20 tests) — PNG generation, threat colors, notifications - ipc-handlers (17 tests) — channel registration, handler delegation - platform/darwin (15 tests) — ps parsing, .app bundle extraction - platform/win32 (40 tests) — tasklist parsing, PowerShell integration - platform/index (3 tests) — platform dispatch verification - threat-report (9 tests) — HTML generation, XSS escaping, risk colors Coverage highlights: - ai-analysis.js: 100% statements/lines - anomaly-detector.js: 99%/100% - exports.js: 100%/100% - threat-report.js: 100%/100% - win32.js: 99%/99% Updated vitest.config.js coverage include list to track all new modules.
Add dependency injection test helpers (_resetForTest, _setDepsForTest, _setPlatformForTest, _setExecFileForTest) to 8 source modules so tests can mock platform calls without brittle module patching. - baselines.js: _setBaselinesPathForTest - config-manager.js: _setSettingsPathForTest - file-watcher.js: _setDepsForTest, _resetForTest, export isSelfAccess/handleWatcherEvent - network-monitor.js: _setDepsForTest, _resetForTest, export isPrivateIp/resolveIp - process-scanner.js: _setPlatformForTest, _resetForTest - process-utils.js: _setPlatformForTest, _resetForTest - platform/posix-shared.js: _setExecFileForTest - platform/linux.js: _setExecFileForTest, export parseSsOutput Also adds: - CI: test job in .github/workflows/ci.yml - package.json: test/test:watch/test:coverage scripts, vitest + @vitest/coverage-v8 devDeps - README: testing section with commands
…ne follow - Add Ctrl/Cmd+Shift+T global shortcut to cycle through all four themes - Theme footer with CSS tokens so it's visible in light/HC themes instead of hardcoded dark background - Show active agent count in system tray tooltip - Fix audit log stats not displaying: backend returned mismatched field names (todayEntries/totalFiles/recordingSince) vs what the UI expected (totalEntries/totalSize/firstEntry/lastEntry); now returns correct fields with actual entry counts, file sizes, and timestamp ranges - Audit log size now shows current log and total: "12.3 KB (1.2 MB)" with support for B/KB/MB/GB/TB - Center radar in shield layout using 3-column grid with agents panel to the right - Timeline scrubber defaults to right edge and auto-follows as new events arrive; user can drag away to browse history, drag back to right to re-enable following - Persist timeline zoom level in settings across restarts
Timeline lazy-loads historical audit log entries when the user drags the scrubber to the left edge. The scrubber is always freely draggable; it defaults to the right edge (following live events) and only triggers a history fetch when it physically reaches position 0. Each fetch loads 25 entries at a time using a performant reverse file reader (4KB chunks from EOF, stops as soon as the batch is full, skips files by date). After each load the viewport scroll compensates for the expanded time range so the view stays stable instead of jumping. - Add audit-logger getEntriesBefore() with chunked reverse file reading - Add get-audit-entries-before IPC handler + preload bridge - Decouple thumb position from scrollLeft so scrubber is always movable - Merge historical + live events with timestamp dedup, cap at 500 - Show active agent count in tray context menu, rebuilt on each scan
Fix/UI polish
This was referenced Feb 25, 2026
Timeline lazy-loads historical audit log entries when the user drags the scrubber to the left edge. The scrubber is always freely draggable; it defaults to the right edge (following live events) and only triggers a history fetch when it physically reaches position 0. Each fetch loads 25 entries at a time using a performant reverse file reader (4KB chunks from EOF, stops as soon as the batch is full, skips files by date). After each load the viewport scroll compensates for the expanded time range so the view stays stable instead of jumping. - Add audit-logger getEntriesBefore() with chunked reverse file reading - Add get-audit-entries-before IPC handler + preload bridge - Decouple thumb position from scrollLeft so scrubber is always movable - Merge historical + live events with timestamp dedup, cap at 500 - Show active agent count in tray context menu, rebuilt on each scan
antropos17
added a commit
that referenced
this pull request
Feb 28, 2026
Fixes identified during maintainer code review of #37 (cross-platform support by @skmelendez). No business logic changes — only safety guards, DI consistency, and test portability. Platform layer: - linux.js: fix bare execFile → _execFile in getParentProcessMap ps-fallback (was bypassing DI hook, breaking test mockability on Linux without /proc) - darwin.js: add _setExecFileForTest DI hook for test mockability (consistent with linux.js and posix-shared.js pattern) - win32.js: add PID integer validation to killProcess, suspendProcess, resumeProcess (defence-in-depth, matches existing getFileHandles guard) Tests: - file-watcher.test.js: skip 3 darwin-specific shouldIgnore tests on non-macOS platforms (patterns from darwin.js not loaded on Windows) - ipc-handlers.test.js: case-insensitive directory name assertion (Windows is case-preserving: AEGIS vs Aegis) Reviewed-by: @antropos17 Co-authored-by: @skmelendez
antropos17
approved these changes
Feb 28, 2026
Owner
There was a problem hiding this comment.
Great work on cross-platform support @skmelendez! This is a massive contribution — platform abstraction layer, 386 tests, UI scaling system.
I've done a full code review and identified a few critical fixes needed (linux.js DI hook, win32 PID validation, test portability). I'll push those as a follow-up PR referencing this one.
Merging — thank you for the contribution! 🎉
antropos17
added a commit
that referenced
this pull request
Feb 28, 2026
Fixes identified during maintainer code review of #37 (cross-platform support by @skmelendez). No business logic changes -- only safety guards, DI consistency, and test portability. Platform layer: - linux.js: fix bare execFile -> _execFile in getParentProcessMap ps-fallback (was bypassing DI hook, breaking test mockability on Linux without /proc) - darwin.js: add _setExecFileForTest DI hook for test mockability (consistent with linux.js and posix-shared.js pattern) - win32.js: add PID integer validation to killProcess, suspendProcess, resumeProcess (defence-in-depth, matches existing getFileHandles guard) Tests: - file-watcher.test.js: skip 4 darwin/linux-specific shouldIgnore tests on non-matching platforms (patterns from darwin.js/linux.js not loaded on Windows) - ipc-handlers.test.js: case-insensitive directory name assertion (Windows is case-preserving: AEGIS vs Aegis) Reviewed-by: @antropos17 Co-authored-by: @skmelendez
antropos17
added a commit
that referenced
this pull request
Feb 28, 2026
fix: critical issues from PR #37 code review
antropos17
added a commit
that referenced
this pull request
Feb 28, 2026
Only fall back to lsof when ss fails with error, not on empty results. An agent with zero TCP connections is normal — no need to retry with lsof. Updated test to expect correct behavior (empty result, no lsof fallback). Resolves: PR #37 code review HIGH issue #7 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
antropos17
added a commit
that referenced
this pull request
Feb 28, 2026
* fix: use cross-platform path separator in AgentCard
Replace split('/') with split(/[/\]/) to handle both Unix and Windows paths.
Fixes path display truncation on Windows where backslash paths were not split correctly.
Resolves: PR #37 code review HIGH issue #1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: cleanup IPC listener to prevent HMR leak in App.svelte
Wrap onToggleTheme listener in $effect with cleanup return.
Make preload.js onToggleTheme return an unsubscribe function.
Prevents duplicate listeners accumulating during hot module replacement.
Resolves: PR #37 code review HIGH issue #4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: correct ss→lsof fallback logic in linux getRawTcpConnections
Only fall back to lsof when ss fails with error, not on empty results.
An agent with zero TCP connections is normal — no need to retry with lsof.
Updated test to expect correct behavior (empty result, no lsof fallback).
Resolves: PR #37 code review HIGH issue #7
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: restore Module._load in afterAll for 6 test files
Prevents monkey-patched module loader from leaking between test suites
if Vitest isolation settings change.
Resolves: PR #37 code review HIGH issue #8
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
antropos17
added a commit
that referenced
this pull request
Feb 28, 2026
* refactor: extract parsePsOutput into posix-shared for DRY darwin.js and linux.js had identical ps output parsing logic. Shared function handles baseline parsing; darwin adds .app bundle name extraction as post-processing. Resolves: PR #37 code review HIGH issue #5 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: align getStats mock shapes with actual API contracts Ensures test mocks match real return shapes from main.js, audit-logger.js, and logger.js getStats() functions. Improves test reliability and documentation of API contracts. Resolves: PR #37 code review HIGH issue #6 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced Feb 28, 2026
ElshadHu
pushed a commit
to ElshadHu/Aegis
that referenced
this pull request
Apr 9, 2026
…omprehensive test suite (antropos17#37) * Updated claude for base run on linux/mac, will need further validation, but does run on mac, will speak to repo owner about getting on discord to see which features are needed * feat: unified UI scaling system + radar high-contrast fix Implement a cohesive interface scaling system that replaces the font-only --aegis-font-scale with a unified --aegis-ui-scale variable. Previously, increasing the scale slider only affected font sizes while layout spacing remained fixed, creating visual imbalance. Now one slider controls text, spacing, padding, gaps, and container sizing together. Scaling tokens added to tokens.css: - 10 spacing tokens (--aegis-space-1 through --aegis-space-10, 2px–24px) - 6 sizing tokens for structural elements (header, footer, timeline, panel min-widths, modal min-width) - 4 column-width tokens for tabular layouts (time, action, agent, state) - All tokens use calc(Npx * var(--aegis-ui-scale)) pattern Converted ~106 hardcoded px values across 24+ Svelte components to use the new tokens. One-off constraints (e.g. max-height on scrollable areas) use inline calc() with --aegis-ui-scale. Left as literal px (intentionally not scaled): - 1px borders/dividers, border-radius (uses shape tokens), box-shadow - Canvas/SVG internals (devicePixelRatio handles canvas scaling) - Media query breakpoints, animation transforms, toggle switch internals Store changes (theme.js): - Renamed fontScale → uiScale, setFontScale → setUiScale - localStorage key migrated from aegis-font-scale to aegis-ui-scale with automatic fallback read of the old key - Backward-compatible re-exports preserved Config changes (config-manager.js): - Default settings key renamed fontScale → uiScale Radar high-contrast theme fix: - Added missing CSS custom property overrides for dark-hc and light-hc themes (previously only dark and light had radar-specific RGB values) - Fixed isLight detection to include light-hc variant - Added isHC flag that boosts alpha values for rings, crosshairs, sweep trail, agent dots, and labels in high-contrast modes - Dark HC: brighter line/label RGB, more vivid sweep color - Light HC: darker line/label RGB, stronger sweep contrast * test: add comprehensive test coverage for 9 previously untested modules Add 386 tests across 21 test files, bringing statement coverage from ~44% file coverage to 86% overall. All new tests validate real logic with no placeholders or stubs. New test files: - anomaly-detector (25 tests) — scoring weights, deviation warnings, dedup - ai-analysis (22 tests) — API calls, JSON extraction, error handling - exports (12 tests) — CSV escaping, JSON export, HTML report generation - tray-icon (20 tests) — PNG generation, threat colors, notifications - ipc-handlers (17 tests) — channel registration, handler delegation - platform/darwin (15 tests) — ps parsing, .app bundle extraction - platform/win32 (40 tests) — tasklist parsing, PowerShell integration - platform/index (3 tests) — platform dispatch verification - threat-report (9 tests) — HTML generation, XSS escaping, risk colors Coverage highlights: - ai-analysis.js: 100% statements/lines - anomaly-detector.js: 99%/100% - exports.js: 100%/100% - threat-report.js: 100%/100% - win32.js: 99%/99% Updated vitest.config.js coverage include list to track all new modules. * chore: add test infrastructure, DI hooks, CI test job, and devDeps Add dependency injection test helpers (_resetForTest, _setDepsForTest, _setPlatformForTest, _setExecFileForTest) to 8 source modules so tests can mock platform calls without brittle module patching. - baselines.js: _setBaselinesPathForTest - config-manager.js: _setSettingsPathForTest - file-watcher.js: _setDepsForTest, _resetForTest, export isSelfAccess/handleWatcherEvent - network-monitor.js: _setDepsForTest, _resetForTest, export isPrivateIp/resolveIp - process-scanner.js: _setPlatformForTest, _resetForTest - process-utils.js: _setPlatformForTest, _resetForTest - platform/posix-shared.js: _setExecFileForTest - platform/linux.js: _setExecFileForTest, export parseSsOutput Also adds: - CI: test job in .github/workflows/ci.yml - package.json: test/test:watch/test:coverage scripts, vitest + @vitest/coverage-v8 devDeps - README: testing section with commands * chore: add coverage/ to .gitignore * feat: UI polish — theme shortcut, footer theming, audit stats, timeline follow - Add Ctrl/Cmd+Shift+T global shortcut to cycle through all four themes - Theme footer with CSS tokens so it's visible in light/HC themes instead of hardcoded dark background - Show active agent count in system tray tooltip - Fix audit log stats not displaying: backend returned mismatched field names (todayEntries/totalFiles/recordingSince) vs what the UI expected (totalEntries/totalSize/firstEntry/lastEntry); now returns correct fields with actual entry counts, file sizes, and timestamp ranges - Audit log size now shows current log and total: "12.3 KB (1.2 MB)" with support for B/KB/MB/GB/TB - Center radar in shield layout using 3-column grid with agents panel to the right - Timeline scrubber defaults to right edge and auto-follows as new events arrive; user can drag away to browse history, drag back to right to re-enable following - Persist timeline zoom level in settings across restarts * feat: timeline history scroll-back, tray menu agent count Timeline lazy-loads historical audit log entries when the user drags the scrubber to the left edge. The scrubber is always freely draggable; it defaults to the right edge (following live events) and only triggers a history fetch when it physically reaches position 0. Each fetch loads 25 entries at a time using a performant reverse file reader (4KB chunks from EOF, stops as soon as the batch is full, skips files by date). After each load the viewport scroll compensates for the expanded time range so the view stays stable instead of jumping. - Add audit-logger getEntriesBefore() with chunked reverse file reading - Add get-audit-entries-before IPC handler + preload bridge - Decouple thumb position from scrollLeft so scrubber is always movable - Merge historical + live events with timestamp dedup, cap at 500 - Show active agent count in tray context menu, rebuilt on each scan * feat: timeline history scroll-back, tray menu agent count Timeline lazy-loads historical audit log entries when the user drags the scrubber to the left edge. The scrubber is always freely draggable; it defaults to the right edge (following live events) and only triggers a history fetch when it physically reaches position 0. Each fetch loads 25 entries at a time using a performant reverse file reader (4KB chunks from EOF, stops as soon as the batch is full, skips files by date). After each load the viewport scroll compensates for the expanded time range so the view stays stable instead of jumping. - Add audit-logger getEntriesBefore() with chunked reverse file reading - Add get-audit-entries-before IPC handler + preload bridge - Decouple thumb position from scrollLeft so scrubber is always movable - Merge historical + live events with timestamp dedup, cap at 500 - Show active agent count in tray context menu, rebuilt on each scan
ElshadHu
pushed a commit
to ElshadHu/Aegis
that referenced
this pull request
Apr 9, 2026
Fixes identified during maintainer code review of antropos17#37 (cross-platform support by @skmelendez). No business logic changes -- only safety guards, DI consistency, and test portability. Platform layer: - linux.js: fix bare execFile -> _execFile in getParentProcessMap ps-fallback (was bypassing DI hook, breaking test mockability on Linux without /proc) - darwin.js: add _setExecFileForTest DI hook for test mockability (consistent with linux.js and posix-shared.js pattern) - win32.js: add PID integer validation to killProcess, suspendProcess, resumeProcess (defence-in-depth, matches existing getFileHandles guard) Tests: - file-watcher.test.js: skip 4 darwin/linux-specific shouldIgnore tests on non-matching platforms (patterns from darwin.js/linux.js not loaded on Windows) - ipc-handlers.test.js: case-insensitive directory name assertion (Windows is case-preserving: AEGIS vs Aegis) Reviewed-by: @antropos17 Co-authored-by: @skmelendez
ElshadHu
pushed a commit
to ElshadHu/Aegis
that referenced
this pull request
Apr 9, 2026
fix: critical issues from PR antropos17#37 code review
ElshadHu
pushed a commit
to ElshadHu/Aegis
that referenced
this pull request
Apr 9, 2026
…s17#41) * fix: use cross-platform path separator in AgentCard Replace split('/') with split(/[/\]/) to handle both Unix and Windows paths. Fixes path display truncation on Windows where backslash paths were not split correctly. Resolves: PR antropos17#37 code review HIGH issue #1 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: cleanup IPC listener to prevent HMR E3A7 leak in App.svelte Wrap onToggleTheme listener in $effect with cleanup return. Make preload.js onToggleTheme return an unsubscribe function. Prevents duplicate listeners accumulating during hot module replacement. Resolves: PR antropos17#37 code review HIGH issue antropos17#4 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: correct ss→lsof fallback logic in linux getRawTcpConnections Only fall back to lsof when ss fails with error, not on empty results. An agent with zero TCP connections is normal — no need to retry with lsof. Updated test to expect correct behavior (empty result, no lsof fallback). Resolves: PR antropos17#37 code review HIGH issue antropos17#7 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: restore Module._load in afterAll for 6 test files Prevents monkey-patched module loader from leaking between test suites if Vitest isolation settings change. Resolves: PR antropos17#37 code review HIGH issue antropos17#8 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
ElshadHu
pushed a commit
to ElshadHu/Aegis
that referenced
this pull request
Apr 9, 2026
* refactor: extract parsePsOutput into posix-shared for DRY darwin.js and linux.js had identical ps output parsing logic. Shared function handles baseline parsing; darwin adds .app bundle name extraction as post-processing. Resolves: PR antropos17#37 code review HIGH issue antropos17#5 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: align getStats mock shapes with actual API contracts Ensures test mocks match real return shapes from main.js, audit-logger.js, and logger.js getStats() functions. Improves test reliability and documentation of API contracts. Resolves: PR antropos17#37 code review HIGH issue antropos17#6 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
antropos17
added a commit
that referenced
this pull request
Aug 25, 2026
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Three-part PR that adds cross-platform runtime support, improves the UI scaling system, and establishes a full test suite.
Cross-platform support — Extracted all platform-specific logic (process listing, TCP connections, file handles, process control) into a
platform/abstraction layer with dedicated modules for darwin, linux, and win32. Refactored process-scanner, process-utils, file-watcher, and network-monitor to use the platform layer instead of hardcoded Windows calls. The app now runs on macOS and Linux in addition to Windows.Unified UI scaling — Replaced the font-only
--aegis-font-scalewith a unified--aegis-ui-scalesystem. One slider now controls text, spacing, padding, gaps, and container sizing together. Added ~20 scaling tokens totokens.cssand converted ~106 hardcoded px values across 24+ Svelte components. Also fixed radar high-contrast rendering. Backward-compatible store migration from the old localStorage key.Test suite — Added 386 tests across 21 test files using vitest + v8 coverage. Achieves 86% statement and 88% line coverage. Tests cover anomaly scoring, AI analysis API handling, CSV/HTML export escaping, platform process parsing, tray icon threat colors, IPC handler registration, and more.
Multiple modules hit 100% coverage (ai-analysis, exports, threat-report, risk-scoring, constants).
Added DI test hooks (_resetForTest, _setDepsForTest, _setPlatformForTest) to 8 source modules for clean mocking. Added CI test job, npm test scripts, and vitest/coverage devDependencies.
Type of change
Testing
npx vitest runnpx vitest run --coverage(86% stmts, 88% lines)npm start— app launches, scans processes, monitors files, network panel functionalChecklist
npm start