HarperFast / HarperFast/harper
RQL 2.0 conformance: divergence tracking
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
Tracking epic for converging Harper's REST query parsing/execution toward the [RQL 2.0 specification](https://github.com/HarperFast/rql/blob/kris/rql-v2/specification/rql-2.0.md) (spec PR: HarperFast/rql#4). The spec is implementation-independent; this epic is Harper's divergence ledger — each row is either a **bug** (sub-issue), a **feature gap** (sub-issue), or a **permitted representational difference** (no action; Harper conforms via an adapter per spec §8).
## Divergences (as of harper main, 2026-09)
| # | Divergence | Class | Action |
|---|---|---|---|
| 1 | Simple queries (no structural chars) skip parsing; conditions surface as raw name/value pairs (dual shape) | permitted | adapter maps to canonical model |
| 2 | Chains attach as `chainedConditions`; nameless legs (`a=ge=1&=5`) inherit the previous comparator | representational + quirk | adapter; nameless legs are a syntax error in 2.0 — deprecate |
| 3 | Strict/coercive modeled as distinct comparators (`equals`/`not_equal` vs `eq`/`ne`) | permitted | adapter normalizes to value-literal modes (§5.2) |
| 4 | `between` is a first-class comparator | permitted | spec Appendix B alias; desugars to element-scoped `ge`+`le` |
| 5 | Sort is a linked list; select is a polymorphic array with marker props | permitted | adapter |
| 6 | `(4)` on a non-list comparator is the literal string `"(4)"` | tolerance | keep; producers must not rely on it |
| 7 | `prop[]=v` repeated array params | tolerance | spec Appendix B host accommodation |
| 8 | Parse errors deferred into the pipeline (`parseError`) | permitted | §6.1 allows deferred mode |
| 9 | `group-by(...)` accepted at parse and falls through into `sort` (missing `break`) | bug | fix in flight (dispatch `harper-groupby-fallthrough`); 2.0 parse-rejects reserved call names |
| 10 | Chained legs' values never type-coerced on the REST path → mixed-type ranges, silent superset/empty results | bug | #2433 |
| 11 | Indexed `elements` attributes return one result per matching element (duplicates) | bug | #2434 |
| 12 | `contains` matches numbers via decimal-string coercion | divergence | spec §5.1.1: string comparators match only strings; decide keep-as-divergence vs align |
| 13 | No `not(...)` group/scope negation | feature gap | sub-issue below |
| 14 | Element conditions (`prop[=ge=10|=le=2]`) and scoped sub-queries per §5.3 surface | partial | Harper has `prop[cond&cond]`; elem-cond (empty relative path) not supported — fold into not() work or file separately |
Pinning tests for rows 2/10/11/12 landed in #2437. The RQL reference parser + conformance suite (surface string → canonical AST) live on the spec branch; a differential corpus harness is queued (`rql-conformance-corpus-diff`).
Contributor guide
Research direction
Start with the RQL 2.0 specification and the divergence table, then inspect the pinning tests in #2437 and related work in #2433 and #2434. This epic is complete when each divergence has a recorded permitted difference, fix, decision, or linked sub-issue, including the queued conformance corpus harness.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nodejs
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100