Skip to content

Latest commit

 

History

History
286 lines (219 loc) · 11.3 KB

File metadata and controls

286 lines (219 loc) · 11.3 KB

Contributing to Formulon

Thank you for considering a contribution. The two most useful things you can give the project today:

  1. Excel oracle data from your locale. This is what keeps Formulon's 1-bit compatibility claim honest. If you have Excel 365 running in a locale we don't yet cover (anything other than Mac ja-JP), one command donates a golden snapshot to the project — see Donating oracle data below.
  2. Bug reports, divergence reports, and code. Standard GitHub PR flow; see Code contributions at the bottom.

Donating oracle data

Requirements: Microsoft 365 only

Oracle data must come from Excel 365 (Microsoft 365 subscription). Office 2019 and earlier are not supported and PRs containing goldens generated against them will not be merged.

Post-2019 functions — ARRAYTOTEXT, LAMBDA, and the entire dynamic-array family (SORT, FILTER, UNIQUE, XLOOKUP, …) — silently return #NAME? on Office 2019 with no warning. Generating goldens on such an install would bake #NAME? into the JSON for every one of those functions, which is the exact failure mode that produced the now-deleted win-2019-ja_JP archive.

The oracle harness enforces this at the tool level: all three generators (oracle-gen, oracle-gen-cf, oracle-gen-workbook) run a startup sentinel that evaluates =ARRAYTOTEXT(1) and aborts with a clear error message if Excel does not recognise it. You should never hit this in practice, but it is your safety net if you accidentally target the wrong install.

Why we ask the community for this

Formulon's 1-bit compatibility is anchored to a single primary oracle: Mac Excel 365 in ja-JP locale. Several Excel function families behave differently across locales and across the Mac/Windows ports, in ways no amount of code review can paper over:

  • Locale-bound text functionsBAHTTEXT (Thai), NUMBERSTRING (Chinese), TEXT with localized format strings, DATEVALUE parsing of locale date strings, weekday/month name output.
  • System-locale-bound formatting — decimal separator (. vs ,), date order (mdy / dmy / ymd), currency symbols, list separator.
  • Mac vs Windows divergences — boundary date arithmetic near the 1900-02-29 phantom leap day, certain [$-...] locale-tag fallbacks, and a handful of text-encoding and rounding edge cases.

The maintainer team can't reproduce these from a single install:

  1. Excel locale isn't a runtime switch. It's tied to system language + Office language pack + (on Windows) registry. Switching requires editing OS settings and restarting Excel — not automatable on a CI runner.
  2. Excel licenses are per-account / per-platform. The maintainer team has Mac Excel 365 ja-JP. Practically and legally, we cannot run "all locales" on one machine.
  3. Authenticity matters. A locale oracle generated by a contributor who actually uses Excel in that locale is more trustworthy than a one-shot reconfiguration. They notice when results look wrong; we wouldn't.
  4. Excel ships monthly updates. Each variant target needs periodic refresh. Distributing this across the community keeps any single update from blocking the project.

If Formulon ever ships a runtime compat_mode switch (Mac ↔ Windows, locale A ↔ locale B), the goldens you contribute are exactly what teaches the engine the right answer in each mode.

What we're collecting

A target name has the shape <host>-<excel-major>-<locale>, with <host>{mac, win} and <locale> in BCP 47 with _ instead of -. The authoritative list is in tools/oracle/targets.yaml. Each entry is tagged with one of:

status meaning
primary the 1-bit reference; maintained by the core team.
scaffolded wired up; goldens may be partial or stale.
wanted reserved slot, no goldens yet. These are exactly what we'd love to receive from you.

Currently reserved as wanted:

  • mac-365-en_US, win-365-en_US
  • win-365-de_DE (decimal-comma locale)
  • win-365-fr_FR (decimal-comma locale)
  • win-365-zh_CN (NUMBERSTRING, localized format codes)
  • win-365-ko_KR
  • win-365-th_TH (BAHTTEXT)

If your locale isn't on this list, see Adding a new target.

Prerequisites

Host Excel Tooling
macOS 12+ Excel 365 (any locale) Python 3.10+ available; make oracle-contribute will bootstrap a venv with xlwings. macOS will prompt for Automation permission the first time — grant it under System Settings → Privacy & Security → Automation → (your terminal) → Microsoft Excel.
Windows 10/11 Excel 365 (any locale) Python 3.10+ from winget install Python.Python.3.12; install xlwings pywin32 pyyaml in that interpreter.
WSL2 on Windows Excel 365 on the Windows side Same as Windows for the Windows-side Python. WSL2 Python only orchestrates and ferries JSON. Export FORMULON_WIN_PYTHON pointing at the Windows-side python.exe so your per-machine path never lands in targets.yaml (e.g. export FORMULON_WIN_PYTHON=/mnt/c/Users/<you>/AppData/Local/Programs/Python/Python312/python.exe).

One-command flow

From a fresh checkout:

make oracle-contribute

That single command:

  1. Bootstraps a Python venv with xlwings (only on first run).
  2. Probes Excel briefly to read your installed version and locale.
  3. Maps your environment to a target name in targets.yaml. If the target isn't tracked yet, it prints how to open an issue to reserve the slot.
  4. Compares versions. If the repository's committed ENVIRONMENT.md for that target was generated against an Excel build at or above yours, it just thanks you and exits. No PR is needed in that case — your contribution would be a no-op refresh.
  5. Otherwise, runs preflight, generates the goldens (15–25 min for the full suite), records ENVIRONMENT.md, and prints exact git commands plus the GitHub PR URL.

If the auto-detection picks the wrong target (you have multi-language Excel installed, or the country code maps ambiguously), override it:

make oracle-contribute TARGET=mac-365-en_US

Verifying your locale

The locale Formulon cares about is Excel's, not the OS's. To check your Excel locale before running:

  • Mac Excel: Excel → Preferences → General → Display Language. The setting must match what's in System Settings → Language & Region for the function results to be self-consistent.
  • Windows Excel: File → Options → Language → Office display language.

If those don't agree, switch one and restart Excel before contributing.

Submitting the PR

After make oracle-contribute finishes successfully, it prints something like:

Done. Your oracle data is on disk -- thank you for the donation!

  Target:   mac-365-en_US
  Locale:   en-US
  Host:     Darwin
  Env file: tests/oracle/variants/mac-365-en_US/ENVIRONMENT.md

  Files git considers new or changed:
    tests/oracle/variants/mac-365-en_US/golden/...
    tests/oracle/variants/mac-365-en_US/ENVIRONMENT.md
    ...

  Next: push your branch and open a PR.

    git checkout -b oracle/mac-365-en_US-2026-04-28
    git add tests/oracle/variants/mac-365-en_US/
    git add tests/oracle/variants/mac-365-en_US/ENVIRONMENT.md
    git add tools/oracle/targets.yaml    # bump status: wanted -> scaffolded
    git commit -m 'test(oracle): contribute mac-365-en_US goldens'
    git push -u origin oracle/mac-365-en_US-2026-04-28

  Then open a PR (oracle template auto-loads):
    https://github.com/libraz/formulon/compare/main...oracle/mac-365-en_US-2026-04-28?expand=1&template=oracle.md

Run those commands as printed. The PR description should include:

  • Your Excel version as shown in Excel → About (paste verbatim).
  • Your OS version (sw_vers -productVersion on Mac, winver on Windows).
  • Confirmation that you ran on real Excel, not a modified driver, and not under a debugger that could have intercepted results.
  • Anything you noticed during generation (warnings, cases that opened Excel dialogs, etc.).

Two-person verify rule for first-time targets

When a target flips from status: wanted to its first real goldens, we ask a second contributor with the same target to regenerate independently and post a git diff against the first PR. Identical output across two independent runs is what justifies labelling the target scaffolded.

If you're the second verifier, run:

git fetch origin pull/<PR-NUMBER>/head:contrib-pr
git checkout contrib-pr
make oracle-contribute TARGET=<target-name>
git diff

A clean diff (only generated_at timestamps and any explicit divergences) is the signal we accept the target.

Refreshing an existing variant

When Excel updates and your installed version is now ahead of the repository, make oracle-contribute will regenerate automatically (version comparison decides). The PR is small in that case — typically ENVIRONMENT.md plus any goldens that actually moved. Call out which results changed in the PR description so reviewers can classify each: bug, ULP drift, or new spec interpretation.

Adding a new target

If your locale isn't yet in targets.yaml, the contribute command prints:

[contribute] derived target name: mac-365-pt_BR
[contribute] this target isn't tracked in tools/oracle/targets.yaml.

Two ways forward:
  1) Open an issue so we can reserve the slot, then re-run:
     https://github.com/libraz/formulon/issues/new?title=Oracle+target%3A+mac-365-pt_BR
  2) Or pass --target=<existing-name> if you intend to map your
     environment onto an already-tracked target.

Open the issue with:

  • The derived target name as printed.
  • Your Excel version and OS.
  • A note about any locale-specific functions you expect divergences in (e.g., pt_BR exercises decimal-comma TEXT and Brazilian date formats).

A maintainer will append a wanted entry to targets.yaml and merge. You can then re-run make oracle-contribute to actually generate.


Code contributions

For bug fixes, new functions, parser improvements, etc.:

  1. Fork, branch off main.
  2. Read CLAUDE.md for the development standards (Expected<T, Error>, no exceptions, RAII, oracle-driven function work).
  3. Run make build && make test (fast suite, ~30s) before pushing.
  4. For functions, add cases to tests/oracle/cases/<category>.yaml and regenerate the primary golden on a Mac (make oracle-gen SUITE=<category>). Reviewers will not merge an unimplemented function PR without oracle coverage.
  5. Open a PR. The default template applies for code; oracle PRs use ?template=oracle.md (the make oracle-contribute output already embeds this).

Bug reports

Issues with a minimal reproducer are easiest to act on:

  • The formula (or the file fragment) that misbehaves.
  • The expected output — and how you obtained it (Mac Excel, Windows Excel, LibreOffice, ...).
  • Formulon's observed output, plus the version of Formulon you're on (formulon_cli --version or the @libraz/formulon package version).
  • For divergences from Excel, ideally a YAML case in the format under tests/oracle/cases/ so we can drop it straight into the suite.

License

By contributing, you agree your contributions are licensed under the project's Apache 2.0 license.