Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
6097880
feat: add offline mode and recommendation search
aaronlippold Jan 29, 2026
91d0dde
feat: add benchmark version comparison (diff command)
aaronlippold Jan 29, 2026
683043a
feat: add auto-fetch for diff command
aaronlippold Jan 29, 2026
87c63cf
fix: improve diff table responsiveness
aaronlippold Jan 29, 2026
3831fa8
fix: use descriptive status labels in diff table
aaronlippold Jan 29, 2026
ea46c5a
feat: add interactive TUI for diff and view commands
aaronlippold Jan 30, 2026
dcb1a82
docs: add beads task tracking documentation to CLAUDE.md
aaronlippold Jan 30, 2026
4a02146
docs: standardize development commands to use uv run
aaronlippold Jan 30, 2026
8e01d4b
feat(tui): add help screen modal (? key)
aaronlippold Jan 30, 2026
bfc92e9
feat(tui): add offline mode indicator
aaronlippold Jan 30, 2026
2dbcdbc
feat(tui): add search functionality (/ key)
aaronlippold Jan 30, 2026
f5e16f5
docs: add TUI features to commands reference and workflows
aaronlippold Jan 30, 2026
38a81b0
docs: add TUI architecture documentation and fix mkdocs build
aaronlippold Jan 30, 2026
1e9106e
feat(tui): add jump, copy, and filter features
aaronlippold Jan 30, 2026
86f6c9d
feat(tui): add multi-select and update docs
aaronlippold Jan 30, 2026
43ef9fb
feat(tui): add catalog browser TUI (ep9.6)
aaronlippold Jan 30, 2026
fc412c4
fix(tui): handle None values in catalog search filter
aaronlippold Jan 30, 2026
f2dfaab
feat(tui): improve catalog browser UX
aaronlippold Jan 30, 2026
95a66eb
refactor(tui): modularize TUI into package structure
aaronlippold Jan 30, 2026
cfc1239
refactor(tui): complete DRY modular structure for diff/view TUIs
aaronlippold Jan 30, 2026
0935c0b
refactor(tui): remove backwards-compat shims, use direct imports
aaronlippold Jan 30, 2026
ac3e769
refactor(tui): DRY base class with abstract method hooks
aaronlippold Jan 30, 2026
a92c225
refactor(tui): complete DRY with sort and selection in base class
aaronlippold Jan 30, 2026
cb0da5d
feat(tui): wire catalog actions to launch ViewApp/DiffApp
aaronlippold Jan 31, 2026
d54f6e3
fix(tui): add visible error handling for action failures
aaronlippold Jan 31, 2026
1518a6a
WIP: TUI architecture refactor to push_screen pattern (BROKEN)
aaronlippold Jan 31, 2026
c27f0b5
chore: configure pytest-asyncio for TUI integration tests
aaronlippold Jan 31, 2026
f58f041
feat(tui): add SPA foundation with BaseBrowserScreen and LoadingModal
aaronlippold Jan 31, 2026
cc40d3f
fix(tui): fix DiffScreen crash on renumbered items
aaronlippold Jan 31, 2026
5a0fb77
feat(tui): integrate LoadingModal into catalog browser
aaronlippold Jan 31, 2026
66186c9
test(tui): add integration and unit tests for TUI workflows
aaronlippold Jan 31, 2026
6995a2f
docs: add TUI user stories for catalog browser
aaronlippold Jan 31, 2026
6119e8c
feat(utils): add centralized parallel execution utility
aaronlippold Jan 31, 2026
8e04499
feat(fetcher): add progress callbacks for parallel downloads
aaronlippold Jan 31, 2026
a95bd49
refactor(tui): DRY screens.py using BaseBrowserScreen inheritance
aaronlippold Jan 31, 2026
bd8f7ba
fix(tui): align with Textual framework best practices
aaronlippold Jan 31, 2026
1df1ef5
feat(tui): add CISBenchApp unified entry point
aaronlippold Jan 31, 2026
b6c4ff1
docs: add Textual framework research and best practices audit
aaronlippold Jan 31, 2026
d7c2711
chore: sync beads and update agent instructions
aaronlippold Jan 31, 2026
3c83cb8
feat(catalog): show cached/downloaded status in catalog browser
aaronlippold Jan 31, 2026
61e71be
fix(tui): use animated LoadingIndicator instead of static emoji
aaronlippold Jan 31, 2026
c24ee8b
fix(tui): remove duplicate progress count in loading modal
aaronlippold Jan 31, 2026
104ff59
fix(tui): order diff by published_date (older benchmark first)
aaronlippold Jan 31, 2026
c6565a9
fix(diff): filter out non-meaningful changes (whitespace, Cloudflare …
aaronlippold Jan 31, 2026
1990361
fix(tui): refresh download status when returning to catalog
aaronlippold Jan 31, 2026
3a4fe86
fix(tui): use dismiss() in action_go_back to trigger callbacks
aaronlippold Jan 31, 2026
2891d4c
feat(services): add ExportService for unified export operations
aaronlippold Jan 31, 2026
2ecd27b
feat(tui): add export dialogs for format selection and progress
aaronlippold Jan 31, 2026
e57599a
feat(tui): wire export dialogs into all browser screens
aaronlippold Jan 31, 2026
71d056c
feat(auth): add SessionKeepAlive to prevent session timeout during TUI
aaronlippold Jan 31, 2026
89db9f2
fix(tui): display catalog details as vertical list, not single line
aaronlippold Jan 31, 2026
96fd423
fix(catalog): correct is_latest calculation per benchmark group
aaronlippold Jan 31, 2026
e8814f7
fix(tui): simplify latest indicator to '★ Latest Version'
aaronlippold Jan 31, 2026
1aeff3b
feat(tui): add dedicated Latest column between Title and Platform
aaronlippold Jan 31, 2026
99fd3ea
fix(tui): use 'Latest' as column header instead of star symbol
aaronlippold Jan 31, 2026
242f34e
feat(tui): add Version column and widen catalog list pane to 65/35
aaronlippold Jan 31, 2026
fd4175a
fix(tui): increase Title column truncation from 40 to 55 chars
aaronlippold Jan 31, 2026
202d8a0
fix(tui): increase Platform column to 15 chars (fits all platforms)
aaronlippold Jan 31, 2026
da0ae3e
test: add mark_latest_versions coverage and fix column tests
aaronlippold Jan 31, 2026
a6b0203
feat(tui): improve catalog sorting and detail display
aaronlippold Jan 31, 2026
f6918e2
feat(tui): add 'o' keybinding to open benchmark URL in browser
aaronlippold Jan 31, 2026
b6b4fb3
feat(tui): add Published date column to catalog table
aaronlippold Jan 31, 2026
54c485c
feat: add collections and last_revision_date to catalog queries
aaronlippold Jan 31, 2026
0d3a74c
feat(parser): extract complete benchmark metadata from detail pages
aaronlippold Jan 31, 2026
61237e9
feat(models): add extended metadata fields to Benchmark model
aaronlippold Jan 31, 2026
b84b868
feat(database): add schema for extended benchmark metadata
aaronlippold Jan 31, 2026
54e04eb
feat(enrichment): add shared enrichment service (DRY architecture)
aaronlippold Jan 31, 2026
5c2acf7
feat(scraper): populate all extended metadata fields
aaronlippold Jan 31, 2026
1aef198
feat(exporters): include extended metadata in all export formats
aaronlippold Jan 31, 2026
8891d65
feat(cli,tui): display extended metadata in info command and catalog TUI
aaronlippold Jan 31, 2026
62446a8
feat(tui): unified 3-tab TUI with DRY config architecture
aaronlippold Jan 31, 2026
4b06f70
feat(tui): Phase 2a - selection, downloaded status, open in browser
aaronlippold Jan 31, 2026
f5a3a00
fix(tui): add Rich Text styling for table indicators
aaronlippold Jan 31, 2026
3dc49c1
feat(tui): enhanced detail pane with Rich Text styling
aaronlippold Jan 31, 2026
06daeee
feat(tui): add Phase 2b view/diff/export actions and reorganize tests
aaronlippold Jan 31, 2026
0e39500
docs(testing): add test organization design decisions
aaronlippold Jan 31, 2026
26cd719
test(tui): add Phase 1 unit tests for MainTUIApp
aaronlippold Jan 31, 2026
a099302
docs: add test organization pattern to CLAUDE.md
aaronlippold Jan 31, 2026
ba0ebcb
fix(tui): eliminate screen flash when opening View/Diff screens
aaronlippold Jan 31, 2026
09949ed
fix(tui): prevent crash when pressing / in ViewScreen/DiffScreen
aaronlippold Jan 31, 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
2 changes: 1 addition & 1 deletion .beads/metadata.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"database": "beads.db",
"jsonl_export": "issues.jsonl"
}
}
1 change: 0 additions & 1 deletion @AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,3 @@ bd sync # Sync with git
- NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds

1 change: 0 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,3 @@ bd sync # Sync with git
- NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds

4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ Authored by: Aaron Lippold<lippold@gmail.com>

New test files (92 tests total): - test_package_data.py: Verify YAML configs included in package (9
tests) - test_auth_windows_fallback.py: Windows permission detection, Firefox fallback (13 tests)

- test_cli_structure.py: Verify auth flags only on auth login (15 tests) -
test_metadata_models.py: CIS Controls and Enhanced Metadata models (30 tests) -
test_xhtml_formatter.py: XHTML element creation and serialization (25 tests)
Expand Down Expand Up @@ -227,6 +228,7 @@ Authored by: Aaron Lippold <lippold@gmail.com>
Session 29-30 documentation cleanup:

Design document reorganization: - Move ARCHITECTURE_PRINCIPLES.md → docs/design/design-principles.md

- Move SYSTEM_ANALYSIS.md → docs/design/handler-reference.md - Move REFACTOR_PLAN.md →
docs/design/xccdf-mapping-design.md - Move FINAL_PLAN.md → docs/design/architecture-decisions.md -
Reduce total from 2,596 to 1,090 lines (58% reduction) - Add Design Documents section to
Expand Down Expand Up @@ -615,6 +617,7 @@ Authored by: Aaron Lippold <lippold@gmail.com>
([`5d8a92b`](https://github.com/mitre/cis-bench/commit/5d8a92bd6756dacc68cc4726f5087f6bdfdd51b9))

Based on working examples from established projects: - Use psf/black@stable with use_pyproject: true

- Use astral-sh/ruff-action@v3 (official action) - Use astral-sh/setup-uv@v5 for UV setup - Use uv
sync for dependency installation - Separate jobs for format, lint, security, and test

Expand Down Expand Up @@ -669,6 +672,7 @@ Authored by: Aaron Lippold <lippold@gmail.com>
for full executable paths - Remove shell=True on Windows (use webbrowser module) - Add subprocess
output capture - Fix type annotation compatibility: - Add __future__ annotations for lxml/Cython
compatibility - Auto-upgrade deprecated typing syntax (ruff --fix): - typing.Union -> X | Y syntax

- typing.List -> list - collections.abc imports - Auto-format code (black) - Fix black regex
pattern in pyproject.toml - Configure bandit to read pyproject.toml config - All checks passing:
black ✓, ruff ✓, bandit ✓, tests ✓ (512 passed)
Expand Down
185 changes: 154 additions & 31 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,56 +14,113 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Essential Commands

### Development
### Development Setup
```bash
# Install with dev dependencies
pip install -e ".[dev]"
# Clone and setup (one-time)
git clone https://github.com/mitre/cis-bench.git
cd cis-bench

# Install uv if not installed
curl -LsSf https://astral.sh/uv/install.sh | sh

# Create .venv and install all dependencies
uv sync --all-extras

# Run full test suite (600+ tests)
pytest tests/
# Install pre-commit hooks
uv run pre-commit install
```

### Running Commands

# Run specific test file
pytest tests/unit/test_catalog_database.py
**IMPORTANT:** This project uses `uv` with a local `.venv`. All commands must use `uv run` to ensure proper environment:

# Run single test
pytest tests/unit/test_catalog_database.py::test_function_name -v
```bash
# Run tests (ALWAYS use uv run)
uv run pytest tests/ # Full suite (1200+ tests)
uv run pytest tests/unit/test_catalog_database.py # Specific file
uv run pytest tests/unit/test_catalog_database.py::test_function_name -v # Single test

# Linting (auto-fix)
ruff check --fix .
ruff format .
uv run ruff check --fix .
uv run ruff format .

# Security scanning
bandit -c pyproject.toml -r src/
uv run bandit -c pyproject.toml -r src/

# Pre-commit hooks
uv run pre-commit run --all-files
```

**Why `uv run`?** The `.venv` contains all dependencies. Running bare `pytest` or `python` uses system Python which may not have dependencies installed.

### Auto-Activation with direnv (Optional)

For automatic venv activation when entering the project directory:

# Pre-commit hooks (run manually)
pre-commit run --all-files
```bash
# Install direnv (one-time)
brew install direnv # macOS
# Add to ~/.zshrc: eval "$(direnv hook zsh)"

# Allow direnv for this project (one-time)
direnv allow

# Now entering the directory auto-activates .venv
cd /path/to/cis-bench # .venv activates automatically
pytest tests/ # Works without uv run!
```

### CLI Usage (Testing Changes)
```bash
# Run via installed package
cis-bench --help

# Run via module (always works)
python -m cis_bench --help

# Key commands
cis-bench auth login --browser chrome
cis-bench catalog refresh
cis-bench search "ubuntu 22"
cis-bench download 23598
cis-bench export 23598 --format xccdf --style cis
cis-bench get "ubuntu 22" --format xccdf
# Run CLI commands via uv
uv run cis-bench --help
uv run cis-bench auth login --browser chrome
uv run cis-bench catalog refresh
uv run cis-bench search "ubuntu 22"
uv run cis-bench download 23598
uv run cis-bench export 23598 --format xccdf --style cis
uv run cis-bench get "ubuntu 22" --format xccdf

# Alternative: Run via module
uv run python -m cis_bench --help
```

### Test Markers
```bash
pytest -m unit # Fast, isolated tests
pytest -m integration # Component integration
pytest -m e2e # Full CLI workflows
pytest -m architecture # Architecture compliance
uv run pytest -m unit # Fast, isolated tests
uv run pytest -m integration # Component integration
uv run pytest -m e2e # Full CLI workflows
uv run pytest -m architecture # Architecture compliance
```

### Test Organization Pattern

**IMPORTANT:** Follow the established test organization pattern when writing new tests.

```
tests/
├── unit/ # Sync tests - isolated components
│ ├── test_main_tui_app.py # MainTUIApp config, bindings
│ └── test_catalog_tab_pane.py # CatalogTabPane bindings, methods
├── integration/ # Async tests - component interaction
│ └── test_main_tui.py # App behavior with run_test()
├── e2e/ # CLI workflow tests
└── regression/ # Architecture compliance
```

**Design Decisions:**
- **Unit tests** (`tests/unit/`): Sync only, no `app.run_test()`, test methods/bindings/config
- **Integration tests** (`tests/integration/`): Async with `app.run_test()`, test full behavior
- **Split mixed files**: If a test file has both sync and async tests, split them

**Example - TUI tests:**
| Component | Unit Tests | Integration Tests |
|-----------|------------|-------------------|
| MainTUIApp | `test_main_tui_app.py` (18 tests) | `test_main_tui.py` (16 tests) |
| CatalogTabPane | `test_catalog_tab_pane.py` (23 tests) | `test_main_tui.py` |

See `docs/developer-guide/testing.md` for full documentation.

## Architecture

### Package Structure (src/ layout)
Expand Down Expand Up @@ -193,3 +250,69 @@ Do NOT push multiple separate commits to main in quick succession. This causes r
- **ruff** - Linting/formatting
- **bandit** - Security scanning
- **pre-commit** - Git hooks

## Beads Task Tracking

This project uses [beads](https://github.com/steveyegge/beads) for task tracking with dependencies.

### Structure: Parent/Child vs Dependencies

| Concept | Command | Purpose |
|---------|---------|---------|
| **Parent/Child** | `--parent <epic-id>` | Organizational grouping - "this task belongs to this epic" |
| **Dependencies** | `bd dep add <task> <blocker>` | Workflow blocking - "can't start until blocker is done" |

**Use BOTH together:**
- `--parent` groups all tasks under an epic (so `bd children <epic>` shows them)
- `bd dep add` enforces implementation order (so `bd ready` shows unblocked work)

### Creating Epics with Tasks

```bash
# 1. Create the epic
bd create "Feature Name" --type epic -d "Full description of the feature"
# Returns: cis-bench-xxx

# 2. Create tasks as children of the epic
bd create "Task 1" --parent cis-bench-xxx --type task
bd create "Task 2" --parent cis-bench-xxx --type task
bd create "Task 3" --parent cis-bench-xxx --type task

# 3. Add dependencies (Task 3 blocked by Task 1 and Task 2)
bd dep add <task-3-id> <task-1-id>
bd dep add <task-3-id> <task-2-id>
```

### Navigation Commands

```bash
bd show <epic-id> # See epic details + vision
bd children <epic-id> # See all tasks under epic
bd epic status <epic-id> # See completion progress (X/Y complete)
bd ready # What can I work on now? (no blockers)
bd blocked # What's waiting on what?
bd dep tree <task-id> # See dependency chain
bd list --parent <epic-id> # Alternative to bd children
```

### Workflow

```bash
# Starting work
bd ready # Find available work
bd show <task-id> # Review task details
bd update <task-id> --status in_progress # Claim it

# Completing work
bd close <task-id> # Mark complete
bd sync # Push to remote
```

### Session Recovery

When starting a new session, recover context with:
```bash
bd ready # See what's available
bd show <current-epic> # Get full context
bd children <current-epic> # See all related tasks
```
Loading
Loading