feat(search): NL search — resolve tag names in query parsing (#743) #765

Merged
marcel merged 15 commits from feat/issue-743-nl-search-tag-resolution into main 2026-06-07 09:33:26 +02:00

15 Commits

Author SHA1 Message Date
Marcel
6878419156 merge: resolve conflicts with origin/main (#763 person name-match integration)
All checks were successful
CI / Unit & Component Tests (pull_request) Successful in 3m31s
CI / OCR Service Tests (pull_request) Successful in 25s
CI / Backend Unit Tests (pull_request) Successful in 3m48s
CI / fail2ban Regex (pull_request) Successful in 45s
CI / Semgrep Security Scan (pull_request) Successful in 22s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m6s
CI / Unit & Component Tests (push) Successful in 3m20s
CI / OCR Service Tests (push) Successful in 23s
CI / Backend Unit Tests (push) Successful in 3m48s
CI / fail2ban Regex (push) Successful in 46s
CI / Semgrep Security Scan (push) Successful in 23s
CI / Compose Bucket Idempotency (push) Successful in 1m8s
- Drop unused MAX_CANDIDATES constant (not referenced in service)
- Keep detached-entity safety comment in resolveTags()
- Add 3 new partial-name match tests (23a/b/c) from #763
- Use resolveByName() API in test 28 (replaces findByDisplayNameContaining)
- Add NameMatches glossary entry from #763

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 08:50:48 +02:00
Marcel
fb41affd4c docs(search): note vitest-browser workaround for + in path
All checks were successful
CI / Unit & Component Tests (pull_request) Successful in 3m22s
CI / OCR Service Tests (pull_request) Successful in 24s
CI / Backend Unit Tests (pull_request) Successful in 3m47s
CI / fail2ban Regex (pull_request) Successful in 46s
CI / Semgrep Security Scan (pull_request) Successful in 24s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m6s
Addresses @Sara review: browser tests in this spec fail silently when
the project path contains '+' (common in git worktrees). The comment
tells developers to copy the frontend directory to a clean path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:58:36 +02:00
Marcel
dc366ed403 docs(search): add detached-entity safety comment in resolveTags
Addresses @Markus review: tags fetched by findByNameContaining live outside
any transaction; Hibernate's dirty-check never fires on them. The comment
removes the ambiguity for cold readers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 00:58:03 +02:00
Marcel
64b7b2315d docs(search): ADR-028 fix + glossary + C4 diagram for tag resolution (#743)
All checks were successful
CI / Unit & Component Tests (pull_request) Successful in 3m25s
CI / OCR Service Tests (pull_request) Successful in 23s
CI / Backend Unit Tests (pull_request) Successful in 4m1s
CI / fail2ban Regex (pull_request) Successful in 45s
CI / Semgrep Security Scan (pull_request) Successful in 23s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m7s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:42:23 +02:00
Marcel
2a7e133717 feat(search): wire theme chip removal to URL navigation in +page.svelte
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:40:33 +02:00
Marcel
5387bc9247 feat(search): render removable theme chips in InterpretationChipRow
When tagsApplied is true, each resolvedTag renders as a 'Thema: Name'
chip with optional inline color style from the tag's resolved color.
Clicking × calls onRemoveChip('theme', tag.name).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:33:53 +02:00
Marcel
847874abb3 feat(api): add TagHint schema and extend NlQueryInterpretation with resolvedTags/tagsApplied
Manual update since Docker compose backend runs old build; regenerate with
npm run generate:api once new backend is deployed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 23:01:11 +02:00
Marcel
573bca4986 feat(i18n): add search_chip_theme_prefix to de/en/es message bundles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:59:58 +02:00
Marcel
86690fdbb6 test(search): DataJpaTest for descendant-expansion via TagRepository
Verifies the recursive CTE in findDescendantIdsByName expands a parent tag
to include all child IDs, and that findByNameContainingIgnoreCase matches
both parent and child names when the fragment appears in both.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:59:07 +02:00
Marcel
6cb1025881 test(search): add 11 tag-resolution test cases to NlQueryParserServiceTest
Covers multi-tag match, no-match FTS fallback, mixed resolution, personRole
bypass, cap at 10, short-keyword skip, dedup, rawQuery suppression when all
keywords resolve, flag independence, colour propagation via resolveEffectiveColors,
and colour=null when depth constraint prevents resolution.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:57:17 +02:00
Marcel
fc557bd9ae feat(search): implement keyword→tag resolution in NlQueryParserService
Keywords that substring-match the tag taxonomy become OR-union tag filters;
non-matching keywords stay as FTS text. Resolved tags surface in the
NlQueryInterpretation as TagHint objects with effective colours. The
rawQuery fallback is now guarded by hadStructuredMatch to prevent
double-apply when all keywords resolve.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:54:33 +02:00
Marcel
e94414b81a refactor(search): extract ChipType to chip-types.ts; audit NL fixtures
Pre-implementation step for #743: ChipType union extracted from
InterpretationChipRow and +page.svelte into shared chip-types.ts;
resolvedTags/tagsApplied neutral defaults added to test fixtures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:49:54 +02:00
Marcel
7eee688ce9 feat(search): extend NlQueryInterpretation with resolvedTags + tagsApplied
Positional record fields added; all 3 construction sites updated with neutral
defaults; NlQueryParserService wired for TagService (4th constructor arg);
NlQueryParserServiceTest and NlSearchControllerTest synced.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:37:45 +02:00
Marcel
8905135006 feat(search): add TagHint record for NL tag resolution API surface
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:35:24 +02:00
Marcel
8bd8390891 feat(search): add TagService.findByNameContaining for NL tag resolution
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:34:34 +02:00