- 새 crate kebab-parse-image 추가 (workspace 19개째). MediaType::Image(_)
자산을 단일-블록 CanonicalDocument 로 변환하는 ImageExtractor 구현.
- parser_version "image-meta-v1" (§9 versioning).
- 본문은 Block::ImageRef 1건만 포함 — OCR / caption 필드는 None 으로
남겨 두고 P6-2 / P6-3 에서 채운다.
- EXIF 화이트리스트 (§9.1, PII 표면 최소화):
Make / Model / Software / DateTimeOriginal / Orientation /
GPSLatitude(+Ref) / GPSLongitude(+Ref). MakerNote / Thumbnail / 기타
태그는 폐기. DateTime 은 EXIF "YYYY:MM:DD HH:MM:SS" → ISO-8601 변환.
GPS DMS triple + N/S/E/W ref → signed decimal degree.
- 차원: image::ImageReader 헤더만 읽어 (w, h, format) 획득. 16k×16k cap
초과 또는 디코드 실패 → metadata.user.dimensions = null + Provenance
Warning 이벤트 (Err 아님). 포맷 자체 인식 실패 → anyhow::Error
(caller skip).
- SourceSpan::Region { 0, 0, w, h } 으로 전체 이미지 영역 표기. 결정성:
동일 bytes + 동일 parser_version → 동일 doc_id + block_id (§4.2 ID
recipe 그대로 사용).
- metadata.source_type = Reference, trust_level = Primary, lang = "und".
title = 확장자 제외 파일명, alt = 파일명.
- 의존성 경계 (§8): kebab-core 만 + image 0.25 (default features off,
png/jpeg/webp/gif/tiff 만), kamadak-exif 0.6, anyhow / serde /
serde_json / time / tracing / thiserror. kebab-source-fs · parse-md ·
store-* · embed* · llm* · rag · UI crate 미참조.
- 테스트 14개 (4 unit + 10 integration):
• PNG 차원 추출, JPEG EXIF GPS 추출 (DMS → decimal 변환 정확도 1e-6),
EXIF 없는 PNG → 빈 map, 손상 PNG → warning + null dims (panic 없음),
인식 불가 bytes → Err, 결정성, 스냅샷, supports() 매칭, media_type
불일치 거부.
• 픽스처는 in-memory 생성 (PNG 는 image crate, EXIF JPEG 는 kamadak
Writer 로 EXIF blob 만든 뒤 SOI 직후 APP1 splice) — 바이너리
fixture 커밋 없음.
- HEIC / RAW 는 spec 상 v1 out of scope (image crate 미지원, Apple
Vision sidecar 가 추후 P+ 에서 채움).
- tasks/p6/p6-1-image-extractor-exif.md status: planned → completed.
contract: docs/superpowers/specs/2026-04-27-kebab-final-form-design.md
sections: §3.4 Block::ImageRef + ImageRefBlock, §3.7a OcrText /
ModelCaption stubs, §9.1 image extraction policy, §9 versioning.
87 lines
3.1 KiB
TOML
87 lines
3.1 KiB
TOML
[workspace]
|
|
resolver = "3"
|
|
members = [
|
|
"crates/kebab-core",
|
|
"crates/kebab-parse-types",
|
|
"crates/kebab-config",
|
|
"crates/kebab-source-fs",
|
|
"crates/kebab-parse-md",
|
|
"crates/kebab-normalize",
|
|
"crates/kebab-chunk",
|
|
"crates/kebab-store-sqlite",
|
|
"crates/kebab-store-vector",
|
|
"crates/kebab-search",
|
|
"crates/kebab-embed",
|
|
"crates/kebab-embed-local",
|
|
"crates/kebab-llm",
|
|
"crates/kebab-llm-local",
|
|
"crates/kebab-rag",
|
|
"crates/kebab-app",
|
|
"crates/kebab-cli",
|
|
"crates/kebab-eval",
|
|
"crates/kebab-parse-image",
|
|
]
|
|
|
|
[workspace.package]
|
|
edition = "2024"
|
|
rust-version = "1.85"
|
|
license = "MIT OR Apache-2.0"
|
|
repository = "https://github.com/altair823/kebab"
|
|
version = "0.1.0"
|
|
|
|
[workspace.dependencies]
|
|
anyhow = "1"
|
|
thiserror = "2"
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
# Golden-fixture loader (P5-1, kebab-eval) parses YAML; pinned in the
|
|
# workspace so future eval-adjacent crates share the same major.
|
|
serde_yaml = "0.9"
|
|
time = { version = "0.3", features = ["serde", "macros", "formatting", "parsing"] }
|
|
uuid = { version = "1", features = ["v7", "serde"] }
|
|
blake3 = "1"
|
|
tracing = "0.1"
|
|
# `bundled` ships SQLite source so the workspace doesn't depend on a
|
|
# system libsqlite3 (matches the kebab-store-sqlite feature set).
|
|
rusqlite = { version = "0.32", features = ["bundled"] }
|
|
globset = "0.4"
|
|
tempfile = "3"
|
|
proptest = "1"
|
|
# fastembed-rs ships ONNX runtime via the `ort-download-binaries` feature
|
|
# in its default set (which also pulls `hf-hub` for first-run model
|
|
# downloads). Pinned to the 4.x line per task p3-2 (current 5.x release
|
|
# remains untested for this workspace).
|
|
fastembed = "4.9"
|
|
# LanceDB embedded vector store (P3-3). 0.23.x pulls arrow / arrow-array /
|
|
# arrow-schema 56.x transitively (via lance 1.0); the kebab-store-vector
|
|
# crate matches that major to share the same Arrow types without a
|
|
# re-export adapter.
|
|
lancedb = { version = "0.23", default-features = false }
|
|
arrow = "56"
|
|
arrow-array = "56"
|
|
arrow-schema = "56"
|
|
tokio = { version = "1", features = ["rt", "macros"] }
|
|
futures = "0.3"
|
|
# Strict citation-marker extraction in kebab-rag (P4-3) needs a single regex
|
|
# pass; pulled into the workspace deps so future crates can share the
|
|
# same major.
|
|
regex = "1"
|
|
# Dev-only HTTP mock server for kebab-llm-local Ollama adapter tests. Requires
|
|
# a tokio runtime to host its mock server (the runtime adapter crate stays
|
|
# sync via reqwest::blocking — wiremock is dev-only there).
|
|
wiremock = "0.6"
|
|
|
|
# Disk-footprint trim for dev / test builds. Codegen, opt-level, and
|
|
# behavior are unchanged — only DWARF debug info is reduced (line
|
|
# numbers kept, column numbers dropped) and split into separate
|
|
# `.dwo` files. backtrace stays useful (function + line). release
|
|
# profile is untouched, so CI / `--release` runs are byte-identical
|
|
# to upstream defaults.
|
|
[profile.dev]
|
|
debug = "line-tables-only"
|
|
split-debuginfo = "unpacked"
|
|
|
|
[profile.test]
|
|
debug = "line-tables-only"
|
|
split-debuginfo = "unpacked"
|