Commit Graph
98 Commits
Author SHA1 Message Date
Alex-GilbertandClaude Opus 4.6 921d702c07 feat: add lazy loaders for associate name lists
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 11:55:09 -06:00
Alex-GilbertandClaude Opus 4.6 291eadaba8 docs: add dictionary full-name solver implementation plan
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 11:52:39 -06:00
Alex-GilbertandClaude Opus 4.6 04aa089c7f docs: add dictionary-based full name solver design
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 11:50:50 -06:00
Alex-GilbertandClaude Opus 4.6 b50a32a038 fix(solver): add max_results cap to prevent OOM in full-name solver
The full-name solver collected all results into a Vec with no limit,
causing OOM crashes for realistic targets where millions of valid
first×last combinations exist. Thread max_results through
solve_subtree, dfs_first, and the Cartesian product loop so the
search stops early once enough results are found.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 11:20:16 -06:00
Alex-GilbertandClaude Opus 4.6 11339d0ecc test(solver): add 3-char equivalence expansion integration test
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 10:52:54 -06:00
Alex-GilbertandClaude Opus 4.6 25a8d47d53 feat(solver): wire equiv classes into DFS pipeline
Thread EquivClasses and deduped_allowed through solve_subtree, dfs,
generate_prefixes, handle_solve, and dfs_first (full_name). The DFS
hot loop now iterates deduped representatives instead of all allowed
chars, and expand_match restores full class-member variants at match
time. This reduces branching factor for charsets with metrically
identical glyphs while preserving complete result sets.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 10:50:31 -06:00
Alex-GilbertandClaude Opus 4.6 700a76eeee feat(solver): add dedup_state_allowed, build_byte_to_idx, expand_match
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 10:43:57 -06:00
Alex-GilbertandClaude Opus 4.6 be9dd07a66 feat(solver): add EquivClasses struct and compute_equiv_classes
Foundation for glyph equivalence class optimization. Groups charset
characters with identical metric signatures (width table columns/rows,
left/right edges, optional extra columns) into equivalence classes
using exact f64::to_bits() comparison. Includes 3 unit tests covering
duplicate detection, all-unique case, and extra column splitting.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 10:39:23 -06:00
Alex-Gilbert a5505c1fbb attempting to make redaction guessing better 2026-02-18 10:35:42 -06:00
Alex-GilbertandClaude Opus 4.6 cddbf74492 docs: add glyph equivalence classes implementation plan
7 bite-sized tasks with TDD steps: EquivClasses struct, dedup/expand
functions, DFS wiring, prefix generation, full_name integration, and
end-to-end testing.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 10:34:58 -06:00
Alex-GilbertandClaude Opus 4.6 23f535a614 docs: add glyph equivalence classes design
Group metrically identical characters into equivalence classes to reduce
the DFS branching factor from N to K per node, with Cartesian product
expansion on matches to recover all solutions.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-18 10:28:41 -06:00
Alex-GilbertandClaude Opus 4.6 b577f2b52e feat: update frontend to use SSE analysis and pre-computed redaction data
Replace the click-to-analyze and spot-detection flows with an automatic
SSE-driven analysis pipeline. After upload, an EventSource connects to
/api/doc/{id}/analyze and reloads page data as each page completes,
consuming pre-computed analysis from the page data endpoint.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 15:38:13 -06:00
Alex-GilbertandClaude Opus 4.6 1a65cb9a87 refactor: replace per-redaction endpoints with SSE upload analysis pipeline
Replace the old /api/redaction/analyze and /api/redaction/spot endpoints
with a new /api/doc/{id}/analyze SSE endpoint that pre-computes all
analysis during upload. The page data endpoint now returns pre-computed
analysis results instead of requiring per-redaction API calls.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 15:35:09 -06:00
Alex-GilbertandClaude Opus 4.6 0f9c7ff858 feat: add page analysis pipeline orchestrating OCR, LLM, OpenCV, and font detection
Wire together the per-page pipeline: OCR -> LLM redaction detection ->
guided OpenCV search -> font detection with masking -> pixel alignment.
Includes font caching per line and progress callbacks.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 15:31:17 -06:00
Alex-GilbertandClaude Opus 4.6 8b5511e7fd feat: add detect_font_masked for redaction-aware font detection
Adds a new detect_font_masked() function that masks redaction boxes to
white (255) before running pixel-based font detection on the full line
crop. This replaces the fragile approach of cropping just the left/right
portion of a line, which lost signal from narrow crops and coordinate
mismatches. The Dice-based scoring naturally ignores masked (white)
regions since they contain no ink pixels.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 15:26:14 -06:00
Alex-GilbertandClaude Opus 4.6 c39d74e46d feat: add guided OpenCV search for LLM-directed redaction regions
Add find_redaction_in_region() that searches for a black rectangle
within a specific page region identified by the LLM. Uses a lower
minimum area threshold (100px vs 500px) since the LLM provides
spatial guidance, preventing merged redactions and false positives.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 15:22:28 -06:00
Alex-GilbertandClaude Opus 4.6 51ef030322 feat: add LLM-based redaction detection module
Introduce llm_detect.py that sends OCR lines to Claude Haiku to identify
redaction locations via broken text patterns (garbled chars, brackets,
pipes). The LLM returns boundary words which are mapped back to pixel
positions using OCR character data. Includes comprehensive tests covering
single/multiple redactions, line start/end edge cases, and error handling.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 13:59:49 -06:00
Alex-GilbertandClaude Opus 4.6 72eae5a468 docs: add pipeline refactor implementation plan
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 13:53:10 -06:00
Alex-GilbertandClaude Opus 4.6 23376ebe00 docs: add pipeline refactor design (LLM-guided redaction detection)
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 13:48:29 -06:00
Alex-GilbertandClaude Opus 4.6 dbc12f6064 fix: use same-line non-redacted text for font detection
Instead of using a neighboring line (which may have a different font/size,
e.g. email header vs body text), crop the non-redacted left or right
portion of the actual redacted line for font detection. Falls back to
clean neighbor lines only when neither side has enough text (>=50px).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 13:16:23 -06:00
Alex-GilbertandClaude Opus 4.6 a2ef97b349 feat: pixel-aligned text positioning for redaction overlay
Replace OCR-based offset calculation with pixel alignment that slides
rendered text across the page image to find the exact position with
maximum Dice overlap. Also fix char filtering to use center-point
(c.x + c.w/2) instead of right-edge, recovering characters like "nt"
in "Sent" that partially overlap the redaction box.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 13:02:36 -06:00
Alex-GilbertandClaude Opus 4.6 d00b189684 docs: add pixel-aligned text positioning design
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 12:47:07 -06:00
Alex-GilbertandClaude Opus 4.6 230d0ed0a1 fix: use clean neighboring lines for font detection near redactions
Redaction boxes corrupt OCR text and add spurious dark pixels that
break pixel-based font scoring. Now uses wider crop padding (3x)
and prefers the nearest non-overlapping line for font detection.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 12:33:47 -06:00
Alex-GilbertandClaude Opus 4.6 1ad17a72a9 refactor: remove old word-width scoring function
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 12:17:29 -06:00
Alex-GilbertandClaude Opus 4.6 5590c3c0d3 fix: pass page image to detect_font_for_line in analysis
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 12:14:43 -06:00
Alex-GilbertandClaude Opus 4.6 c0b4cc2d61 feat: update font detection API to pass page image for pixel scoring
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 11:43:11 -06:00
Alex-GilbertandClaude Opus 4.6 93f4502bfa fix: update score docstring, remove dead SIZE_RANGE, fix unused import
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 11:39:13 -06:00
Alex-GilbertandClaude Opus 4.6 1b863fdf21 feat: wire pixel scoring into _full_search and _fine_search
Replace word-width MAE scoring with pixel-overlap Dice scoring in both
_full_search() and _fine_search(). Both functions now accept a line_crop
parameter and use _score_font_line_pixel() instead of _score_font_line().
Comparisons are flipped (higher is better). The size range is now derived
from the OCR line height instead of the fixed SIZE_RANGE constant, and
uses step=1 since pixel scoring has sharp peaks at the exact font size.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 11:33:10 -06:00
Alex-GilbertandClaude Opus 4.6 043aae5abb feat: add pixel-based font scoring function
Add _score_font_line_pixel() which renders candidate text and compares
pixels against the actual page image using Dice coefficient overlap.
This captures glyph shape differences that the old word-width MAE
approach cannot distinguish (e.g. serif vs sans-serif).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 11:16:20 -06:00
Alex-GilbertandClaude Opus 4.6 cb15bb068b docs: add pixel-based font detection implementation plan
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 11:11:53 -06:00
Alex-GilbertandClaude Opus 4.6 f4703285ed docs: add pixel-based font detection design
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 11:08:41 -06:00
Alex-GilbertandClaude Opus 4.6 8f432cc220 refactor: extract CSS custom properties for theme colors
Centralize 21 repeated color values into :root variables.
Makes theme changes trivial and improves readability.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 10:52:53 -06:00
Alex-GilbertandClaude Opus 4.6 bc65b82b26 feat: split app.js into ES modules with JSDoc types
Reorganize the monolithic 1,436-line frontend into 9 focused modules:
types, state, dom, canvas, viewport, associates, popover, solver, main.

No build step — browsers load ES modules natively. JSDoc @typedef
annotations provide type safety via @ts-check + jsconfig.json.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 10:42:11 -06:00
Alex-GilbertandClaude Opus 4.6 fd3617f98d docs: add frontend modularization implementation plan
Complete code for all 9 ES modules with JSDoc types.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 08:30:46 -06:00
Alex-GilbertandClaude Opus 4.6 7a8cda542c docs: add frontend modularization design
Split app.js into ES modules with JSDoc types, no build step.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-17 08:18:35 -06:00
Alex-GilbertandClaude Opus 4.6 6d4a91f7d0 fix: add viewer-section flex layout to fill viewport
Without flex properties, #viewer-section collapsed to content
height (just the controls bar), giving the workspace 0 height
and causing zoom to compute as 0%.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 18:17:07 -06:00
Alex-GilbertandClaude Opus 4.6 35b898af50 fix: remove unused import, add duplicate redaction detection
- Remove unused detect_redactions import from app.py
- Add de-duplication check in dblclick handler to prevent
  creating duplicate redaction entries for the same dark region

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 18:02:54 -06:00
Alex-GilbertandClaude Opus 4.6 6ca949b233 feat: remap shift+drag to gap width, remove manual marking
Shift+drag now adjusts gap width (was ctrl+shift+drag).
Manual redaction marking via shift+drag is removed;
users now double-click to spot-detect redactions.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 18:00:45 -06:00
Alex-GilbertandClaude Opus 4.6 dc40c1db00 feat: replace double-click zoom with spot redaction detection
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 18:00:08 -06:00
Alex-GilbertandClaude Opus 4.6 3d739b13f5 feat: add toast notification system
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:59:40 -06:00
Alex-GilbertandClaude Opus 4.6 fe9eb289ac feat: remove auto-detection from upload pipeline
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:59:00 -06:00
Alex-GilbertandClaude Opus 4.6 7fb5a85634 feat: extract _run_analysis helper and add /api/redaction/spot endpoint
Extract inline analysis logic from the analyze endpoint into a reusable
_run_analysis() helper function, then add a new /api/redaction/spot
endpoint that chains spot_redaction detection with analysis in one call.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:56:48 -06:00
Alex-GilbertandClaude Opus 4.6 5b395a6a8f fix: use _ for unused connectedComponents label count
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:55:18 -06:00
Alex-GilbertandClaude Opus 4.6 c35821dab2 feat: add spot_redaction() for click-targeted redaction detection
Uses OpenCV connected components to find a dark region at a specific
click point, complementing the existing detect_redactions() which
auto-detects all redaction bars via morphological operations.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:53:15 -06:00
Alex-GilbertandClaude Opus 4.6 6e8933f0f4 docs: add spot redaction implementation plan
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:51:12 -06:00
Alex-GilbertandClaude Opus 4.6 25f3705820 docs: add spot redaction detection design
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:49:01 -06:00
Alex-GilbertandClaude Opus 4.6 bd42f32cb9 feat: add green overlay, font toolbar, and text edit bar for active redactions
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 15:30:37 -06:00
Alex-GilbertandClaude Opus 4.6 3c867de6aa feat: add offset_x/offset_y to analyze response for alignment guess
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 15:20:11 -06:00
Alex-GilbertandClaude Opus 4.6 23cbfcc862 docs: add text editing & green overlay implementation plan
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 15:18:00 -06:00
Alex-GilbertandClaude Opus 4.6 5606157e37 docs: add text editing & green overlay design
Adds green segment overlay, floating font toolbar, bottom text edit
bar, and backend offset guess to the redaction-centric UI.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 15:13:50 -06:00
Alex-GilbertandClaude Opus 4.6 a481608d41 feat: add shift+drag to manually mark redaction boxes
Hold Shift and drag on the canvas to draw a custom redaction
rectangle. Creates an unanalyzed redaction entry that triggers
on-demand OCR when clicked.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 14:47:36 -06:00
Alex-GilbertandClaude Opus 4.6 5f2e1c5ec9 feat: rewrite frontend from line-based to redaction-centric UI
Replace line list with redaction list, add canvas-native redaction
overlays with hit-testing, popover with on-demand analysis and
solver integration. Remove old font/segment/overlay controls.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 14:46:11 -06:00
Alex-GilbertandClaude Opus 4.6 4a8716539d feat: add /api/redaction/analyze endpoint for on-demand OCR + font detection
When a user clicks a redaction, this endpoint crops the surrounding line,
runs Tesseract OCR, detects the font, and returns text segments (before/after
the redaction), gap width, font info, and character-level bounding boxes.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 14:40:17 -06:00
Alex-GilbertandClaude Opus 4.6 c0f52772ee refactor: simplify upload endpoint to use redaction detection instead of OCR
Replace upfront OCR + font detection + overlay rendering with lightweight
OpenCV-based redaction detection. Upload now just rasterizes and detects
black rectangles, making it significantly faster. Remove the overlay
endpoint and update the data endpoint to return redaction bboxes.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 14:37:54 -06:00
Alex-GilbertandClaude Opus 4.6 793ab1c970 feat: add OpenCV redaction detection module
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 14:34:22 -06:00
Alex-GilbertandClaude Opus 4.6 b0e7a3ea9c docs: add interactive redaction UI implementation plan
11 bite-sized tasks covering: OpenCV detection module, simplified
upload endpoint, on-demand analyze endpoint, frontend state rewrite,
redaction list, canvas overlays, popover, manual marking, test cleanup.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 14:31:51 -06:00
Alex-GilbertandClaude Opus 4.6 48de3857b4 docs: add interactive redaction UI design
Shift from upfront OCR to redaction-centric workflow with OpenCV
detection, canvas-native clickable overlays, on-demand analysis,
and per-redaction popover solver UI.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 14:28:09 -06:00
Alex-Gilbert caf6ec3576 emails in 2026-02-16 14:05:15 -06:00
Alex-GilbertandClaude Opus 4.6 62f25a267c feat: add Emails option to solve mode dropdown
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 13:43:09 -06:00
Alex-GilbertandClaude Opus 4.6 0f4ef6b816 feat: add emails solve mode with kerning-aware width matching
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 13:39:19 -06:00
Alex-GilbertandClaude Opus 4.6 cb53f2b8fc fix: add pandas/pyarrow as optional build dependencies for build_emails.py
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 13:36:55 -06:00
Alex-GilbertandClaude Opus 4.6 0d88d6c0e7 feat: add build script to fetch and merge Epstein-related email addresses
Fetches from 3 data sources (HuggingFace parquet, rhowardstone entities,
Epstein Exposed API) plus 8 court-verified addresses. Merges, deduplicates,
validates, and writes 644 unique emails to unredact/data/emails.txt.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 13:29:18 -06:00
Alex-GilbertandClaude Opus 4.6 efda2a06fc docs: add implementation plan for email unredaction
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 13:18:54 -06:00
Alex-GilbertandClaude Opus 4.6 d0a39c6dce docs: add design for email unredaction via known email dictionary
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 13:16:37 -06:00
Alex-GilbertandClaude Opus 4.6 2268e8549e feat: add separate V (victim) badge independent of associate tiers
Victim names are stored as a flat set of lowercased name variants
with no person details — the V badge appears but is not clickable,
protecting victim identities. A result can show both T1/T2/T3 and V
badges simultaneously.

- 15 known victims from public court records → 43 name variants
- Enabler/perpetrator categories promoted to T2
- Purple V badge with pointer-events disabled
- Victim matching uses prefix/suffix combination like associate matching

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 10:31:38 -06:00
Alex-GilbertandClaude Opus 4.6 d0e6a7c47a fix: combine filter prefix/suffix with gap text for associate lookup
When matching solver results against associates, now tries:
- gap text alone ("oe")
- prefix + gap ("joe" if prefix="j")
- gap + suffix
- prefix + gap + suffix

Composite matches (prefix+gap) get a +3 score boost since the
surrounding context confirms the match. Deduplicates by person_id,
keeping the highest-scoring match.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 09:42:35 -06:00
Alex-GilbertandClaude Opus 4.6 368df1a35b feat: clickable tier badges with associate detail popup
Badge is now a button — clicking it opens a popup listing all
matching associates with their tier description (flight logs /
inner circle / named in files), category, and match type.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 09:33:27 -06:00
Alex-GilbertandClaude Opus 4.6 921fafc828 fix: sort associates by tier first, boost with prefix/suffix hints
- Sort results strictly by tier (T1 > T2 > T3 > none), then by score
  within the same tier. Previously a T3 full-name match could outrank
  a T1 first-name match.
- Boost associate score by +2 when the person's name matches the
  user's filter prefix/suffix, surfacing likely candidates higher.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 09:30:15 -06:00
Alex-GilbertandClaude Opus 4.6 eb42b0e179 fix: correct scoring inversion, filter garbage names, add Makefile target
- Fix priority scoring: (4 - tier) * weight so T1 ranks above T3
- Filter upstream redaction placeholders like "(b) (6)" from data
- Add build-associates Makefile target
- Rebuild associates.json (1586 persons, 28 garbage entries removed)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 09:17:48 -06:00
Alex-GilbertandClaude Opus 4.6 dfe78a58f2 feat: frontend associate matching, badges, and priority sorting
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 07:55:47 -06:00
Alex-GilbertandClaude Opus 4.6 4bfe7c85a7 feat: add GET /api/associates endpoint
Lazy-loads associates.json from data dir and serves it at /api/associates,
with fallback to empty dicts if file is missing.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 07:51:07 -06:00
Alex-GilbertandClaude Opus 4.6 b5d2670fa3 feat: generate associates.json with tiered Epstein network data
Fix source_name/target_name field mapping in tier computation, use
compact JSON output (696KB). Stats: 7147 lookups, 1614 persons
(204 tier-1, 38 tier-2, 1372 tier-3).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 07:49:17 -06:00
Alex-GilbertandClaude Opus 4.6 8011cf4da2 feat: add associates data processor with nickname generation and tiering
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 07:46:56 -06:00
Alex-GilbertandClaude Opus 4.6 a0173a2f40 docs: add implementation plan for associates priority dictionary
7 tasks covering build script, API endpoint, frontend matching/sorting/badges,
and end-to-end testing. TDD approach with exact file paths and code.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 07:26:57 -06:00
Alex-GilbertandClaude Opus 4.6 c914028a0a docs: add design for Epstein associates priority dictionary
Defines tiered prioritization of known Epstein associates in solver
results using rhowardstone/Epstein-research-data as the data source.
Associates are matched by full name, first/last, nicknames, and aliases
with frontend-side sorting and badge display.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 07:24:06 -06:00
Alex-GilbertandClaude Opus 4.6 fc9eff2da5 test: add round-trip integration test for solver
Measures a known word's width in font context, then verifies the solver
recovers that word from its width. Proves the width table and solver
work correctly end-to-end.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 22:26:20 -06:00
Alex-GilbertandClaude Opus 4.6 556007f5fb feat: frontend solve panel with SSE streaming results
Add a solve panel UI that lets users attempt to recover redacted text
by finding strings whose rendered width matches the redaction gap.
Includes charset selection, length bounds, tolerance slider, and
dictionary/enumerate/both mode controls. Results stream via SSE and
can be clicked to insert into the gap.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 22:24:30 -06:00
Alex-GilbertandClaude Opus 4.6 d391bfa6d6 feat: SSE solve endpoint with dictionary and enumerate modes
Add POST /api/solve endpoint that streams results via Server-Sent Events,
supporting both enumerate (brute-force) and dictionary solve modes. Add
dictionary CRUD endpoints (POST/GET/DELETE /api/dictionary) and solve
cancellation (DELETE /api/solve/{id}). Move static files mount to end of
app.py so API routes take priority.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 22:20:20 -06:00
Alex-GilbertandClaude Opus 4.6 b357713e5e feat: dictionary solver with in-memory word list store
Add solve_dictionary() for linear-scan matching of dictionary entries
against a target pixel width, and DictionaryStore for managing named
word/name lists. Reuses SolveResult from the solver module.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 22:15:21 -06:00
Alex-GilbertandClaude Opus 4.6 11cc29d3f8 feat: parallel solver with multiprocessing via ProcessPoolExecutor
Distribute branch-and-bound search across CPU cores by generating
depth-2 prefixes and farming each subtree to a worker process.
Includes on_progress callback and automatic prefix depth selection.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 22:12:49 -06:00
Alex-GilbertandClaude Opus 4.6 9021cf8a21 feat: single-threaded branch-and-bound gap solver
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 22:07:41 -06:00
Alex-GilbertandClaude Opus 4.6 696b0165ef feat: width table module with kerning-aware font metrics
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 22:00:12 -06:00
Alex-GilbertandClaude Opus 4.6 fe70bcaa6c docs: constraint solver design for redaction gap enumeration
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 21:44:50 -06:00
Alex-GilbertandClaude Opus 4.6 b9df273521 Add interactive font tuning UI with split-panel layout
Replace static overlay with client-side canvas rendering. Left panel
shows clickable OCR lines with font controls (dropdown + size slider).
Right panel renders green text overlay on the document via canvas.
Fonts loaded from backend TTF files using the FontFace API.

New endpoints: GET /api/fonts, GET /api/font/{id}

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 20:17:57 -06:00
Alex-GilbertandClaude Opus 4.6 9b23ad827b Add .worktrees/ to .gitignore
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 19:41:08 -06:00
Alex-GilbertandClaude Opus 4.6 d2b149f1ba feat: per-line font detection with prior bias
Instead of detecting one font per page, detect the font for each line
independently. The previous line's font is used as a prior — if it
scores within 15% of the best candidate, it's kept for consistency.
This handles documents with mixed fonts (bold headers, regular body,
different sections).

Also: redirect / to the static UI, fix data endpoint to return
per-line font info.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 19:24:48 -06:00
Alex-GilbertandClaude Opus 4.6 605729209b fix: render overlay line-by-line, not word-by-word
Word-by-word rendering hides font detection errors by repositioning
each word at the OCR'd spot. Line-by-line rendering lets the font's
own character spacing determine where each character falls — any
drift reveals that the font/size is wrong. The drift IS the feedback
mechanism.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 19:15:34 -06:00
Alex-Gilbert a9c394151d test: end-to-end smoke test with visual output 2026-02-15 19:06:24 -06:00
Alex-GilbertandClaude Opus 4.6 8d82054b5d feat: overlay calibration with word-by-word rendering
- Render each word at its OCR'd position instead of whole lines,
  so word spacing matches the original document exactly
- Add y-offset correction using glyph bounding box
- Add fine-grained font size search (±3 around coarse best, step 1)
- Add alignment quality test (48.9% hit rate, >30% threshold)
- Add scipy to dev dependencies

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 19:04:40 -06:00
Alex-GilbertandClaude Opus 4.6 3da043046c feat: web UI with document viewer and overlay toggle
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:56:51 -06:00
Alex-GilbertandClaude Opus 4.6 c95b6cb9d7 feat: FastAPI backend with upload, overlay, and data endpoints
Adds POST /api/upload (runs full pipeline: rasterize, OCR, font detect,
overlay), GET endpoints for original/overlay images and OCR data JSON.
Also adds python-multipart, anyio, and pytest-anyio dependencies.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:53:48 -06:00
Alex-GilbertandClaude Opus 4.6 73320365a3 feat: green text overlay renderer
Add render_overlay() that composites semi-transparent green text on
the original document image using the detected font. This is the
visual proof mechanism for font detection accuracy. Also adds numpy
to project dependencies for test pixel analysis.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:49:39 -06:00
Alex-GilbertandClaude Opus 4.6 2a3a0f2076 feat: font detection by comparing rendered vs OCR'd word widths
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:46:07 -06:00
Alex-GilbertandClaude Opus 4.6 b79ca81965 feat: OCR module with character-level bounding boxes
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:41:05 -06:00
Alex-GilbertandClaude Opus 4.6 420e20a8cf feat: PDF rasterization module
Add rasterize_pdf() that converts PDF pages to PIL images using
pdf2image. Supports configurable DPI and page range selection.
Includes tests verifying multi-page output, high-DPI dimensions,
and single-page extraction.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:38:50 -06:00
Alex-GilbertandClaude Opus 4.6 94877952db feat: project scaffolding with dependencies
Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:36:10 -06:00
Alex-GilbertandClaude Opus 4.6 75834d4a85 Add Stage 1 implementation plan: font matching overlay
9 tasks covering: project scaffolding, PDF rasterization, OCR with
character bounding boxes, font detection, green overlay renderer,
FastAPI backend, web UI, alignment calibration, and E2E smoke test.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:31:26 -06:00
Alex-GilbertandClaude Opus 4.6 3431ea1d30 Add initial design doc for unredact tool
AI-powered redaction analysis tool for Epstein case files.
Image-first pipeline: OCR, font detection, redaction detection,
constraint solving, and Claude API guessing with visual overlay
verification.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-15 18:27:29 -06:00