Commit Graph
140 Commits
Author SHA1 Message Date
stumpylogandClaude Opus 5 c56f910cc9 docs(search): scope the relative-offset warning to a value standing alone
The warning said relative offsets such as "-1 week" "in practice mean no
documents at all", unqualified, one bullet after the range-bound rule
offered added:['-1 week' to now] as the example of quoting a bound. Both
sentences were true in their own scope, but read together they talk a
user out of a query that works: the bare value is a zero-width instant,
the same offset as a bound is a real seven-day window (verified:
lo=2026-06-08T12:00, hi=2026-06-15T12:00 from a frozen 2026-06-15T12:00).

Also widens the last sentence to say now-3days and "3 days ago" are
rejected wherever they appear, having checked they are rejected as range
bounds too, single- or double-quoted, not only as bare values.

Restores the 'added:"-1 week"' case to the standalone-forms list, which
the docs name by that exact spelling, and pins the bound reading beside
it so neither half of the warning is an unpinned claim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 15:19:26 -07:00
stumpylogandClaude Opus 5 5ecd237a3d feat(search)!: let a wildcard match the typed run or its stem
whoosh-compat's pattern_normalizer now accepts several alternative forms
per literal run, ORed and deduplicated by the emitter, so the
shorter-of-the-two heuristic that had to pick one form is gone. The typed
run and its stem are both offered: neither is a prefix of the other once
the stemmer substitutes rather than truncates ("copy" -> "copi"), so
"copy*" now reaches "copies" and "copyright" alike instead of trading one
for the other.

checksum keeps _fold_normalizer. It is the only KEYWORD field, indexed
with the raw tokenizer, and a stemmed prefix there ("ceded" -> "cede")
returns documents whose checksum does not start with what was typed.

Also picks up two date-grammar fixes from the same library release: a
reversed relative range now swaps its bounds like the absolute case
instead of day-bumping the upper one, and a date value the grammar can
only half-consume (a bare, unquoted "added:2005-03-04T15:30:00Z") is
rejected as an InvalidDateQuery rather than silently matching nothing.

docs/usage.md: the "copy* does not find copyright" caveat is no longer
true; the bare timestamp is now an error rather than a silent non-match;
and the range-bracket quoting rule was wrong in a user-visible way. Only
double-quoted bounds are rejected, single-quoted ones parse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 15:02:33 -07:00
stumpylogandClaude Opus 5 82546f13b3 fix(search): keep wildcard patterns literal on unstemmed KEYWORD fields
get_field_registry() branched the analyzer by field kind but gave every field
the same stemming pattern normalizer. checksum is indexed with the raw
tokenizer, so its terms are neither folded nor stemmed, yet its wildcard
patterns were: "checksum:ceded*" normalized to "cede*" and matched a document
whose checksum starts with "cedef00d". About 2.8% of random hex prefixes were
rewritten this way. Always over-matching rather than missing, but for a field
whose whole purpose is exact identification, returning a different checksum is
a wrong answer.

KEYWORD fields now get a fold-and-lower normalizer, which is what every field
used before pattern stemming was added; TEXT fields keep the stemming one so
"invoice*" still reaches the indexed "invoic".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 12:08:47 -07:00
stumpylogandClaude Opus 5 b3e3d8b23e docs(search): correct the RFC3339 timestamp claim, it works when quoted
The previous commit's warning said a timestamp carrying a time of day was
not understood at all, and told users to fall back to whole-day range
bounds. Both halves were wrong. Only the bare unquoted spelling fails:

    added:2005-01-01T00:00:00Z                            -> no match
    added:"2005-01-01T00:00:00Z"                          -> matches
    added:[2005-01-01T00:00:00Z to 2006-01-01T00:00:00Z]  -> matches

That is the ordinary quoting rule the surrounding docs already state, the
same one "-1 week" and "next monday" obey, so present the timestamp as a
working form rather than as a limitation and drop the false workaround:
range bounds carrying a time of day work fine.

A bound must be bare inside range brackets, where quoting it is rejected
outright, so document both halves of the rule rather than just "quote it".

Keep the zero-width warning distinct from the quoting rule now sitting above
it, since a reader who just learned quoting rescues "next monday" would
otherwise assume it rescues "-3 days". It does not: re-verified against
documents added at exactly those instants, the quoted offsets still match
only that one instant.

Pin the working spellings, which is the assertion that was missing: nothing
covered the quoted or range-bound forms, so a regression of a working
feature went undetected. Also pin that quoting does not rescue the
zero-width group.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 10:06:12 -07:00
stumpylogandClaude Opus 5 059759b83f docs(search): describe the query grammar paperless actually supports
usage.md linked to tantivy's QueryParser documentation, promising a grammar
paperless neither implements nor intends to. Replace the link with a
description of the surface that was verified end-to-end against a real index,
and correct the claims that did not survive that verification.

- checksum: the field is stored verbatim, so only a complete lowercase
  checksum matches. The old a1b2c3d4 example matched nothing.
- A leading - is not negation. Separators are stripped at index time, so
  "invoice -secret" requires "secret", the opposite of the intent. Document
  NOT as the way to exclude a term.
- Document the aliases type: and path:, num_notes:, numeric ranges, quoted
  phrases, tag:'s comma list (which requires all listed tags, not any), and
  the date forms that resolve to a real span: tomorrow, ISO dates, month
  names, "next monday"/"last monday".
- Warn about now/noon/midnight and offsets like "-3 days": they parse, but
  resolve to a single instant rather than a span, so they match nothing.
  Likewise a T/Z timestamp, whose time portion is split off as loose text.

Add test_documented_syntax.py, which asserts on matched document IDs rather
than on parsed queries, so the docs cannot drift from the code again. Its
negative cases pin the behaviours the warnings describe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:53:19 -07:00
stumpylogandClaude Opus 5 7fddad849a refactor(search): delete the date-keyword-phrase pre-parse rewrite
whoosh-compat's grammar already accepts the closed multi-word date
keyword vocabulary (previous month, this year, etc.) unquoted after a
date field, making _quote_date_keyword_phrases redundant. Like its
sibling rewrite removed in an earlier commit, it was not quote-aware
and could insert quotes mid-phrase inside an unrelated quoted string
(e.g. title:"see added:previous month notes"), corrupting the parse.
Deleting it removes that hazard entirely.

Docs are adjusted to scope the quoted-or-unquoted equivalence to the
documented keyword list; other date expressions the grammar accepts
(relative offsets, absolute dates) still require quoting.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:27:07 -07:00
stumpylogandClaude Opus 5 e48182c358 docs(search): pin the stem-substitution limit wildcards inherit
Stemming substitutes as well as truncates ("copy" and "copies" both index as
"copi" while "copyright" keeps its literal y), so a stemmed pattern reaches a
word's inflections but no longer reaches compounds that keep the surface
spelling. That trade is accepted: the same substitution is what makes company*
and library* work, and no rule over one normalized string separates them. So
usage.md stops claiming a trailing star just works, and a test pins copy* to the
base word rather than the compound. Also adds a parity test tying
stem_pattern_text to paperless_text_analyzer's own output, so a filter added to
the index analyzer alone cannot silently diverge, and corrects the docstring
claim that a run can analyze to several tokens - the raw tokenizer emits one
token whatever the input, so only the remove_long zero-token case can fire.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:01:02 -07:00
stumpylogandClaude Opus 5 e311c84139 fix(search): stem wildcard patterns so prefix searches match again
Index terms are stemmed but query patterns were not, so invoice* matched nothing
while invoic* worked. v2's index was unstemmed (whoosh TEXT() defaults to
StandardAnalyzer), so this regressed against both baselines, not just dev. Uses
the typed run's stem unless the stem is longer than the run, since a stem can be
longer than a partial prefix and a shorter prefix only widens recall. Patterns
spanning the stem boundary (produ*name) still cannot match a stemmed index, so
usage.md loses that example rather than advertising a broken one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 07:37:26 -07:00
Trenton HolmesandClaude Fable 5 bd87624b29 fix(search): rewrite bare notes:/custom_fields: prefixes to their subpaths
The v2 whoosh schema had plural notes/custom_fields TEXT fields (notes
indexed the joined note texts, custom_fields indexed joined
"name : value" strings), so "notes:foo" and "custom_fields:foo" were
valid fielded searches in released paperless and through the deleted
translation layer. On the whoosh-compat registry those names are JSON
fields addressable only via subpaths, and the bare spelling silently
demoted to an unfielded text search of the words themselves, matching
unrelated documents that merely contain "notes" or "custom".

parse_user_query now rewrites the bare prefixes live to the same
targets migration 0017 chose for the singular whoosh-era spellings:
notes: becomes notes.note: and custom_fields: becomes
custom_fields.value:, with 0017's lookbehind guard so subpath spellings
and words merely ending in the prefix are untouched. Prefix
substitution only; values ride through unchanged, and every value shape
lands in a documented outcome downstream (ranges, wildcards and exists
on JSON subpaths are typed errors, not crashes). The inherited
trade-off stands: custom_fields.value: drops the name-matching half of
v2's combined indexing, with custom_fields.name: available for it.

Acceptance tests pin the rewrite with decoy documents whose content
contains the literal prefix words, which the old demotion matched and
the fielded search must not, plus untouched-subpath controls.
docs/usage.md documents the bare prefixes as subpath shorthand.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WMsn6DgzbvSqh1pwy66VVF
2026-08-19 13:36:53 -07:00
Trenton HolmesandClaude Fable 5 ff540041b5 fix(search): restore unquoted multi-word date keywords via pre-parse quoting
"added:previous month" returned HTTP 400 after the whoosh-compat
migration. The unquoted spelling was never parser-native anywhere: v2
rewrote it to explicit bracket ranges app-side before whoosh saw the
string, and the deleted translation layer consumed it itself, so users
and saved views have relied on it continuously while whoosh-compat
deliberately scopes it out of its parser (its DIVERGENCES.md entry 19)
and understands the phrases natively only as quoted values.

parse_user_query now quotes the closed six-phrase vocabulary (previous
week/month/quarter/year, this month/year) when it directly follows a
date field's colon, before parsing. Only quoting happens app-side; every
date computation stays in whoosh-compat's grammar, unlike v2's rewrite,
which computed the ranges itself. Date field names derive from
PUBLIC_FIELDS, the field name matches case-sensitively (the parser's own
field tagging is case-sensitive), the phrase case-insensitively (the
grammar accepts any case in the quoted form), and already-quoted
spellings, TEXT fields, unfielded words and bracketed ranges are
untouched.

The previously xfailed end-to-end regression test now passes as a plain
test, and a new acceptance class pins unquoted == quoted == mixed-case
result sets on a boundary fixture, no-error parsing for the whole
vocabulary across all three date fields, and that "title:previous month"
stays an ordinary text search. docs/usage.md now states the two
spellings are equivalent after a date field.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WMsn6DgzbvSqh1pwy66VVF
2026-08-19 13:36:53 -07:00
Trenton HolmesandClaude Sonnet 5 2b90a577c7 docs: drop *_id field-removal note from usage.md
These prefixes were never documented public API (undocumented internal
fields the old KNOWN_FIELDS happened to accept), so their removal isn't a
user-facing regression worth calling out in usage.md. The behavior is still
covered by test_acceptance.py's TestUnregisteredIdFieldFoldsToLiteralText.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RVj8NFy821G3YhNf68PF6X
2026-08-19 13:36:53 -07:00
Trenton Holmes 943e60fecc docs: clarify quoted date-keyword phrases and dropped *_id field aliases
Add a sentence to the "Supported date keywords" advanced-search section
noting that multi-word date keywords must be quoted (e.g.
added:"previous month") -- whoosh-compat requires quoting where the
unquoted form used to work. Also document that the old undocumented
*_id field aliases (tag_id, owner_id, viewer_id, correspondent_id,
document_type_id, storage_path_id, type_id, path_id) are no longer
recognized: a query using one now silently folds to a literal-text
search instead of matching the intended structured field.
2026-08-19 13:36:53 -07:00
Trenton Holmes 5941c19fb4 docs: document asn/page_count/checksum/original_filename advanced search fields 2026-08-19 13:36:53 -07:00
shamoonandGitHub e389298aab Enhancement: merge documents as versions (#13515) 2026-08-19 07:20:14 -07:00
shamoonandGitHub 855669ddf9 Fix: fixes for workflow assign custom field values (#13630) 2026-08-10 07:38:07 -07:00
Trenton HandGitHub 12d318deff Documentation: Add Password Removal workflow action documentation (#13377)
Addresses discussion #13373. Documents that password removal creates a
new document version via re-consumption of the decrypted file rather
than editing in place, and explains why the Consumption Started trigger
produces an initial un-OCR'd version followed by a properly processed
one.
2026-07-28 09:21:14 -07:00
shamoon b566232542 Documentation: correct search docs for v3 2026-07-23 06:25:33 -07:00
shamoon c2d9c52cde Merge branch 'main' into beta 2026-07-22 10:30:57 -07:00
shamoon 5589a584b6 Documentation: clarify PAPERLESS_URL requirement for pw reset 2026-07-10 11:05:40 -07:00
bb5d7438b1 Documentation (beta): Updates documentation for new v3 features (#13033)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-06-18 16:20:31 -07:00
a009ea1f04 Chore(beta): Update suggested broker to Valkey + Redis agnostic documentation (#13032)
Co-authored-by: upmcplanetracker <219436948+upmcplanetracker@users.noreply.github.com>
2026-06-18 19:54:15 +00:00
shamoonandGitHub 69cb4d06c6 Enhancement (dev): Use OpenAI-like backend (#12668) 2026-04-28 10:06:59 -07:00
0c25c2dac5 Feature: Allow monitoring access to tasks summary (#12624)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-04-22 13:48:54 -07:00
shamoonandGitHub 20aa0937e8 Fix (dev): retain backwards compatibility with natural-date keywords in tantivy (#12602) 2026-04-20 08:26:33 -07:00
shamoon 8f036c9521 Merge branch 'main' into dev
# Conflicts:
#	docs/usage.md
#	src/documents/signals/handlers.py
#	src/documents/tests/test_api_documents.py
#	src/documents/views.py
2026-04-14 15:11:23 -07:00
shamoon 12c0dc635e Merge branch 'release/v2.20.x' 2026-04-14 13:10:52 -07:00
shamoon 1e01ce42c0 Update usage.md 2026-04-14 13:10:40 -07:00
shamoonandGitHub 4629bbf83e Enhancement: add view_global_statistics and view_system_status permissions (#12530) 2026-04-08 15:39:47 +00:00
shamoon 1ba6c31385 Clarify User permission scope in docs 2026-04-07 13:38:24 -07:00
c232d443fa Breaking: Decouple OCR control from archive file control (#12448)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-04-06 15:50:21 -07:00
aed9abe48c Feature: Replace Whoosh with tantivy search backend (#12471)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Antoine Mérino <3023499+Merinorus@users.noreply.github.com>
2026-04-02 12:38:22 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>shamoon
e2947ccff2 Chore(deps): Bump the pre-commit-dependencies group with 4 updates (#12323)
* Chore(deps): Bump the pre-commit-dependencies group with 4 updates

---
updated-dependencies:
- dependency-name: https://github.com/codespell-project/codespell
  dependency-version: 2.4.2
  dependency-type: direct:production
  dependency-group: pre-commit-dependencies
- dependency-name: prettier
  dependency-version: 3.8.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pre-commit-dependencies
- dependency-name: prettier-plugin-organize-imports
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pre-commit-dependencies
- dependency-name: https://github.com/lovesegfault/beautysh
  dependency-version: 6.4.3
  dependency-type: direct:production
  dependency-group: pre-commit-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* Drop this, it seems more trouble than its worth

* Re-run prek with new prettier

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-03-12 16:29:57 +00:00
shamoonandGitHub df03207eef Fix: correct doc version filename handling (#12223) 2026-03-04 23:28:07 +00:00
shamoon b7ca3550b1 Merge branch 'main' into dev 2026-03-02 13:45:10 -08:00
Jan Kleineandshamoon cd2b5127db Documentation: fix version label filename placeholder
Co-Authored-By: shamoon <4887959+shamoon@users.noreply.github.com>
2026-03-02 00:12:52 -08:00
shamoon 7ff51452f0 Documentation: small note re filename vs original_filename 2026-03-01 11:45:06 -08:00
shamoonandGitHub ceee769e26 Feature: document file versions (#12061) 2026-02-26 16:46:54 +00:00
shamoon be82fcb70a Documentation: docs cleanup (#12158) 2026-02-24 15:10:38 -08:00
shamoon ffbbe7986f Merge branch 'main' into dev
# Conflicts:
#	docs/setup.md
2026-02-24 15:05:49 -08:00
shamoon 6de7283cbf Documentation: docs cleanup (#12158) 2026-02-24 14:59:40 -08:00
c4ea332c61 Feature: move to trash action for workflows (#11176)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-02-23 16:42:50 -08:00
shamoon ab328e0212 Chore: move to Zensical for docs (#12011)
(cherry picked from commit 3c51b3f9cd)
2026-02-07 10:58:55 -08:00
shamoonandGitHub 3c51b3f9cd Chore: move to Zensical for docs (#12011) 2026-02-06 08:34:15 -08:00
shamoon 63c0e2f72b Documentation: clarify workflow placeholders docs 2026-02-03 08:13:10 -08:00
shamoonandGitHub 1f074390e4 Feature: sharelink bundles (#11682) 2026-01-27 18:54:51 +00:00
shamoonandGitHub 32b236cfa2 Enhancement: support doc_id placeholder in workflow templates (#11847) 2026-01-22 00:05:19 +00:00
Trenton HandGitHub 51b466a86b Feature: Simplify and improve the consumer (#11753) 2026-01-21 14:37:48 -08:00
shamoonandGitHub e940764fe0 Feature: Paperless AI (#10319) 2026-01-13 16:24:42 +00:00
shamoonandGitHub 58d88440f1 Feature: Remote OCR (Azure AI) (#10320) 2026-01-08 21:49:17 +00:00
Jan KleineandGitHub e770ff572e Documentation: Document missing workflows env variable and complete diagram (#11554) 2025-12-12 16:12:23 +00:00