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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ All notable changes to Fair Code are documented here, newest first.
- **End-to-end test coverage for intersectional reporting and `run_benchmark()`** (closes #271) - the two-protected-attribute fairness-reporting block and the `run_benchmark()` discovery/seeding entrypoint were both untested; existing tests only used the one-attribute fixture and called the lower-level `run_audit()` directly. Uses Insurance Denial (1,341 rows, age × gender) - the smallest real two-attribute audit.

### Fixed
- **`scripts/render_terminal_png.py` hardcoded a macOS-only font path** (closes #323, by [@Ayaan-20-11](https://github.com/Ayaan-20-11), [#331](https://github.com/yakew7/Fair-Code/pull/331), first merged PR) - `FONT_PATH` was `/System/Library/Fonts/Menlo.ttc`, which crashed with an opaque PIL `OSError` on any non-macOS contributor's machine. Now resolves to the repo-bundled `assets/fonts/IBMPlexMono-Regular.ttf`, the same font `generate_og_images.py` already uses for exactly this reason.
- **Web profiler's reference-file picker strands keyboard focus** (closes #303) - every other file-picker path already returned focus to a visible element after the hidden input's native picker closed; the reference-baseline input was the one exception.
- **Web profiler mis-parses a records-orientation JSON file as CSV without a `.json` extension** (closes #304) - the content sniff only checked for a leading `{`; `E.parseJSON()` already handled the records-array branch correctly, it just never got the chance to run.
- **Web profiler's compare view scroll-jacks the page on every column-mapping change** (closes #305) - `profiler-ui.js`'s single-dataset view already gated its scroll behind an explicit flag for exactly this reason; `profiler-compare.js` had no equivalent.
Expand Down
14 changes: 12 additions & 2 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ ordered by merged PR count, most first - ties broken by commit count, then by ea
date. Within each entry, the PR numbers link the claim to the actual diff, so nothing here is an
unverifiable "thanks to".

**Snapshot:** 2026-08-27, covering everything merged through **PR #330**.
**Snapshot:** 2026-08-28, covering everything merged through **PR #331**.
Anything merged after that date is real and welcome, but is not yet reflected here - the
[contributors graph](https://github.com/yakew7/Fair-Code/graphs/contributors) is always the live
source of truth, and the `contrib.rocks` grid above regenerates from it automatically.
Expand Down Expand Up @@ -233,6 +233,15 @@ inside `profile()`/`compare()`, so `tests/test_js_parity.py`'s `==` comparison o
no change ([#330](https://github.com/yakew7/Fair-Code/pull/330), relates to issue #327). Documented as
new SPEC.md section 10; `--no-provenance` restores the pre-existing export shape exactly.

### Ayaan Kapoor - [@Ayaan-20-11](https://github.com/Ayaan-20-11)

**1 merged PR · 1 commit · first merged 2026-08-28**

Fixed `scripts/render_terminal_png.py`'s hardcoded macOS-only font path
(`/System/Library/Fonts/Menlo.ttc`), which crashed with an opaque PIL `OSError` on any non-macOS
contributor's machine. Now resolves to the repo-bundled `assets/fonts/IBMPlexMono-Regular.ttf`,
the same font `generate_og_images.py` already uses for exactly this reason ([#331](https://github.com/yakew7/Fair-Code/pull/331), closing issue #323).

---

## Contributions by area
Expand All @@ -247,7 +256,7 @@ A cross-cut of the same work, for anyone looking for who to ask about what.
| **Profiler - web** (`profiler.html`, `assets/profiler-*.js`) | [@yakew7](https://github.com/yakew7), [@ahmdkaml](https://github.com/ahmdkaml), [@ImMortaL0P](https://github.com/ImMortaL0P), [@AnayDhawan](https://github.com/AnayDhawan), [@Shreyash0712](https://github.com/Shreyash0712) |
| **Benchmark harness & paper freeze** | [@yakew7](https://github.com/yakew7), [@ahmdkaml](https://github.com/ahmdkaml) |
| **CI & workflows** (`.github/`) | [@yakew7](https://github.com/yakew7), [@ahmdkaml](https://github.com/ahmdkaml), [@cannotdoit13](https://github.com/cannotdoit13), [@Shreyash0712](https://github.com/Shreyash0712), [@evanjain-dot](https://github.com/evanjain-dot), [@propcgamer20-png](https://github.com/propcgamer20-png), [@Swastik-Yadav](https://github.com/Swastik-Yadav) |
| **Website & explainer build** | [@yakew7](https://github.com/yakew7), [@anujkamdar](https://github.com/anujkamdar), [@Swastik-Yadav](https://github.com/Swastik-Yadav) |
| **Website & explainer build** | [@yakew7](https://github.com/yakew7), [@anujkamdar](https://github.com/anujkamdar), [@Swastik-Yadav](https://github.com/Swastik-Yadav), [@Ayaan-20-11](https://github.com/Ayaan-20-11) |
| **Tests** (`tests/`) | [@yakew7](https://github.com/yakew7), [@ahmdkaml](https://github.com/ahmdkaml), [@tomatotomata](https://github.com/tomatotomata), [@ImMortaL0P](https://github.com/ImMortaL0P), [@evanjain-dot](https://github.com/evanjain-dot), [@propcgamer20-png](https://github.com/propcgamer20-png), [@mahirhir](https://github.com/mahirhir) |
| **Contributor tooling & docs** | [@yakew7](https://github.com/yakew7), [@propcgamer20-png](https://github.com/propcgamer20-png), [@ahmdkaml](https://github.com/ahmdkaml), [@Swastik-Yadav](https://github.com/Swastik-Yadav), [@Circout-sudo](https://github.com/Circout-sudo), [@nivedmahendran](https://github.com/nivedmahendran) |

Expand Down Expand Up @@ -288,6 +297,7 @@ makes `git shortlog -sne` reconcilable with the list above.
| [@TanishGoyal-Dev](https://github.com/TanishGoyal-Dev) | `TanishGoyal-Dev` |
| [@shwetagupta1234](https://github.com/shwetagupta1234) | `shwetagupta1234` |
| [@Circout-sudo](https://github.com/Circout-sudo) | `Yojeet` |
| [@Ayaan-20-11](https://github.com/Ayaan-20-11) | `Ayaan Kapoor` - commit email is a local hostname (`ayaankapoor@Mac.lan`), not linked to the GitHub account, so [#331](https://github.com/yakew7/Fair-Code/pull/331) doesn't register in the repo's contributors graph despite being a real merged PR |

If your name is wrong, missing, or you would rather be listed under a different handle, or not
listed at all, open an issue or a one-line PR against this file. It gets merged, no questions asked.
Expand Down
14 changes: 8 additions & 6 deletions METRICS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# Fair Code - Metrics Tracker

![Stars](https://img.shields.io/badge/Stars-47-brightgreen?style=flat-square&logo=github)
![Contributors](https://img.shields.io/badge/Contributors-19-blue?style=flat-square)
![Forks](https://img.shields.io/badge/Forks-24-orange?style=flat-square)
![Contributors](https://img.shields.io/badge/Contributors-20-blue?style=flat-square)
![Forks](https://img.shields.io/badge/Forks-25-orange?style=flat-square)
![Watching](https://img.shields.io/badge/Watching-8-yellow?style=flat-square)
![Explainers](https://img.shields.io/badge/Explainers-47-blueviolet?style=flat-square)
![Countries](https://img.shields.io/badge/Countries-18-informational?style=flat-square)
Expand Down Expand Up @@ -40,7 +40,7 @@ Weekly snapshot of project health. Updated every Friday.
| 2026-W32 | 42 | 22 | 8 | 14 | 26K+ total | 17 | 11 | 7 total |
| 2026-W33 | 43 | 21 | 8 | 15 | 27K+ total | 17 | 55 | 7 total |
| 2026-W34 | 43 | 22 | 8 | 17 | 30K+ total | 18 | 35 | 7 total |
| 2026-W35 | 47 | 24 | 8 | 19 | 30K+ total | 18 | 31 | 7 total |
| 2026-W35 | 47 | 25 | 8 | 20 | 30K+ total | 18 | 32 | 7 total |

> **2026-W27 - v1.2.0 shipped:** Open Dataset Profiler (CLI + client-side web tool) released; 23 explainers total.
>
Expand Down Expand Up @@ -71,6 +71,8 @@ Weekly snapshot of project health. Updated every Friday.
> **2026-W35 (later in week) - all 12 open non-explainer issues closed:** #247 (`--proxy-hints` on `compare`), #251 (stdin support), #284 (web profiler advanced-thresholds panel), #302 and #271 (test coverage for `compare_to_html` and `benchmark.py`'s intersectional/`run_benchmark()` paths), #303-#306 (four web profiler bugs: keyboard focus, JSON-without-extension detection, compare-view scroll-jacking, same-dimension crossing), #301 (`--map` unknown-column error), #286 (`build-explainers.yml` trigger gap), and #309 (a ROADMAP/README contradiction) - each committed and pushed individually, verified with tests/manual CLI runs before every commit. Also credited [@propcgamer20-png](https://github.com/propcgamer20-png)'s bundled #314 (closing #300, #307, #308, #310, merged the same day). No numeric changes this note - same live GitHub snapshot as the entry above, just a lot more closed issues.
>
> **2026-W35 (weekend update) - a 12-issue re-seed, then the first one closed:** with the backlog cleared, 12 fresh non-explainer issues were opened (#315-#326) covering real, independently-reproduced gaps - a Python/JS parity break in age-band labeling on date columns (#315), literal NUL bytes in `profiler-engine.js` that hide the file from plain `grep` (#316), a silently-misparsed split-orient JSON shape (#317), a spurious 100%-drift false positive when a column auto-detects to different kinds across two datasets (#318), a `parse_reference()`/JS parity break on percent-formatted shares (#319), plus several smaller CLI/report/tooling gaps (#320-#326). Separately, a contributor conversation about wanting to verify a profiler result after the fact - "was this actually produced from this dataset, these thresholds, this version of the tool" - turned into three more issues (#327-#329) once the code confirmed the gap was real: `to_json()` echoed none of that. New contributor [@mahirhir](https://github.com/mahirhir) closed the first one same-day: `faircode/provenance.py` (#330) attaches a `provenance` block - dataset SHA-256, `faircode` version, resolved params - to `--json` exports, at the export boundary so the JS-parity test needs no change. **Contributors `18 → 19`** (mahirhir's first merged PR, counted from `CONTRIBUTORS.md` - the raw API still lags). Forks `23 → 24` (live GitHub numbers). Stars, watching, countries, and social reach unchanged.
>
> **2026-W35 (later still) - the MCP server ships, `faircode` goes live on PyPI, and a second same-week new contributor:** Phase 1 of the MCP plan discussed for #327-#329 landed - `faircode/mcp_server.py` exposes `profile_dataset`, `compare_datasets`, and `proxy_hints` as MCP tools over stdio, a thin adapter over the existing `profile()`/`compare()`/`proxy_hints()` functions with no new analysis logic and the same local-only trust boundary as the CLI. `faircode` was then published to PyPI for the first time (`pip install faircode` / `faircode[mcp]` now work without cloning the repo). New contributor [@Ayaan-20-11](https://github.com/Ayaan-20-11) fixed `scripts/render_terminal_png.py`'s hardcoded macOS-only font path (#331, closing #323) - it now uses the repo-bundled `assets/fonts/IBMPlexMono-Regular.ttf`, the same font `generate_og_images.py` already uses. **Contributors `19 → 20`** (Ayaan's first merged PR). Forks `24 → 25` (live GitHub numbers). Stars, watching, countries, and social reach unchanged.

---

Expand All @@ -79,12 +81,12 @@ Weekly snapshot of project health. Updated every Friday.
| Metric | Current | Target | Timeline |
|--------|--------:|-------:|----------|
| Stars | 47 | 50+ | End of 2026 |
| Forks | 24 | 25+ | End of 2026 |
| Forks | 25 | 25+ | End of 2026 |
| Watching | 8 | 12+ | End of 2026 |
| Contributors | 19 | 20+ | End of 2026 |
| Contributors | 20 | 20+ | End of 2026 |
| Social reach | 30K+ | 40K+ | End of 2026 |
| Countries reached | 18 | 20+ | End of 2026 |
| Issues closed | 31 (past 7 days) | Track weekly | Ongoing |
| Issues closed | 32 (past 7 days) | Track weekly | Ongoing |
| Code audits | 7 | 8+ | End of 2026 |
| Explainers | 47 | 60+ | End of 2026 |

Expand Down
4 changes: 4 additions & 0 deletions faircode/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ def main(argv: list[str] | None = None) -> int:
print("error: --cross expects two column names: COLA,COLB",
file=sys.stderr)
return 2
if parts[0] == parts[1]:
print("error: --cross needs two different columns, got "
f"'{parts[0]}' twice", file=sys.stderr)
return 2
opts["cross"] = parts
if args.reference:
try:
Expand Down