diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..7f89a57 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,19 @@ +--- +name: Bug Report +about: Report incorrect behavior +title: "[BUG] " +labels: bug +--- + +## What happened? + +## Expected behavior + +## Steps to reproduce +1. +2. + +## Environment +- Python version (if applicable): +- Node version (if applicable): +- OS: diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..f358724 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/CameronImmesoete/.github/blob/main/SECURITY.md + about: Report security issues privately via GitHub Security Advisories + - name: Note on contributions + url: https://github.com/CameronImmesoete/.github/blob/main/CONTRIBUTING.md + about: Issues and feedback are welcome. Pull requests are not accepted for this repository. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..fdb2235 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,10 @@ +--- +name: Feature Request +about: Suggest an improvement or new feature +title: "[FEATURE] " +labels: enhancement +--- + +## Description + +## Use case diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..f46e082 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,15 @@ +# Copilot Instructions + +When assisting with code in this repository or any CameronImmesoete project: + +- Follow existing code style and patterns in the repo +- Use type annotations (Python: mypy strict, TypeScript: strict mode) +- Write tests for new functions and bug fixes +- Use descriptive variable and function names +- Prefer simple, readable code over clever abstractions +- For Python repos: use uv for package management, ruff for linting, mypy for type checking, pytest for testing +- For TypeScript repos: use npm, eslint, prettier, vitest +- Never commit secrets, API keys, tokens, or credentials +- Commit messages: imperative mood, under 72 characters, explain why not what +- Python repos should configure mypy in pyproject.toml. The shared CI workflow runs `mypy .` which requires project-level configuration. +- One PR per task diff --git a/.github/copilot-review-skill.md b/.github/copilot-review-skill.md new file mode 100644 index 0000000..8f7d52d --- /dev/null +++ b/.github/copilot-review-skill.md @@ -0,0 +1,58 @@ +# Code Review Standards + +Use these criteria when reviewing pull requests across CameronImmesoete repositories. + +## Review Dimensions + +### 1. Correctness +- Does the code do what the PR description claims? +- Are edge cases handled (zero, negative, null, empty, boundary values)? +- Are error paths tested, not just the happy path? +- Do mathematical calculations match the documented formulas? + +### 2. Security +- No secrets, tokens, or credentials in code, config, or comments +- Input validation at system boundaries (user input, file uploads, API responses) +- Dependencies are pinned to specific versions +- No command injection, path traversal, or XSS vectors + +### 3. Test Coverage +- New functions have unit tests covering happy path and edge cases +- Bug fixes include a regression test that fails without the fix +- Tests are deterministic (no flaky assertions, no timing dependencies) +- Test names describe the behavior being verified + +### 4. Code Quality +- Functions do one thing and are named for what they do +- Variable names are descriptive (not `x`, `temp`, `data2`, `result`) +- No dead code, no commented-out blocks, no unreachable branches +- No copy-paste duplication across functions +- Type annotations present where the language supports them + +### 5. Performance +- No O(n^2) loops on unbounded input +- Large files or datasets handled with streaming, not full memory load +- No unnecessary network calls or filesystem I/O in hot paths +- Database queries are indexed and bounded + +### 6. Documentation +- Public APIs and exported functions have docstrings or JSDoc +- Complex logic has inline comments explaining the reasoning (not restating the code) +- README updated if user-facing behavior changes +- No TODOs without a tracking reference (issue number or owner) + +### 7. Regression Risk +- What existing behavior could this change break? +- Are downstream consumers or dependents considered? +- Is there a clear rollback path if problems surface after merge? +- Were before/after behaviors verified for affected workflows? + +## Review Output Format + +For each issue found, include: +- **Severity:** Critical / High / Medium / Low +- **Location:** file path and line number +- **Issue:** what is wrong and why it matters +- **Suggestion:** specific fix or approach to resolve it + +Summarize with: total issue count by severity and an overall recommendation (approve, request changes, or comment only). diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ca79ca5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..55c6a8f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ +## Summary + + +## Testing + + +## Risk + + +## Checklist +- [ ] Tests pass locally +- [ ] Lint passes +- [ ] No new dependencies without justification diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a937354 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + validate: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Validate YAML syntax + run: | + pip install yamllint==1.35.1 + yamllint -d '{extends: relaxed, rules: {line-length: disable}}' .github/workflows/ + + - name: Validate issue templates + run: | + fail=0 + for f in .github/ISSUE_TEMPLATE/*.md; do + echo "Checking $f..." + head -1 "$f" | grep -q "^---" || { echo "FAIL: $f missing frontmatter"; fail=1; } + done + exit $fail + + - name: Check profile README links + run: | + npx markdown-link-check@3.12.2 profile/README.md --retry diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml new file mode 100644 index 0000000..32273a5 --- /dev/null +++ b/.github/workflows/python-ci.yml @@ -0,0 +1,68 @@ +name: Python CI (Reusable) + +on: + workflow_call: + inputs: + python-versions: + description: "Python versions to test" + required: false + type: string + default: '["3.11", "3.12"]' + run-tests: + description: "Whether to run pytest" + required: false + type: boolean + default: true + run-mypy: + description: "Whether to run mypy" + required: false + type: boolean + default: true + coverage-source: + description: "Source directory for coverage (callers should override for their src layout)" + required: false + type: string + default: "." + +permissions: + contents: read + +jobs: + ci: + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + python-version: ${{ fromJson(inputs.python-versions) }} + env: + UV_PYTHON: ${{ matrix.python-version }} + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Install uv + uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4.2.0 + with: + enable-cache: true + + - name: Set up Python ${{ matrix.python-version }} + run: uv python install ${{ matrix.python-version }} + + - name: Install dependencies + run: uv sync --extra dev + + - name: Lint + run: uv run ruff check . + + - name: Format check + run: uv run ruff format --check . + + - name: Type check + if: inputs.run-mypy == true + run: uv run mypy . + + - name: Test + if: inputs.run-tests == true + env: + COVERAGE_SOURCE: ${{ inputs.coverage-source }} + run: uv run pytest tests/ -v --tb=short --cov="$COVERAGE_SOURCE" --cov-report=term-missing diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c11f44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# OS +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Python +__pycache__/ +*.pyc +*.pyo +.venv/ +dist/ +*.egg-info/ +.mypy_cache/ +.ruff_cache/ +.pytest_cache/ +.coverage +htmlcov/ + +# Secrets +.env +.env.* +!.env.example +*.pem +*.key diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..220504a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,31 @@ +# Agent Guidelines + +## PR Rules +- One PR per branch. One branch per task. +- Never close a PR to open a replacement. Fix in place. +- Never push directly to main. +- Squash merge only. +- Branches auto-delete after merge. +- Branch naming: `user/CameronImmesoete/` + +## CI Requirements +- All CI checks must pass before merge. +- No `[skip ci]` commits unless pure documentation. +- If CI is red on main, fix it before other work. + +## Security +- Never commit secrets, API keys, tokens, or credentials. +- Never add dependencies without justification. +- Never force push to main. +- Run tests before pushing. + +## Code Quality +- Tests required for all new functions. +- Lint must pass (ruff for Python, eslint for TypeScript). +- Type checks must pass (mypy for Python, tsc for TypeScript). +- Prefer simple, readable code over clever abstractions. + +## Shared Workflows +- Python repos can use the reusable CI workflow: `uses: CameronImmesoete/.github/.github/workflows/python-ci.yml@main` # @main is used here because this IS the source repo; downstream callers should pin to a release tag or commit SHA + - Note: The doubled `.github` is intentional. The first is the repo name (`CameronImmesoete/.github`), the second is the workflows directory within it (`.github/workflows/`). +- **Pinning policy:** `@main` is temporary during initial setup. Once the repo has a stable first release, all downstream callers must pin to a tagged release or specific commit SHA (e.g., `@v1.0.0` or `@abc1234`). Never use `@main` in production workflows. Update callers when the shared workflow changes by bumping the pinned reference. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..13fa51e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,37 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +## Our Standards + +Examples of behavior that contributes to a positive environment: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior: + +* The use of sexualized language or imagery, and sexual attention or advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by opening a discussion on the relevant repository or contacting the maintainer through GitHub. All complaints will be reviewed and investigated promptly and fairly. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..04e4f78 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,65 @@ +# Contributing + +This is a solo project maintained by [Cam Immesoete](https://github.com/CameronImmesoete). External contributions are not accepted. Pull requests from outside contributors will be closed. + +Found a bug or have a feature idea? [Open an issue](../../issues/new/choose). + +The standards below document how I contribute to my repos. They exist for consistency, not collaboration. + +## Branch Naming + +``` +user/CameronImmesoete/ +``` + +Descriptors are kebab-case, 3-6 words, describe the outcome not the activity. + +## Pull Requests + +- One PR per branch. One branch per task. +- All PRs start as drafts. +- Never close a PR to open a replacement. Fix in place. +- Squash merge only. +- Branches auto-delete after merge. +- Every PR includes: a summary, what was tested, and what could break. + +## Local Validation + +### For downstream Python repos: + +The commands below apply to Python repos that use the shared `python-ci.yml` workflow. This `.github` repository contains configuration only and has no Python code to validate. + +Run before every push in a downstream repo: + +```bash +uv run ruff check . +uv run ruff format --check . +uv run mypy . +uv run pytest tests/ -v --tb=short +``` + +All must pass. No exceptions. + +## Commit Messages + +Imperative mood, present tense, first line under 72 characters. + +Good: `Prevent division by zero in break-even calculator` +Bad: `fix bug` / `Update stuff` / `hopefully this works` + +No hedging. No fix-the-fix chains. Squash before opening the PR. + +## Code Quality + +| Tool | Purpose | Config | +|------|---------|--------| +| uv | Package management | `pyproject.toml` | +| ruff | Linting and formatting | `pyproject.toml` | +| mypy | Static type checking (strict) | `pyproject.toml` | +| pytest | Testing + coverage | `pyproject.toml` | + +Tests required for all new functions. No new dependencies without justification. + +## License + +This project is licensed under the MIT License. See [LICENSE](LICENSE) for details. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8cf30d0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Cam Immesoete + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..7b4a03e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Security + +If you discover a security vulnerability in any of my projects, please report it responsibly. + +You can report vulnerabilities privately using GitHub's built-in [security advisory feature](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability) on the affected repository. + +Please do not open a public issue for security vulnerabilities. I will respond within 48 hours and work with you to understand and address the issue. diff --git a/profile/README.md b/profile/README.md new file mode 100644 index 0000000..66aa666 --- /dev/null +++ b/profile/README.md @@ -0,0 +1,28 @@ +# Hi, I'm Cam + +Software Engineer at Microsoft. Berkeley Haas EWMBA candidate. I like building things that sit at the intersection of software engineering and business analytics. + +## What I'm Working On + +**Interactive MBA Calculators.** Browser-based calculators powered by Pyodide (Python running in WebAssembly). The conjoint analysis tool handles full-profile generation, OLS regression, and attribute importance scoring in the browser with zero backend. + +- [marketing_calculators](https://github.com/CameronImmesoete/marketing_calculators): conjoint analysis, CLV, break-even, CAC, churn rate, NPS, ROMI +- [macroeconomics_calculators](https://github.com/CameronImmesoete/macroeconomics_calculators): IS-LM, AD-AS, Phillips Curve, fiscal multiplier, exchange rate, BoP +- [microeconomics_calculators](https://github.com/CameronImmesoete/microeconomics_calculators): supply and demand, elasticity, consumer/producer surplus, market equilibrium + +## Other Projects + +- [TensorGAN](https://github.com/CameronImmesoete/TensorGAN): generative adversarial network experiments +- [STT-TTS-Demo](https://github.com/CameronImmesoete/STT-TTS-Demo): speech-to-text and text-to-speech demo +- [cam-neurosity-tools](https://github.com/CameronImmesoete/cam-neurosity-tools): BCI tooling for Neurosity devices +- [Cam-TensorFlow-Experiments](https://github.com/CameronImmesoete/Cam-TensorFlow-Experiments): TensorFlow experiments +- [Pascal](https://github.com/CameronImmesoete/Pascal): Pascal language projects + +## Tech + +Python (numpy, pandas, scikit-learn, matplotlib), TypeScript, Pyodide. New repos use CI with ruff, mypy, and pytest. + +## Links + +- [immesoete.cam](https://immesoete.cam) +- [LinkedIn](https://www.linkedin.com/in/cameronimmesoete/)