From b93f1e984811944fd5ccfd1d9aa37bba5fc10000 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 2 Oct 2026 07:43:35 -0400 Subject: [PATCH] ROADMAP: parity estimate by feature count and by effort; xtask parity prints weighted completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `cargo xtask parity` adds a weighted-completion line (โœ… 1, ๐ŸŸก ยฝ, out of scope left out) per tier to the generated summary: 65.7% of 500 in-scope rows (P0 98.5%, P1 79.9%, P2 11.7%). - ROADMAP: remaining work by package in agent-hours (โ‰ˆ 295โ€“540; โ‰ˆ 75โ€“130 h wall clock with 4โ€“6 agents), effort-weighted completion โ‰ˆ 20โ€“30% for full parity, milestone statuses refreshed, Totals replaced. Co-Authored-By: Claude Opus 5.5 --- ROADMAP.md | 81 +++++++++++++++++++++++++++++++++++---------- docs/parity.md | 2 ++ xtask/src/parity.rs | 30 +++++++++++++++++ 3 files changed, 95 insertions(+), 18 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 91d7f54df..ef6b0e2c1 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -8,30 +8,74 @@ projects (DrawCraft reached its first four milestones in โ‰ˆ 4ยฝ h) and are revi | # | Milestone | Scope (summary) | Estimate (h) | Status | |---|---|---|---|---| -| M0 | Skeleton + visual shell | workspace, xtask CI + layering, geom/color/raster, develop model, pipeline v0, catalog v0, engine commands, Lightroom-look UI (grid, loupe, filmstrip, Edit panel), control channel, MCP, web build | 3โ€“5 | ๐Ÿšง (UI, pipeline, engine, control channel โœ…; MCP/CLI, web ๐Ÿšง) | -| M1 | Library core | import (JPEG/PNG/TIFF/WebP), EXIF/XMP, persistent catalog (op log + snapshots), albums, ratings/flags/labels, filter/search/sort, thumbnail cache, 100k-photo grid | 6โ€“10 | ๐Ÿšง (import, codecs, EXIF/XMP, albums, search โœ…; persistence ๐Ÿšง) | -| M2 | Pipeline v1 (quality) | WB temp/tint, profiles, local tone mapping (highlights/shadows), curves, HSL, point colour, colour grading, texture/clarity/dehaze, vignette, grain, B&W, auto tone/WB, histogram, before/after | 10โ€“15 | โฌœ | +| M0 | Skeleton + visual shell | workspace, xtask CI + layering, geom/color/raster, develop model, pipeline v0, catalog v0, engine commands, Lightroom-look UI (grid, loupe, filmstrip, Edit panel), control channel, MCP, web build | 3โ€“5 | โœ… | +| M1 | Library core | import (JPEG/PNG/TIFF/WebP), EXIF/XMP, persistent catalog (op log + snapshots), albums, ratings/flags/labels, filter/search/sort, thumbnail cache, 100k-photo grid | 6โ€“10 | โœ… (100k-photo grid scale test pending) | +| M2 | Pipeline v1 (quality) | WB temp/tint, profiles, local tone mapping (highlights/shadows), curves, HSL, point colour, colour grading, texture/clarity/dehaze, vignette, grain, B&W, auto tone/WB, histogram, before/after | 10โ€“15 | โœ… (look tuning vs our references ongoing) | | M3 | RAW I | TIFF/DNG (LJ92, deflate, tiles, opcodes), demosaic (AHD/PPG/bilinear), highlight recovery, DNG colour model, CR2, NEF, ARW, embedded previews | 10โ€“15 | ๐Ÿšง (DNG, CR2, ARW, NEF uncompressed, embedded previews โœ…; NEF Huffman โฌœ) | -| M4 | Crop, geometry, optics | crop tool + overlays, straighten, Upright (auto/level/vertical/full/guided), manual transforms, CA, defringe, manual lens corrections | 6โ€“10 | โฌœ | -| M5 | Performance | source pyramids, wgpu compute pipeline (CPU oracle), draft/full renders, prefetch, budgets (16 ms slider updates on 24 MP) | 10โ€“15 | โฌœ | -| M6 | Masking | brush, linear/radial gradients, colour/luminance/depth range, add/subtract/intersect/invert, all local adjustments, masks panel | 8โ€“12 | โฌœ | -| M7 | Detail | sharpening + masking preview, luminance/colour NR, Denoise, Raw Details, Super Resolution | 6โ€“10 | โฌœ | -| M8 | Heal / Remove | content-aware remove (PatchMatch), heal, clone, brush spots, visualize spots, red/pet eye | 6โ€“10 | โฌœ | -| M9 | Presets, profiles, versions, sync | preset browser + amount, create/import presets, profile browser, versions, history, copy/paste/sync settings | 5โ€“8 | โฌœ | -| M10 | Export & share | export dialog (JPEG/PNG/TIFF/DNG/AVIF/JXL/original), sizing, sharpening, metadata, watermark, naming, batch jobs, XMP sidecars, HDR export | 6โ€“10 | โฌœ | -| M11 | RAW II | CR3, RAF (X-Trans), ORF, RW2, PEF, SRW, 3FR, IIQ + long tail; camera calibration DB; HEIC/AVIF/JXL import | 20โ€“35 | ๐Ÿšง (RAF uncompressed, RW2 packed, PEF, ORF uncompressed โœ…) | +| M4 | Crop, geometry, optics | crop tool + overlays, straighten, Upright (auto/level/vertical/full/guided), manual transforms, CA, defringe, manual lens corrections | 6โ€“10 | โœ… | +| M5 | Performance | source pyramids, wgpu compute pipeline (CPU oracle), draft/full renders, prefetch, budgets (16 ms slider updates on 24 MP) | 10โ€“15 | ๐Ÿšง (stage cache, source pyramid, wgpu pipeline, prefetch, memory budget โœ…; colour NR at half resolution, GPU histogram โฌœ) | +| M6 | Masking | brush, linear/radial gradients, colour/luminance/depth range, add/subtract/intersect/invert, all local adjustments, masks panel | 8โ€“12 | ๐Ÿšง (brush/linear/radial/colour/luminance range, add/subtract/intersect, masks panel โœ…; depth range, AI masks โฌœ) | +| M7 | Detail | sharpening + masking preview, luminance/colour NR, Denoise, Raw Details, Super Resolution | 6โ€“10 | ๐Ÿšง (sharpening, luminance/colour NR โœ…; AI Denoise, Raw Details, Super Resolution โฌœ) | +| M8 | Heal / Remove | content-aware remove (PatchMatch), heal, clone, brush spots, visualize spots, red/pet eye | 6โ€“10 | ๐Ÿšง (heal, clone, auto source, visualize spots, red/pet eye โœ…; PatchMatch remove โฌœ) | +| M9 | Presets, profiles, versions, sync | preset browser + amount, create/import presets, profile browser, versions, history, copy/paste/sync settings | 5โ€“8 | โœ… | +| M10 | Export & share | export dialog (JPEG/PNG/TIFF/DNG/AVIF/JXL/original), sizing, sharpening, metadata, watermark, naming, batch jobs, XMP sidecars, HDR export | 6โ€“10 | ๐Ÿšง (all formats incl. DNG/original, sizing, presets, background jobs โœ…; JXL encode, HDR export โฌœ) | +| M11 | RAW II | CR3, RAF (X-Trans), ORF, RW2, PEF, SRW, 3FR, IIQ + long tail; camera calibration DB; HEIC/AVIF/JXL import | 20โ€“35 | ๐Ÿšง (RAF uncompressed, RW2 packed, PEF, ORF uncompressed โœ…; CR3, compressed NEF/ORF/RAF โฌœ) | | M12 | AI & smart features | subject/sky/background/people/object masks, semantic search, faces/People (permissively licensed models, pure-Rust inference) | 20โ€“40 | โฌœ | -| M13 | Merge | HDR merge (deghost), panorama (projections, boundary warp, fill edges), HDR panorama | 10โ€“15 | โฌœ | +| M13 | Merge | HDR merge (deghost), panorama (projections, boundary warp, fill edges), HDR panorama | 10โ€“15 | โœ… | | M14 | Video | import/playback/trim via FilmCraft crates, global edits + presets on video, video export | 6โ€“10 | โฌœ | -| M15 | Classic modules | Map, Book, Slideshow, Print, Web; smart collections, stacks, virtual copies, publish services, tethering | 25โ€“40 | โฌœ | -| M16 | 1.0 polish | preferences, shortcut editor, accessibility, localization, packaging (dmg/msi/AppImage/web), hardening | 10โ€“20 | โฌœ | +| M15 | Classic modules | Map, Book, Slideshow, Print, Web; smart collections, stacks, virtual copies, publish services, tethering | 25โ€“40 | ๐Ÿšง (smart albums, stacks, virtual copies, compare/survey โœ…; Map/Book/Slideshow/Print/Web โฌœ) | +| M16 | 1.0 polish | preferences, shortcut editor, accessibility, localization, packaging (dmg/msi/AppImage/web), hardening | 10โ€“20 | ๐Ÿšง (settings, keyboard shortcuts sheet, packaging basics โœ…; accessibility, localisation โฌœ) | + +## Parity estimate (2026-10-02) + +**By feature count** โ€” from `docs/parity.md` (one row per Lightroom feature, menu item and shortcut; `cargo xtask +parity` prints this line on every run, so it stays current): + +| Scope | Weighted completion | Rows | +|---|---:|---:| +| P0 (core) | **98.5%** | 198 | +| P1 (important parity) | **79.9%** | 144 | +| P2 (later / AI / niche, incl. Classic modules) | **11.7%** | 158 | +| **All in-scope rows** | **65.7%** | 500 | + +โœ… counts 1, ๐ŸŸก ยฝ, โฌœ 0; out-of-scope rows (cloud sharing, Adobe accountsโ€ฆ) are left out. + +**By remaining effort** โ€” rows are not equal: a shortcut and the whole Book module are one row each, and what is +left is the heavy part (AI, video, Classic output modules, undocumented raw codecs). Remaining work in **Opus agent-hours** +(one agent working continuously; calibrated on this project โ€” a single lead agent closed โ‰ˆ 45 tracker rows of +UI/feature work in โ‰ˆ 5 h on 2026-10-01, and four to six parallel agents built M0โ€“M13 in โ‰ˆ 25 active hours): + +| Work package | Tracker rows | Agent-hours | Risk | +|---|---|---:|---| +| Remaining P0/P1 UI and library features (version hover previews, filter presets, quick develop, missing-file relink, metadata presets, keyword setsโ€ฆ) | โ‰ˆ 30 | 20โ€“35 | low | +| Raw codecs: CR3 (CRX), compressed NEF / ORF / RAF, RW2 v4, HEIC/AVIF decode | LR-IMP-FORMATS | 40โ€“80 | **high** โ€” clean-room black-box analysis, no permissive specs | +| Lens-profile database of our own (calibration targets, fitting, data) | LR-EDIT-OPTICS-PROFILE | 15โ€“30 | data collection | +| Video: playback, trim, edits, export (pure-Rust decode, ideally shared with FilmCraft) | R. Video | 20โ€“40 | medium | +| AI: subject / sky / background / people / object masks, object-aware remove, AI denoise, super resolution, lens blur, people & faces, natural-language search, culling | โ‰ˆ 30 | 80โ€“150 | **high** โ€” permissively licensed weights, pure-Rust inference, maybe training | +| HDR editing, display, visualisation and export | Q. HDR, LR-EXP-HDR | 15โ€“25 | medium | +| Classic modules: Map, Book, Slideshow, Print, publish services, tethering, soft proofing | โ‰ˆ 50 | 60โ€“100 | medium (large, well-understood) | +| Smaller P2 items: watched folders, Enhance dialog, external-editor round trip, export to Photos, help / what's new, accessibility, localisation | โ‰ˆ 25 | 20โ€“35 | low | +| Look tuning, performance budgets (colour NR at half resolution on CPU + GPU, 100k-photo library), packaging, hardening | โ€” | 25โ€“45 | medium | +| **Total remaining** | | **โ‰ˆ 295โ€“540** | | + +Spent so far โ‰ˆ 90โ€“130 agent-hours, so **by effort the project is โ‰ˆ 20โ€“30% of the way to complete Lightroom + Classic +parity**, and โ‰ˆ 40โ€“55% of the way for cloud-Lightroom parity without AI and the Classic modules (remaining โ‰ˆ 135โ€“235 h). + +**Wall clock:** โ‰ˆ 300โ€“540 h for one agent working alone; with 4โ€“6 parallel agents (โ‰ˆ 70% parallel efficiency, merges and +CI under load cost the rest) **โ‰ˆ 75โ€“130 h of continuous work**. The AI package and the raw codecs carry most of the +uncertainty: they can finish faster if suitable permissive models / documentation turn up, or stall on licensing. ## Totals -| Target | Milestones | Wall-clock estimate | -|---|---|---| -| Cloud-Lightroom feature complete | M0โ€“M11, M13โ€“M14 | **โ‰ˆ 130โ€“180 h** (6โ€“8 days, 24/7) | -| Full parity incl. Classic modules and AI | M0โ€“M16 | **โ‰ˆ 200โ€“300 h** (9โ€“13 days, 24/7) | +Remaining from 2026-10-02 (see *Parity estimate* above for the breakdown): + +| Target | Remaining agent-hours | Wall clock, 4โ€“6 parallel agents | +|---|---:|---:| +| Cloud-Lightroom parity without AI or Classic modules | โ‰ˆ 135โ€“235 h | โ‰ˆ 35โ€“60 h | +| Full parity incl. AI, video and the Classic modules | โ‰ˆ 295โ€“540 h | โ‰ˆ 75โ€“130 h | + +The milestone estimates in the table above were made before work started and are kept for calibration (M0โ€“M13 took +โ‰ˆ 25 active hours with parallel agents against an estimate of โ‰ˆ 110โ€“170 h for those milestones). ## Risks that coding hours alone don't retire @@ -70,4 +114,5 @@ own chart-based calibration (M11.4). Adobe matrices are never used. ## Log - 2026-09-30: roadmap created; M0 in progress; research docs (Lightroom reference, Rust imaging ecosystem) complete. - 2026-09-30 (later): app running with the full Lightroom-style UI; pipeline v0; DNG/CR2/ARW; README showcase. โ‰ˆ 8 h elapsed. +- 2026-10-02: parity estimate added (xtask parity prints weighted completion); milestone statuses refreshed. - 2026-10-01: RAW II formats: RAF (uncompressed Bayer + X-Trans), RW2 (packed), PEF (incl. Huffman), ORF (uncompressed); embedded previews for every container incl. CR3; raw corpus test with 37 CC0 samples. diff --git a/docs/parity.md b/docs/parity.md index 8e0c2bfb2..a2ec77b0c 100644 --- a/docs/parity.md +++ b/docs/parity.md @@ -49,6 +49,8 @@ and prints the summary; `cargo xtask parity --write` refreshes the summary table | Z. Keyboard shortcuts (desktop) | 61 | 12 | 7 | 1 | 49/52 (94%) | 12/23 (52%) | | Lightroom Classic extras | 7 | 19 | 53 | 9 | โ€” | 6/21 (29%) | | **Total** | 297 | 63 | 140 | 37 | 192/198 (97%) | 95/144 (66%) | + +Weighted completion (โœ… = 1, ๐ŸŸก = ยฝ, ๐Ÿšซ left out): **65.7%** of 500 in-scope rows โ€” P0 98.5% of 198 ยท P1 79.9% of 144 ยท P2 11.7% of 158. ## Top gaps diff --git a/xtask/src/parity.rs b/xtask/src/parity.rs index 651f3372e..caa3932a9 100644 --- a/xtask/src/parity.rs +++ b/xtask/src/parity.rs @@ -227,9 +227,35 @@ pub fn summary_table(doc: &Doc) -> String { s += &row(name, c); } s += &row("**Total**", &total); + s += &format!("\n{}\n", weighted_line(doc)); s } +/// Weighted completion of the in-scope rows (โœ… = 1, ๐ŸŸก = ยฝ, โฌœ = 0; ๐Ÿšซ left out) for `tier` +/// (`None` = all): (percent, rows). +pub fn weighted(doc: &Doc, tier: Option<&str>) -> (f64, usize) { + let rows: Vec<&Row> = doc.rows.iter().filter(|r| r.status != Status::OutOfScope && tier.is_none_or(|t| r.tier == t)).collect(); + let score: f64 = rows + .iter() + .map(|r| match r.status { + Status::Done => 1.0, + Status::Partial => 0.5, + _ => 0.0, + }) + .sum(); + (if rows.is_empty() { 0.0 } else { score * 100.0 / rows.len() as f64 }, rows.len()) +} + +/// "Weighted completion: 65.7% of 500 rows (P0 โ€ฆ, P1 โ€ฆ, P2 โ€ฆ)". +pub fn weighted_line(doc: &Doc) -> String { + let (all, n) = weighted(doc, None); + let tiers: Vec = ["P0", "P1", "P2"] + .iter() + .filter_map(|t| Some(weighted(doc, Some(t))).filter(|w| w.1 > 0).map(|(p, n)| format!("{t} {p:.1}% of {n}"))) + .collect(); + format!("Weighted completion (โœ… = 1, ๐ŸŸก = ยฝ, ๐Ÿšซ left out): **{all:.1}%** of {n} in-scope rows โ€” {}.", tiers.join(" ยท ")) +} + /// Replace the summary between the markers. pub fn with_summary(md: &str, table: &str) -> Option { let b = md.find(BEGIN)? + BEGIN.len(); @@ -397,6 +423,10 @@ old let table = summary_table(&d); assert!(table.contains("| A. Import (IMP) | 1 | 1 | 0 | 1 | 1/1 (100%) | 0/1 (0%) |"), "{table}"); assert!(table.contains("| **Total** | 1 | 1 | 1 | 1 | 1/2 (50%) | 0/1 (0%) |"), "{table}"); + // three in-scope rows: 1 + ยฝ + 0 + assert_eq!(weighted(&d, None), (50.0, 3)); + assert_eq!(weighted(&d, Some("P0")), (50.0, 2)); + assert!(table.contains("**50.0%** of 3 in-scope rows โ€” P0 50.0% of 2 ยท P1 50.0% of 1."), "{table}"); let new = with_summary(SAMPLE, &table).unwrap(); assert!(!new.contains("\nold\n")); assert!(new.contains(&format!("{BEGIN}\n{table}{END}")));