Skip to content
Closed
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
8 changes: 8 additions & 0 deletions .github/agents/refactor.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: refactor
description: Specializes in code refactoring
model: GPT-5.3-Codex
---
Improve code structure and maintainability.
Preserve existing behavior.
Run relevant tests after changes.
19 changes: 17 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# GitHub Copilot Instructions - Budget Buddy Demo Lab

Budget Buddy is a GH-300 training repository. Treat the codebase as a working demo-start app, not as finished production software.
Budget Buddy is a GH-300 training repository. Treat the codebase as a working
demo app, not as finished production software. The main branch may be used as
the starter baseline; feature branches can capture completed workshop stages.

## Important Context
- The app should run from `python main.py`.
- The starter test suite should pass at roughly 30% coverage.
- The current suite and coverage gate are defined in [pytest.ini](../pytest.ini).
- The trainer will use Copilot to generate tests, fix bugs, review security, refactor performance issues, and update docs.
- Do not remove intentional issues unless the user asks to move toward the completed/reference state.

Expand All @@ -21,3 +23,16 @@ Budget Buddy is a GH-300 training repository. Treat the codebase as a working de
- Edge-case bugs in budget calculations.
- Path traversal gap in JSON file reading.
- O(n^2) transaction processing logic.

When a user explicitly asks to complete a workshop stage, update the issue
ledger and demo documentation to reflect the new state.

## Change Workflow

- Before editing, identify which repository instructions affect the task.
- Add or update tests first when practical.
- Fix the narrowest relevant code path.
- Run `pytest` after code changes.
- Update `README.md` when setup, commands, or user-facing behavior changes.
- Update `CHANGELOG.md` for meaningful user-facing changes.
- Before committing, summarize changed files, tests run, and remaining risks.
22 changes: 11 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
# DEMO TODO (Module 3 - DevOps): this CI workflow is intentionally incomplete.
# Use Copilot to finish the steps so the pipeline installs dependencies and runs pytest.
#
# Suggested goals for the live demo:
# - check out the repository
# - set up Python 3.13
# - install dependencies from requirements-test.txt
# - run pytest with coverage
# Completed Module 3 workflow: install the test environment and run pytest.

name: CI

Expand All @@ -22,8 +15,15 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

# TODO: set up Python 3.13 with actions/setup-python
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: pip
cache-dependency-path: requirements-test.txt

# TODO: install dependencies from requirements-test.txt
- name: Install dependencies
run: python -m pip install -r requirements-test.txt

# TODO: run pytest
- name: Run tests
run: pytest
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ ENV/
.pytest_cache/
.coverage
htmlcov/
*.log

# OS
.DS_Store
Expand Down
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@
"~/.copilot/skills": true,
"~/.claude/skills": true,
"~/.vscode/extensions/synapsevscode.synapse-1.26.0/copilot/skills": true
}
},
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
10 changes: 5 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ changes.
## What this project is

Budget Buddy is a small Python budget tracker used for GitHub Copilot (GH-300)
demonstrations. It is intentionally a **working but immature** app: the happy
path runs, starter tests pass, coverage is low, and realistic TODOs, bugs,
security gaps, and performance issues are left in place as teaching material.
demonstrations. It is intentionally a **working but immature** app. The main
branch provides the starter baseline, while feature branches may capture
completed workshop stages with higher coverage and selected issues resolved.

Do not remove the intentional issues unless the user explicitly asks to move
toward the completed/reference state. If you fix one, update
Expand All @@ -24,8 +24,8 @@ pytest # run tests with coverage gate
pytest --cov=. --cov-report=term-missing
```

The coverage gate lives in [pytest.ini](pytest.ini). It starts at 30 and is
raised to 90 during the unit-test demo.
The coverage gate lives in [pytest.ini](pytest.ini). The starter baseline begins
at 30%; completed workshop branches can raise it as tests are added.

## Conventions

Expand Down
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Revamped the repository into **Budget Buddy**, a working Personal Budget & Expense Tracker demo app for GH-300 delivery.
- Added sample transaction data in [data/sample_transactions.csv](data/sample_transactions.csv).
- Added a sparse starter pytest suite designed to begin around 30% coverage.
- Added focused calculator edge-case and comprehensive data-table tests, raising coverage above the 80% gate.
- Added [DEMO_SCRIPT.md](DEMO_SCRIPT.md) for trainer delivery flow.
- Added [INTENTIONAL_ISSUES.md](INTENTIONAL_ISSUES.md) documenting deliberate bugs, TODOs, security gaps, and performance issues.
- Added reusable Copilot Skills under [.github/skills](.github/skills).
Expand All @@ -19,11 +20,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Replaced arithmetic-only calculator examples with budget calculation helpers.
- Replaced generic data processing examples with transaction processing helpers.
- Replaced generic file examples with CSV/JSON budget data loading helpers.
- Updated pytest configuration to use a demo-start `30%` coverage threshold.
- Restricted file reads and report writes to canonically resolved paths within the configured base directory.
- Refactored expense category grouping to use a single-pass aggregation.
- Completed the Budget Buddy Dockerfile and GitHub Actions test workflow.
- Updated pytest configuration to enforce an `80%` coverage threshold consistently.
- Guarded empty expense averages, zero-expense category percentages, and zero-income savings rates.
- Refreshed README, quick reference, setup script, reset script, and Copilot instructions for the app-centered demo flow.

### Intentional Demo Gaps
- Coverage is intentionally low at the start of the demo.
- Several TODOs and bugs are intentionally present for Copilot-assisted implementation.
- File handling intentionally includes a path traversal risk for security review demos.
- Transaction processing intentionally includes O(n^2) logic for refactoring demos.
26 changes: 15 additions & 11 deletions DEMO_SCRIPT.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ Talking points:
### 2d. Focused context (security example)

The course shows a "review this banking app for security" prompt. The Budget
Buddy equivalent is the path-traversal gap in file handling. Select
Buddy equivalent is reviewing file handling for path traversal. Select
[file_handler.py](file_handler.py) and ask:

```text
Expand All @@ -323,8 +323,9 @@ plain the risk before changing code.
Emphasize how a focused prompt plus repo context produces a better answer than a
vague one.

> Presenter note: the path-traversal gap is in `read_transactions_json`, logged
> in [INTENTIONAL_ISSUES.md](INTENTIONAL_ISSUES.md#L13) (Security row).
> Presenter note: the remediated implementation centralizes canonical path
> containment checks in `_resolve_safe_path`; use repository history when
> demonstrating discovery and remediation of the original gap.

---

Expand All @@ -344,6 +345,10 @@ Open [calculator.py](calculator.py) and implement `forecast_month_end_spend()` o
Transform group_expenses_by_category in data_processor.py into a single-pass aggregation.
```

> Presenter note: the completed implementation performs the aggregation in one
> pass; use repository history when demonstrating the original nested-loop
> implementation.

### 3c. Optimize (performance)

Ask Copilot:
Expand All @@ -363,7 +368,7 @@ Add concise docstrings and type hints to the public methods in calculator.py.

### 3e. DevOps snippets

The repo ships a `Dockerfile` and a CI workflow with intentional TODOs. Ask:
The repo ships a `Dockerfile` and CI workflow for the DevOps exercise. Ask:

```text
Complete the Dockerfile to run Budget Buddy, then finish the GitHub Actions workflow to install deps and run pytest.
Expand Down Expand Up @@ -393,11 +398,10 @@ Generate focused pytest tests for BudgetCalculator edge cases, including empty t

You can also use `@workspace /tests` on a selected function.

> Presenter note: the calculator edge-case bugs (empty expenses, category
> percentage, savings rate) are listed in
> [INTENTIONAL_ISSUES.md](INTENTIONAL_ISSUES.md#L9) (rows 9-11). Input
> validation lives at
> [INTENTIONAL_ISSUES.md](INTENTIONAL_ISSUES.md#L12).
> Presenter note: empty expenses, zero-expense percentages, and zero-income
> savings rates are the starter-state red-green examples. The completed state
> records them under **Resolved Issues** in
> [INTENTIONAL_ISSUES.md](INTENTIONAL_ISSUES.md).

### 4c. Run, verify, and fix (red-green loop)

Expand Down Expand Up @@ -617,8 +621,8 @@ Demo tip: combine them — e.g. `@workspace /tests #file:calculator.py` says

If live generation runs long, implement one narrow slice end to end:

1. Fix `savings_rate()` zero-income behavior (Module 2/4).
2. Add tests for it (Module 4).
1. Start from the calculator's zero-income behavior (Module 2/4).
2. Add the focused regression test and guard (Module 4).
3. Rerun `pytest`.
4. Ask Copilot to summarize the diff (Module 5).

Expand Down
9 changes: 5 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@

FROM python:3.13-slim

# TODO: set WORKDIR
WORKDIR /app

# TODO: copy dependency manifests and install them
COPY requirements-test.txt .
RUN pip install --no-cache-dir -r requirements-test.txt

# TODO: copy the rest of the application
COPY . .

# TODO: define the container entrypoint/command, e.g. python main.py
CMD ["python", "main.py"]
26 changes: 12 additions & 14 deletions INTENTIONAL_ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,15 @@ Budget Buddy starts from a realistic but incomplete codebase. These issues are d

| Module | Area | File | Issue | Demo Value |
| --- | --- | --- | --- | --- |
| 4 | Edge cases | [calculator.py](calculator.py) | Empty expense lists raise `ZeroDivisionError` | Bug fixing + tests |
| 4 | Edge cases | [calculator.py](calculator.py) | Category percentage divides by zero | Defensive programming |
| 4 | Edge cases | [calculator.py](calculator.py) | Savings rate divides by zero when income is zero | Test-driven bug fix |
| 3 | Validation | [data_processor.py](data_processor.py) | Negative amounts and unknown transaction types are accepted | Input validation |
| 2 | Security | [file_handler.py](file_handler.py) | JSON reads do not validate paths | Security review |
| 4 | CSV handling | [file_handler.py](file_handler.py) | Malformed CSV rows fail unclearly | Error handling |

## Performance Issues

| Module | File | Issue | Suggested Improvement |
| --- | --- | --- | --- |
| 3 | [data_processor.py](data_processor.py) | Category grouping mutates a list while using nested loops | Replace with one-pass aggregation |
| 3 | [data_processor.py](data_processor.py) | Duplicate detection is O(n^2) | Use a tuple key and dictionary/set |

## DevOps TODOs (Module 3)

| File | Issue | Suggested Improvement |
| --- | --- | --- |
| [Dockerfile](Dockerfile) | Image build steps are stubbed with TODOs | Complete so `python main.py` runs in a container |
| [.github/workflows/ci.yml](.github/workflows/ci.yml) | CI steps are stubbed with TODOs | Install deps and run pytest on push/PR |

## TODOs For Feature Generation

- `forecast_month_end_spend()` in [calculator.py](calculator.py)
Expand All @@ -35,7 +23,18 @@ Budget Buddy starts from a realistic but incomplete codebase. These issues are d
- `spending_alerts()` in [data_processor.py](data_processor.py)
- `summarize_by_merchant()` in [data_processor.py](data_processor.py)
- `write_transactions_csv()` in [file_handler.py](file_handler.py)
- `_resolve_safe_path()` in [file_handler.py](file_handler.py)

## Resolved Issues

- Budget calculations return `0.0` for empty expense averages, zero-expense
category percentages, and zero-income savings rates.
- File reads and writes in [file_handler.py](file_handler.py) now reject absolute
paths and paths that resolve outside the configured base directory.
- Category grouping in [data_processor.py](data_processor.py) now aggregates
expenses in a single pass.
- [Dockerfile](Dockerfile) now builds a runnable Budget Buddy image.
- [.github/workflows/ci.yml](.github/workflows/ci.yml) now installs test
dependencies and runs pytest on pushes and pull requests.

## Coverage Journey

Expand All @@ -45,7 +44,6 @@ The starter suite intentionally covers only the happy path. Ask Copilot to add t
- zero-income months
- zero-expense months
- malformed CSV rows
- path traversal attempts
- duplicate transactions
- category grouping behavior
- report-building behavior in [main.py](main.py)
Expand Down
9 changes: 2 additions & 7 deletions QUICK_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,9 @@ pytest --cov=. --cov-report=term-missing
| 5 | AGENTS.md / Skills | [AGENTS.md](AGENTS.md), [.github/skills](.github/skills) | Show the agent operating manual and a `SKILL.md` playbook. |
| 5 | PR summary | Git diff | `Summarize this diff as a pull request description.` |

## Intentional Issues
## Remaining Intentional Issues

- `BudgetCalculator.average_expense()` fails on empty expense lists.
- `BudgetCalculator.category_percentage()` divides by zero when total expenses are zero.
- `BudgetCalculator.savings_rate()` divides by zero when income is zero.
- `TransactionProcessor.group_expenses_by_category()` uses inefficient nested loops.
- `TransactionProcessor.find_duplicate_transactions()` uses O(n^2) duplicate detection.
- `TransactionProcessor.validate_transaction()` accepts negative amounts and unknown types.
- `BudgetFileHandler.read_transactions_json()` does not block path traversal.
- CSV parsing lacks clear errors for malformed rows.
- TODOs are present for forecasting, budget alerts, CSV export, safe path resolution, sorting, merchant summaries, and spending alerts.
- TODOs are present for budget alerts, CSV export, sorting, merchant summaries, and spending alerts.
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Budget Buddy - GitHub Copilot Demo Lab

Budget Buddy is a small Python budget tracker designed for Microsoft GH-300 demonstrations. It is intentionally a **working but immature** app: the happy path runs, starter tests pass, coverage is low, and realistic TODOs, bugs, security issues, and performance problems are left for GitHub Copilot to improve.
Budget Buddy is a small Python budget tracker designed for Microsoft GH-300 demonstrations. It is intentionally a **working but immature** app with realistic TODOs and performance problems for GitHub Copilot to improve. This walkthrough branch captures completed security, refactoring, DevOps, and unit-testing exercises.

The goal is to show Copilot as more than autocomplete: codebase explanation, inline edits, agent mode, test generation, debugging, security review, refactoring, documentation, and PR-style summaries.

## Current Demo State

- Runnable app: `python main.py`
- Starter tests: 8 tests
- Current coverage target: about 30%
- Workshop goal: use Copilot to reach 90%+ coverage
- Current tests: 30 tests
- Current coverage: 85%+
- Enforced coverage gate: 80%
- Workshop stretch goal: 90%+ coverage
- Intentional issues: documented in [INTENTIONAL_ISSUES.md](INTENTIONAL_ISSUES.md)
- Trainer flow: documented in [DEMO_SCRIPT.md](DEMO_SCRIPT.md)

Expand Down Expand Up @@ -46,12 +47,12 @@ Budget Buddy reads sample transactions from [data/sample_transactions.csv](data/
| File | Purpose |
| --- | --- |
| [main.py](main.py) | Runnable demo app and report orchestration |
| [calculator.py](calculator.py) | Budget calculations with intentional edge-case bugs |
| [calculator.py](calculator.py) | Budget calculations with guarded zero-denominator edge cases |
| [data_processor.py](data_processor.py) | Transaction filtering, grouping, duplicate detection, and TODOs |
| [file_handler.py](file_handler.py) | CSV/JSON file I/O with an intentional path traversal gap |
| [file_handler.py](file_handler.py) | CSV/JSON file I/O confined to a configured base directory |
| [data_table.py](data_table.py) | Generic table helper used by the app |
| [logger.py](logger.py) | Centralized logging utility |
| [tests](tests) | Sparse starter tests for the coverage journey |
| [tests](tests) | Pytest suite covering calculations, tables, file handling, logging, and processing |

## Demo Flow (GH-300 modules)

Expand Down Expand Up @@ -93,7 +94,9 @@ pytest
pytest --cov=. --cov-report=term-missing
```

During the demo, after Copilot generates enough tests and fixes, change the coverage threshold in [pytest.ini](pytest.ini) from `30` to `90` and rerun `pytest`.
The starter baseline begins at 30%. This walkthrough branch enforces 80%; a
trainer can continue adding tests and raise the threshold to the 90% stretch
goal.

## Trainer Notes

Expand Down
Loading
Loading