# STANDARDS-AXIS REVIEW — fix: correct integer geohash decode for odd bitDepth
Branch: fix/odd-bitdepth-int-decode  vs  master   (single commit faa7061)
Files: main.js (decode_bbox_int rewrite, +25/-14), tests/test.js (+99 tests)

Scope: standards/style only; spec/correctness is the other axis. No eslint/
prettier/tsconfig exist; no CODING_STANDARDS.md. Only authoritative repo
standard source is README.md. Repo style is deliberately pre-ES6.

------------------------------------------------------------------------
HARD FINDINGS (documented-standard divergence)
------------------------------------------------------------------------

H1. README.md:71 vs the new behavior/tests — "Bit depth must be even."
   Quote (README.md:71):
     "...you can specify the `bitDepth` ... which ... **must be used
      consistently when decoding**. Bit depth must be even."
   The diff changes decode_bbox_int to be correct for ODD bitDepth
   (main.js:234-235 `Math.ceil`/`Math.floor` split) and tests now
   actively exercise odd values: tests/test.js bds=[...,5,15,25] (l.263),
   and 5*L prefixes for odd L (l.~210). The implementation + test suite
   now contradict the README's documented "must be even" constraint, and
   the diff does NOT update README.md. This is a documented-standard
   consistency breach: the README statement is left stale. Recommend the
   diff amend README.md:71 (drop/relax "Bit depth must be even") OR
   explicitly note the change is out of doc-scope. (Arguably "must be
   even" was an inaccurate doc all along and the fix corrects behavior,
   but per the brief README rules are the repo standard, so flag it.)

H2. (No other HARD violations.) README.md:66 "capped at 52bits" and
   README.md:69/74/79 bitDepth=52 default are NOT contradicted: code
   still defaults to 52 (main.js:222 `bitDepth = bitDepth || 52`) and
   all new tests stay within bd<=52.

------------------------------------------------------------------------
BASELINE SMELLS (judgement calls — repo standard overrides; none block)
------------------------------------------------------------------------

S1. Duplicated Code — main.js:237-256. The two new loops are the same
   bisection shape (read bit -> halve min or max) applied to lon then
   lat:
     "for (var i = 0; i < lonBits; i++) { var lonBit = get_bit(...);
        if (lonBit === 0) { maxLon = (maxLon + minLon) / 2; }
        else { minLon = (maxLon + minLon) / 2; } }"
     "for (var j = 0; j < latBits; j++) { var latBit = get_bit(...);
        if (latBit === 0) { maxLat = (maxLat + minLat) / 2; }
        else { minLat = (maxLat + minLat) / 2; } }"
   The old code combined both in one loop; the rewrite splits into two
   near-identical loops, growing the duplicated surface. A small
   pre-ES6 helper (bisect on a referenced min/max) would collapse it.

S2. Structural divergence from sibling — main.js:183-201 (string
   decode_bbox) uses one interleaved loop with `isLon = !isLon`; the
   integer version now uses two separate loops. The two parallel
   functions no longer share structure. Acceptable (string path reads 5
   bits/char) but a consistency note.

S3. Mysterious Name — tests/test.js:230-235 use terse abbreviations
   `sb`/`ib` (string/int bbox), `ni`/`ns`/`niLat`/`nsLat` (neighbor
   int/string). They are commented, so low severity.

S4. Copy-paste slip — tests/test.js:263 `bds = [..., 25, 26, ..., 5, 15, 25]`
   lists value 25 twice. Harmless to the test but a stray dupe worth a
   glance (not a standards smell per se).

------------------------------------------------------------------------
CONSISTENT / GOOD (evidence)
------------------------------------------------------------------------
G1. Style matches repo pre-ES6 baseline: main.js keeps `var`, function-
    expression assignment (`var decode_bbox_int = function(...)`), single
    `module.exports`. New tests keep nodeunit form `exports.testX =
    function(test){ ... test.done(); }` matching all existing tests
    (e.g. tests/test.js:7,16,22,29,85,104).
G2. Test helpers `strToInt`/`near` (tests/test.js:177-184) are clean
    function declarations; self-contained cross-check vs the library is
    appropriate for a regression suite.
G3. No Message Chains, Feature Envy, Primitive Obsession introduced.
    No Speculative Generality (no new params/hooks).
G4. Long comment block (main.js:221-233) is verbose but justified for a
    regression-fix rationale; not a violation given no lint config.

------------------------------------------------------------------------
SUMMARY
------------------------------------------------------------------------
1 HARD item: README.md:71 "Bit depth must be even" now contradicted by
both code and tests; diff does not update README. Reconcile the doc.
3-4 judgement-call smells (dup loops, sibling divergence, terse test
names, a stray dupe in the bds array) — none block.
