# From paperless-ngx docs/usage.md (current HEAD) search section, plus the
# v2-era docs/usage.md (git show aed9abe48^:docs/usage.md), plus the
# end-to-end acceptance scenarios in tests/emitter/test_acceptance_e2e.py.
#
# See corpus_paperless.txt's header for the section-marker convention and
# `pytest tests/differential -rs` for the authoritative per-query skip
# reason.

# --- compared -------------------------------------------------------------
shopname AND (product1 OR product2)
type:invoice tag:unpaid
correspondent:university certificate
added:yesterday
modified:today
produ*name
added:today
modified:yesterday
created:"previous week"
added:"previous month"
modified:"this year"
tag:billing AND (title:2020 OR (NOT title:2019 AND NOT title:2018 AND created:[2020 TO 2020]))
shopname product1
Wär*
tag:foo,bar
has_tag:false
has_tag:''
-foo

# --- empty-group drop: empty groups are dropped at parse time rather than
# annihilating the enclosing query.
shopname ()
NOT ()
shopname (() ())

# --- quoted-star existence: a quoted star on a numeric or boolean field is an
# existence match, matching the unquoted field:* form. has_tag:"*"
# (double-quoted, a Phrase) is deliberately not included here: real
# whoosh itself raises (not a NullQuery, a bare Exception) trying to
# process_text() a double-quoted phrase against a BOOLEAN field, which
# has no analyzer (whoosh/fields.py's BOOLEAN.tokenize) -- a whoosh
# crash, not a whoosh-compat defect, and there is no oracle result to
# compare against. Covered directly instead, without the oracle, by
# tests/emitter/test_emit_phrase.py's
# test_quoted_star_phrase_matches_unquoted_star.
type_id:'*'
type_id:"*"
has_tag:'*'

# --- unsupported-pattern diagnostics: a wildcard/prefix pattern on a numeric field, or a
# BOOLEAN_EXISTS field (reopened), is diagnosed at parse time
# (DIVERGENCES.md entry 29); these skip via the existing entry 6
# diagnostics-present check like any other parse-time diagnostic.
type_id:1*
type_id:1?
type_id:1[2-3]*
has_tag:t*
has_tag:tr?e
has_tag:[t-t]rue*

# --- KNOWN DIVERGENCE (whoosh-bug, allowlist.py): bracketed date ranges
# (see corpus_paperless.txt's matching section for the root cause).
created:[2005 to 2009]
created:[2020 to]
added:[now-7d TO now]
added:[-1 week to now]

# --- Unquoted multi-word natural-date keyword: an ordinary compared line
# since whoosh-compat's grammar joins the phrase itself (see
# corpus_paperless.txt's matching section).
created:previous month

# --- KNOWN DIVERGENCE (design, allowlist.py): JSON dotted-path fields.
# v3-only concept (FieldRegistry.resolve_json / a JSON FieldSpec) with
# nothing in the v2 whoosh schema to register it against; on both sides the
# field is "unknown", but the two parsers' fieldname taggers handle an
# unregistered dotted name differently (whoosh-compat's tagger is
# deliberately dot-inclusive so real JSON-configured registries *can*
# resolve "notes.user:"). See allowlist.py's matching entry.
custom_fields.value:policy
custom_fields.name:"Contract Number"
custom_fields.name:Insurance custom_fields.value:policy
custom_fields.value:1312
custom_fields.name:"Contract Number" custom_fields.value:1312
notes.user:alice
notes.note:reminder
notes.user:alice notes.note:insurance
# The same tagger-cut difference applies to any dotted run followed by a
# colon, registered or not: whoosh-compat reads "ab.cd:9" as one rejected
# candidate folded onto its value, real whoosh only ever matches "cd:" and
# leaves "ab." attached to whatever precedes it.
title:ab.cd:9 OR x
ab.cd:ef

# --- compared: comma_values quote-escape (design, DIVERGENCES.md entry 17)
# is a whoosh-compat-only feature at the raw parse-tree level (real whoosh's
# KEYWORD(commas=True) analyzer always splits on commas, quoted or not), but
# the differential harness's own forward-analysis step re-runs the same
# comma-splitting analyzer on both sides before comparing, so this line
# compares and passes structurally; see DIVERGENCES.md entry 17 for why
# there is deliberately no allowlist.py entry for it.
tag:'foo,bar'

# --- KNOWN DIVERGENCE (design, allowlist.py, DIVERGENCES.md entry 36): a
# comma-values field boost attaches to the whole split group in
# whoosh-compat (CommaValuesPlugin's split runs before BoostPlugin binds the
# boost) but to each split term individually in real whoosh (KEYWORD's
# comma split happens at analysis time, after the boost is already bound to
# the single unsplit term). Matched-document sets and summed relevance
# scoring are identical either way; see the DIVERGENCES.md entry for the
# verified arithmetic.
tag:alpha,beta^2

# --- KNOWN DIVERGENCE (design, allowlist.py): bare field:* simplifies to
# Every(field) in whoosh-compat vs a literal Wildcard('*') in whoosh.
title:*

# --- paperless-ngx#13568: v2->v3 migration broke saved views using bracket-class
# wildcards like "title:*202[0-3]". Both queries below are verbatim from the
# report (the second is the 2025 variant of the first).
tag:steuer AND tag:valentin AND (title:*2024 OR (NOT title:*202[0-3] AND NOT title:*201[0-9] AND created:2024))
tag:steuer AND tag:valentin AND (title:*2025 OR (NOT title:*202[0-3] AND NOT title:*201[0-9] AND created:2025))

# --- KNOWN DIVERGENCE (whoosh-bug, allowlist.py): trailing-star bracket
# fold (DIVERGENCES.md entry 13). Real whoosh's Wildcard.normalize() only checks for
# "*"/"?" (despite SPECIAL_CHARS = "*?["), so a trailing-star pattern
# containing a character class folds to a Prefix that silently drops the
# class body: Prefix('title', '202[0-3]') instead of keeping the class.
# whoosh-compat fixed this fold once, in parser/plugins.py's
# folds_to_prefix (shared by both sites that perform it), so it keeps the
# full Wildcard('title', '202[0-3]*') pattern instead. See
# tests/emitter/test_acceptance_e2e.py for the same bug demonstrated at the
# search-result level.
title:202[0-3]*

# --- KNOWN DIVERGENCE (design, allowlist.py): a whitespace-padded quoted
# BOOLEAN_EXISTS value (DIVERGENCES.md entry 33). Real whoosh's unstripped
# trues/falses check falls through to bool(qstring), True for any non-empty
# string; whoosh-compat strips before the same check, so identical padded
# text reads False instead.
has_tag:'  false  '
has_tag:'F '

# --- KNOWN DIVERGENCE (whoosh-bug, allowlist.py): trailing-star bracket
# fold (DIVERGENCES.md entry 13), unfielded/multifield-expanded form. Same
# root cause as title:202[0-3]* above, but with no "field:" prefix at all,
# and a reversed (rather than merely non-numeric) character class: the
# existing allowlist pattern originally required an explicit field prefix
# and was broadened after the expanded generator found this shape.
x[z-a]*

# --- KNOWN DIVERGENCE (design, allowlist.py): "attrs" is a JSON field
# registered only on whoosh-compat's side (DIVERGENCES.md entry 14,
# extended), added purely so the generator can reach JSON subpath
# pattern/existence vocabulary; real whoosh has no such field at all.
attrs.user:alice
attrs.user:*

# --- KNOWN DIVERGENCE (design, allowlist.py): "release_date" is a
# date_only field registered only on whoosh-compat's side (DIVERGENCES.md
# entry 37); real v2 whoosh has no date-vs-datetime distinction and no such
# field at all.
release_date:'2020-03-15 15:30'

# --- KNOWN DIVERGENCE (whoosh-bug, allowlist.py): a double-quoted value on
# a BOOLEAN_EXISTS field crashes real whoosh at parse time (DIVERGENCES.md
# entry 38, DivergenceKind.ORACLE_ERROR): BOOLEAN fields have no analyzer,
# but PhrasePlugin unconditionally tries to tokenize through one.
has_tag:"true"

# --- KNOWN DIVERGENCE (design, allowlist.py): U64 accepts the full 64-bit
# domain (DIVERGENCES.md entry 39); real v2 whoosh's NUMERIC fields default
# to bits=32 and silently fail to parse a value at or above 2**32 (unsigned
# fields like asn) or 2**31 (signed fields, the library default, like id).
asn:4294967296
id:2147483648

# --- KNOWN DIVERGENCE (design, allowlist.py): entry 33's whitespace-padded
# quoted BOOLEAN_EXISTS reading applies to every registered BOOLEAN_EXISTS
# field, not just has_tag; the allowlist entry was broadened accordingly.
has_correspondent:'  false'

# --- CONFIRMED PARITY: entry 23's match-all face used to diverge here
# (an unfielded match-all ANDed with a term whose analyzer
# drops every token collapsed to Nothing() in whoosh-compat, stayed
# Every() in real whoosh: the normalize pass ahead of analysis dropped
# the unfielded Every as the And identity before analysis ever got a
# chance to protect it from the sibling that was about to empty out).
# Fixed: normalize() itself now holds that drop back while any surviving
# sibling is a fielded leaf analysis has not resolved yet, so the Every is
# still there when the real analysis pass learns the sibling's fate. Kept
# as live, ordinary comparisons (not removed) to pin the fix: see
# DIVERGENCES.md entry 23's "match-all face" subsection. The parenthesized
# spelling is the one that stayed broken for a caller who normalized the
# tree itself before analyzing it.
*:* title:the
(*:*) AND (title:the)

# --- KNOWN DIVERGENCE (design, allowlist.py): entry 20's other star-soup
# face. "*:**" is read by whoosh's FieldsPlugin as the unfielded match-all
# "*:*" plus a leftover bare "*", which becomes a literal Wildcard("*") per
# default field on the oracle side and Every(field) on whoosh-compat's: a
# genuine entry-20 divergence that the "*:*" carve-out's neighbourhood left
# unclaimed, i.e. a shape an unlucky fuzz draw could have failed CI with on
# a published library. Asserted here rather than left to chance. Exactly two
# trailing stars: "*:***" compares EQUAL and is deliberately not claimed.
*:**
**:**

# --- KNOWN DIVERGENCE (design, allowlist.py): entry 20's remaining
# star-soup neighbourhood, closed narrowly rather than swept into the two
# entries above. Two mechanisms, each measured directly against the oracle
# rather than assumed from the shape:
#
# "**:" / "**::" / "**:::" (star-run then colon-run, no trailing star):
# same Every(field)-vs-Wildcard('*') leaf-type divergence as "*:**"/"**:**"
# above, just with zero trailing stars instead of two.
**:
**::
**:::

# ":*:**" / "**:*:" (a leading bare ":"): whoosh's own grammar binds the
# leading ":" to a single schema field (a literal Term), while
# whoosh-compat multifield-expands the same bare ":" into an Or of one Term
# per default field. A different node shape, not a leaf-type swap; kept
# separate from the family above rather than generalized past what was
# measured.
:*:**
**:*:

# --- KNOWN DIVERGENCE (whoosh-bug, DIVERGENCES.md entry 57, allowlist.py):
# an unquoted value with two consecutive colon-fieldname-looking segments
# where neither is a real field. The tagger produces FieldnameNode("aa"),
# FieldnameNode("bb"), WordNode("cc"); real whoosh's do_fieldnames keeps
# only the most recently rejected candidate and silently drops "aa:", so
# the oracle reads this as the two words "bb"/"cc" per default field.
# whoosh-compat's fixed do_fieldnames accumulates every rejected
# candidate's text instead, keeping the literal "aa:bb:cc" the user typed.
# The same bug is reached by any two rejected candidates in a row, whatever
# the segments say: in "zzz:and:9" the discarded "zzz:" leaves the oracle
# reading the value as "and:9", with no trace of what the user typed.
aa:bb:cc
zzz:and:9

# --- KNOWN DIVERGENCE (whoosh-bug, DIVERGENCES.md entry 56, allowlist.py):
# a range value that itself begins with a to-prefixed word ("total",
# "into") is silently misparsed by real whoosh's word-boundary-free
# RangePlugin regex: it reads the word's own embedded "to" as the "TO"
# separator instead of the whole word being (part of) the bound. No date
# field involved here, so real whoosh does not crash the way the entry-55
# neighbourhood does; it just builds the wrong Range object silently.
title:[total 5]
title:[into TO 5]

# --- KNOWN DIVERGENCE (design, DIVERGENCES.md entry 24, allowlist.py): an
# unfielded all-zero-token quoted phrase, the same mechanism as the fielded
# "title:\"to\"" shape already covered by the fuzzer, just not previously
# anchored in a static corpus line. Confirmed unrelated to entry 23's
# match-all face Every/And-identity ordering bug despite the superficial
# similarity ("a zero-token thing survives in whoosh but not
# whoosh-compat"): no Every node is involved here at all.
"to"

# --- KNOWN DIVERGENCE (design, DIVERGENCES.md entry 15, allowlist.py): a
# SINGLE-QUOTED unknown-field value whose comma_values pieces contain
# characters that would be value boundaries outside the quotes (an interior
# colon, whitespace). Both sides hand the tag KEYWORD field exactly the
# same two pieces; only the combinator differs, which is entry 15's own
# Multitoken.DEFAULT question.
zzz:'a:b,c'
zzz:'a b,c'
