Skip to content

Releases: skymanbp/autoshop

Autoshop v1.0.0

Choose a tag to compare

@skymanbp skymanbp released this 24 Aug 18:07

Autoshop v1.0.0 — the first major release

Autoshop v1.0.0 turns the post-v0.35.0 Lightroom measurement work into a
clearer mask-frame contract, improves modern sidecar import, and makes the
project documentation and release checks harder to drift. The deterministic
develop path remains recipe-based: AI proposes or derives intent, while the
Rust renderer owns the pixels.

What changed since v0.35.0

Rendering fidelity

  • Angled LINEAR masks now evaluate their projection in the frame's pixel/aspect
    metric instead of normalized-coordinate distance (ecb6505). On the measured
    9504×6336 probe, the half-contour error fell from 874 px to 9.8 px;
    axis-aligned gradients and square frames remain byte-stable.
  • RADIAL mask transport now uses Sony 0x7037's measured (i+1)/16 native
    radius law, a metadata-derived full-raw-frame centre, a 64-knot persisted map,
    and the exact-once m_lr^-1 ∘ T_engine sampler (706ac84). All 41 measured
    radial point vectors close to at most 1 px.
  • LINEAR masks now use their measured H2 topology instead of sharing RADIAL's
    pointwise sampler (ad6de62). With correction enabled, Autoshop reconstructs
    the straight gradient in the corrected frame. With correction disabled, it
    transports only the Zero/Full handles and rebuilds one straight line in the
    raw pixel metric.

Lightroom interoperability

  • Camera-metadata lens profiles now preserve the mask-warp centre as
    LensProfile.mask_warp_center; disabled-sidecar LINEAR transport preserves
    its separate camera map as LensProfile.linear_handle_warp.
  • Modern Lightroom MaskBrushTable data can be read from the companion .acr
    content store with strict directory, digest, envelope, Brotli, and payload
    validation (2cb59a5). Supported table-encoded brushes now import and render
    instead of producing the previous named out-of-model refusal.
  • Unmodified table-backed mask groups remain byte-preserved on sidecar merge.
    Unknown or malformed table forms are still refused by name rather than
    guessed or partially imported.
  • The lens-profile refusal model remains explicit: unsupported fisheye LCPs,
    unparseable profiles, and missing profile roots do not silently invent a map.

Masks and local AI

  • Gesture dabs attached to subtype-0 object masks now become ordered positive
    SAM 2.1 point prompts (1e99e84). Prompt transfer uses a bounded temporary
    JSON file rather than an unbounded command line.
  • Only subtype-0 masks that carry gestures receive the new gp1 cache identity
    and re-derive once. Subject masks, sky masks, and gesture-free object masks
    retain their previous cache keys and behavior.
  • Object/background intent remains ambiguous in Lightroom's subtype-0 carrier;
    Autoshop continues to disclose that it locally re-derives an alpha rather than
    importing Adobe's unavailable raster.
  • The training-data scope comments were audited and corrected (70832eb):
    Autoshop distributes neither ADE20K nor SA-1B, while the downloaded
    OneFormer and SAM runtime artifacts remain governed and digest-gated under
    their own MIT and Apache-2.0 terms.

Application and evaluation

  • A new per-user Windows installer needs no administrator access, creates Start
    Menu shortcuts, offers optional desktop and user PATH tasks, and preserves
    the develop store on uninstall.
  • Evaluation rows with fewer than 20 observations are marked [low n], and a
    supplementary n-weighted gap is reported without changing the established
    headline, state-file, or n≥20 definitions (ef5a71a).
  • Retry disclosures now distinguish native Anthropic 529 refusals from relay
    failures that may have completed upstream, and warn that retrying relay
    524/529 failures can incur a second charge.
  • Advisor error bodies use the same bounded read policy as the other response
    paths. Store safety tests now use explicit temporary roots rather than a real
    user data location.
  • A same-version rerun measured a 16.3% evaluation gap versus the 17.7%
    baseline. That 1.4-point resampling swing is comparable to the prior
    1.7-point cross-version change, so the 17.7% figure is not evidence of a
    rendering regression.

Documentation and release gates

  • The README is now a structured install guide, user manual, CLI reference,
    Lightroom/AI explainer, and measured showcase (53bb77f).
  • Architecture and planning docs now state the RADIAL and LINEAR frame laws,
    schema breaks, precision limits, and the current test battery.
  • scripts/check_docs.py now checks the exact README RAW-extension membership,
    the exact no-preview format membership, and README/ARCHITECTURE battery
    consistency in addition to the existing version, count, dependency,
    toolchain, camera, and corpus checks.

Hard changes and compatibility

v1.0.0 remains backward-compatible with older recipes: both new lens-frame
fields have defaults, so recipes written by earlier releases remain readable.
Forward compatibility is deliberately strict. Older executables use
deny_unknown_fields for LensProfile and therefore refuse a v1.0.0 recipe
that carries either mask_warp_center or linear_handle_warp. Refusal is safer
than silently discarding a coordinate transform and rendering the mask in the
wrong frame.

The following existing content can render differently in v1.0.0:

  • angled LINEAR masks on non-square frames, because their metric is now
    pixel/aspect-correct;
  • RADIAL masks paired with camera-metadata lens profiles, because the native
    knot law, map centre, and exact-once transport are now applied;
  • LINEAR masks paired with camera-metadata lens profiles, in both the
    correction-on and correction-off paths, because LINEAR now follows H2;
  • modern table-encoded Lightroom brushes, which move from named refusal to
    actual brush rendering; and
  • subtype-0 object masks with gesture dabs, whose SAM prompt set and scoped
    cache identity now include those dabs.

No released Autoshop version shipped the intermediate 706ac84 LINEAR
behavior; ad6de62 is the v1.0.0 LINEAR contract.

Known limitations

  • RADIAL point transport is 41/41 at ≤1 px, but the R2 large-mask dilation has
    an open residual of about 1.2 percentage points. Clean cells are within
    0.35 pp and R1 is about 0.5 pp.
  • LINEAR H2 is not 1 px-closed. Correction-on residuals are
    9.748/7.025/6.336 px RMS; correction-off residuals are
    12.449/9.943/4.979 px RMS. A fitted anisotropic-aspect term remains diagnostic
    only and is not shipped.
  • AI masks are local re-derivations, not Adobe raster imports. Model or sidecar
    failure leaves the adjustment skipped and disclosed rather than applying an
    inverted mask to the whole frame.
  • The X-Trans path is a geometry-aware approximation, not a
    Markesteijn-class directional demosaic.
  • Generative reimagine/retouch outputs are lossy, resolution-limited targets,
    not full-resolution deliverable masters.
  • Prebuilt artifacts are Windows-only for this release; Linux and macOS are
    built and tested in CI but remain less exercised interactively.

Validation

The v1.0.0 source battery is 871 library tests (862 pass + 9 ignored forensic
probes), 14 CLI tests, 132 GUI-feature tests, and two integration suites with
2 tests each. The GUI-feature Clippy and compile gates are clean.

Checksums

Artifact Size SHA-256
autoshop.exe (CLI) 31,180,152 bytes 116a38410a810b1b27602c97daa4db614241b89fffbb80c6691a275fc7f168c0
autoshop-gui.exe (desktop app) 40,810,704 bytes 847f42c4b35c09ab5dd040fdf8e90f99d597c66624ef131ac02d93071bcb58ce
Autoshop-Setup-1.0.0.exe (installer) 19,768,387 bytes 28c4acd37089e78bf02182cd8b20a214a63cababb1b02971209be3fdf33d4750
autoshop-1.0.0-windows-x64.zip (portable archive) 27,131,443 bytes 47389ed42f80798ead96980d69ce10f5063ece606e0f0d548482c58aef9f717e

v0.35.0

Choose a tag to compare

@skymanbp skymanbp released this 22 Aug 01:03

Autoshop v0.35.0

The largest render-correctness release on this branch: brush masks actually render, the radial feather falloff is a measured 290×11 table, negative texture has its measured shape, every mask samples at pixel centres, parametric masks live in their measured Lightroom frames, and the subject segmenter is a pinned BiRefNet with a named fallback. Seven of these changes are breaking in one direction or another — read the list below before upgrading a shared library.

⚠ Seven hard changes (read before upgrading)

  1. LensProfile schema forward break. The recipe's LensProfile block gains mask_warp + mask_warp_src, always serialised, and the block refuses unknown fields — so every recipe.json written by v0.35.0 is refused by name by v0.34.0 and earlier (the whole recipe, not a dropped field). The reverse is lossless: v0.35.0 reads every old recipe, an empty mask_warp is identity, and rendering of old recipes is bit-identical on this axis.

  2. Parametric masks change frames. Lightroom stores a radial/linear in the post-lens-correction frame and a brush in the pre-correction frame; the engine used to read both in one frame. Radial/linear now map through the exact inverse of this engine's own geometry stage; a brush is identity. Old recipes: on a geometry-active frame, radial/linear masks land 0.09–0.30 px from their stored coordinates instead of 8–24 px out — which means those renders change. No lens profile, or geometry off: bit-identical.

  3. Brush masks render. The brush arm was a literal 0.0 (carried, disclosed, not rendered). It is now a real rasteriser — a measured dab kernel, screen accumulation, LR-anchored. Every recipe with an LR brush mask renders differently (the mask used to not exist). The disclosure renames with the behaviour: BrushCarriedBrushRendered — the alpha is our measured model, not Adobe's rasteriser.

  4. Negative texture changes shape. The notch filter is replaced by a measured dual-lowpass elevated step with a hyperbolic depth law, pinned to 45 LR anchors. Everything with texture < 0 (global or per-mask) re-renders; texture ≥ 0 is bit-identical.

  5. Radial feather falloff is now a measured table. After three refuted closed forms, the falloff ships as a measured 290×11 LUT (11 feather columns from a dedicated export ladder); Feather = 0 keeps the analytic hard edge byte-for-byte. Radials with Feather ≥ 10 re-render — at Feather 100 the old law painted 2.08× Lightroom's area.

  6. AI masks all recompute once. The subject backend is a commit-pinned BiRefNet (e2bf8e44…) with a named U²-Net fallback tier, and AI_BACKEND_GENERATION moves 1→2: cached alphas from v0.34 and earlier recompute once on first develop, all three subtypes (sky/object backends did not change; one generation constant covers three fields by design). A machine that fell back re-upgrades itself once the dependencies appear, and says why.

  7. Half-pixel sampling. The whole mask family (radial, linear, brush, bitmap, AI) now samples at pixel centres ((x+0.5)/w) — measured against Lightroom on two different frames. Every mask shifts up-left by 0.5 px, independent of feather, geometry, or aspect.

Also in this release

  • Adobe .lcp lens-profile reading: profiles are located, parsed and solved into the recipe as a named model of Lightroom's warp with a seven-state provenance tag (in-camera knots, solved .lcp, or an honest named refusal). The solved model is carried provenance — not yet a render-time input; a frame this engine does not itself correct still renders masks at their stored coordinates.
  • --long-edge export sizing on the three render commands.
  • One bounded retry for HTTP 524/529 with per-class billing disclosure; eval checkpoint/resume on by default.
  • Segmentation closeout: named backend in every report line, one-shot backend marker migration, digest-pinned model sources, a self-authored ADE20K class table (no third-party licence carry).
  • Pre-release: an independent read-only model review was adjudicated finding-by-finding; two confirmed gaps (a cache entry bound, a bounded .lcp read) landed before this tag. Ledger: docs/ROADMAP.md.

Gates at this tag

  • Battery: 816 lib (9 ignored) / 14 CLI / 132 GUI / 2+2 contract — both configs (default & --features gui), clippy clean.
  • RAW zoo: 9/9 makes decode and self-agree (AUTOSHOP_RAW_ZOO).
  • Real Lightroom sidecars: 7 sidecars / 42 masks imported, 0 refused (AUTOSHOP_MB_FIXTURES).
  • LR probe fixtures: measured-ellipse decode green (AUTOSHOP_LR_PROBE_FIXTURES).
  • check_docs --gates: 22/22. GUI font subset: 803/803. i18n audit: clean.

Downloads

file bytes sha256
autoshop.exe (CLI) 31,063,300 e48f6bbc9a6e9bf4aa98b01240eb6d733136d68320b6e79312d9b239bddfa6c6
autoshop-gui.exe (GUI) 40,706,348 b58b7be4b5e83b3f70e33b8023aba3bcfb985a1762d6eed7e39ef1deafb9a492

Recipes are JSON; v0.35.0 reads every recipe earlier releases wrote. v0.34.0 and earlier refuse v0.35.0 recipes by name (see item 1).

v0.34.0 - X-Trans colour, hardened budgets, typed scopes

Choose a tag to compare

@skymanbp skymanbp released this 20 Aug 12:39

Autoshop v0.34.0 — the R28 round: X-Trans colour, hardened budgets, typed scopes

Five batches, all landed 2026-08-20. No recipe-schema changes: a v0.33.0
binary reads a v0.34.0 recipe and vice versa
— the first feature release
since v0.30 with no forward break.

The headline: Fujifilm X-Trans renders correct colour

Through v0.33.0, X-Trans RAFs developed visibly green and dark. The root cause
was starker than a detail approximation: the Bayer demosaic's chroma pass
assumes the right/down neighbours of a green photosite carry the two chroma
colours, and inside X-Trans's four 2×2 all-green blocks per tile that
assumption fails 16 times per 36 pixels — R was never written (left at zero)
at 8 of every 36 photosites, B at another 8.
No white balance can repair a
per-channel hole.

v0.34.0 demosaics non-Bayer RGB arrays in-tree over the array's own geometry:
every channel is interpolated only from photosites that actually measured it,
with per-phase plane-fit weights (convex, no ringing). Measured on the release
binary against the CC0 X-S10 zoo sample: whole-frame G/R 1.5503 → 0.9473
(the camera's own preview reads 0.95), per-phase channel spread R 157.8 % →
0.34 %. All eight Bayer-format zoo renders hash byte-identical before and
after. Fine detail remains softer than a dedicated X-Trans converter and the
render's disclosure line says so — the old line's "colour, tone and framing
are unaffected" clause was measured false and is gone.

Behaviour changes (all deliberate, all disclosed)

  • Negative Texture is band-limited. texture = −100 used to degenerate to
    a full Gaussian blur (the transfer's endpoint was literally the blurred
    frame). It is now a mid-band smoothing: at −100 a 4 px pattern keeps 96 % of
    its contrast while a 16 px pattern still loses 71 %. The positive branch is
    untouched (it was measured against Lightroom in R27). The negative curve is
    ours and stated as unmeasured — there is no LR ground truth for it in the
    tree, and the sidecar still carries the raw slider value.
  • A RAW too big to develop is refused by name. The RAW door gains the same
    4 GiB per-file peak ceiling the baked door has had for months, charged on a
    header read before any sensor row is decompressed. At the measured
    31 bytes/pixel that is ~138.5 MP and up (a 150 MP back is caught; a 102 MP
    GFX is well clear). The message names the estimate, its basis, and says
    outright that --jobs 1 will not help. Such files used to be attempted and
    would page the machine.
  • AI-mask alphas re-derive once. The segmentation cache key now records
    the frame (quarter turns) it was computed in — closing a bug where a mask
    clicked exactly at the frame centre kept serving its pre-rotation alpha
    sideways. Every alpha cached by v0.33.0 re-runs the local segmenter on its
    first develop (seconds of GPU per mask), reported as a normal re-derivation.
  • AI masks on a saved retouch master now render. The resolver takes the
    photo for identity and the render source for pixels; a baked master used to
    fail the RAW-only staging decoder and the mask was carried inert.
  • The eval hue rows changed meaning. The four color_grade.*_hue rows
    count a photo only when BOTH sides put saturation on that wheel — a hue at
    zero saturation renders nothing, and the old rule manufactured a 141°
    "disagreement" between two colourless wheels. The report discloses that
    these rows are not comparable with pre-v0.34.0 runs.
  • The style-embedding sidecar loads in half precision by default and is
    single-flighted (one resident model regardless of worker count):
    4 × 1.50 GB of fp32 SigLIP weights becomes 1 × 0.75 GB.
    AUTOSHOP_EMBED_FP32=1 restores the old arithmetic exactly.
  • Batch transcripts are attributable. Worker-reachable warnings carry
    their photo's stem, and batch renders the proposer's note channel into
    each photo's own output block the way eval always did.

Hardening (defect classes closed, each with a gate that keeps it closed)

  • Every store-file read goes through the capped readers (four bypasses closed;
    a source-scanning test now fails on any new bare read).
  • Brush-dab truncation cuts on token boundaries and is disclosed on every
    surface; one dab token is bounded at 256 bytes; the import-side clamp
    summary is no longer discarded.
  • XMP read scope is a type (Tag vs Scope): a per-element read can no
    longer silently become a subtree search. Four adversarial scope fixtures pin
    the difference; the 16 real-Lightroom sidecars byte-round-trip unchanged,
    which is the proof the redesign moved no real-LR behaviour.
  • The docs gate lexers handle block comments, cross-check literal counts
    against [&str; N], and mask quoted spans in the TOML census.
  • The --jobs planner consults per-file peaks where headers are free (a
    native-resolution 16-bit TIFF from LR's "Edit in…" can exceed the corpus
    constant on its own, and now says so); the 1,800 MB constant was re-measured
    with the full-resolution render included (peak 1,771 MB — the render tail
    does not raise it) and the probe harness is now in-tree and re-runnable.

Gates at release (both build configurations)

clippy clean ×2 · 727 library (9 #[ignore]d forensic probes) / 11
CLI
/ 131 GUI / 2+2 contract · RAW zoo 9/9 (full test name) · 16/16 real
Lightroom radial sidecars byte-round-tripped · M-B forensic corpus 42/42 masks
· i18n audit 0 · doc-drift gate 11/11 with the release battery transcript.

The format-strip .raf tile in the README was re-rendered with this release.

Also in this release

Cross-platform compilation is CI-verified on ubuntu-latest and
macos-latest in both feature configurations on every push to main (compile
only — no tests run in CI, and no binary has been executed on either
platform). Prebuilt binaries remain Windows-only.

Autoshop v0.33.0

Choose a tag to compare

@skymanbp skymanbp released this 20 Aug 03:55

Autoshop v0.33.0 — R27: multi-format input, parallel processing, and the biggest forensic round yet

Ten batches, five pixel-measurement campaigns, and three controlled Lightroom
experiments (two of them executed via synthesized sidecars — no hand painting).

⚠ Forward-compatibility breaks (v0.32.0 reading v0.33.0 recipes)

  • A v0.33.0 recipe that carries a 90° rotation (quarter_turns), a
    brush mask, or an AI mask entry is hard-refused by the v0.32.0
    exe — a loud schema refusal by design (deny_unknown_fields), never a
    silent drop. Recipes using none of those serialize byte-identically to
    v0.32.0 and stay readable both ways.

Behavior changes

  • Radial masks now render at the sidecar's stored geometry. The former
    1.032 frame constant was proven — by a LensProfileEnable A/B export and
    an 11-dab displacement field — to be one frame's lens-profile warp
    mistaken for a universal affine. Previous builds dilated every imported
    radial by 3.2%. The residual on any frame is now that frame's own
    (unmodelled) Adobe lens warp, 0–3.4% observed; an .lcp reader is the
    candidate fix for R28. Byte round-trips are unaffected.
  • batch transcripts are index-ordered (previously completion-ordered:
    [7/50] could print before [3/50]).

New

  • Multi-format input: 24 RAW extensions (Canon CR2/CR3, Nikon NEF,
    Fujifilm RAF, Olympus ORF, Panasonic RW2, Pentax PEF, DNG, and more —
    validated against a CC0 9-camera zoo) plus baked formats
    (JPEG/PNG/TIFF/WebP/BMP/GIF). Formats without an embedded preview degrade
    to a neutral develop with disclosure; X-Trans demosaics through the
    Bayer path, disclosed per render. .x3f is excluded (upstream decoder
    panics; guarded).
  • --jobs N parallelism on batch and eval, capped by a memory
    budget
    (one 61 MP photo's pipeline pass peaks at ~1.77 GB commit —
    measured, and the cap discloses when it overrules you). The 147-photo eval
    went from 2.3 h serial to 38 min.
  • Lightroom brush and AI masks are carried first-class (byte-exact
    round-trip of dab streams and mask intent). AI masks can be recomputed
    locally
    (SAM 2.1 point-prompted / OneFormer sky / u2net subject), always
    disclosed as a recomputation, never passed off as Adobe's raster.
  • SigLIP2 style embedding (opt-in via AUTOSHOP_STYLE_EMBED): the style
    index can now rank by image content, licence-vetted (Apache-2.0 model),
    sha256-pinned weights.
  • 90° rotation skeleton (⭯/⭮ in the GUI; rotated recipes are the
    forward-break above).
  • Concurrency race fixed in style embedding staging: two photos developed
    in parallel could receive each other's style vectors (shipped since
    R26's three-worker batch pool). Root-fixed for every caller.
  • New 147-pair eval baseline (relay endpoint + 3-way parallel, zero
    fallbacks): gap 15.5%; mask-import refusals 2.35 → 0.05 per photo
    (the mask-import root fix, proven on the full corpus).

Measured this round (docs/ROADMAP.md 当前状态 — the measurement ledger)

The brush alpha model is now fully measured — screen accumulation, density
as a pre-screen scale, a one-parameter flow law (κ = 0.1219 ± 0.0027), an
11-rung hardness kernel table — and the radial feather law was refuted at
both endpoints. Brush masks still render nowhere: the kernel has no closed
form and the mask lives in Lightroom's pre-lens-correction frame, which this
engine cannot yet reproduce. That stays an honest BrushCarried disclosure
rather than a confidently wrong image — the R28 work is named in the docs.

Post-release documentation refresh (2026-08-20)

The docs on main were fully re-aligned to this release after it shipped:
docs/ARCHITECTURE.md now opens at v0.33.0 and names the complete dependency
stack (commit 5cb287e), a doc-drift gate (scripts/check_docs.py, an 11-row
claims registry run before every release) keeps the numbers honest from now
on, and the internal development ledgers (M1_PLAN/V2_PLAN) moved off the
public tree (ea15f99) — docs/ARCHITECTURE.md and this page are the
public-facing documentation. The release binaries above are unchanged: every
commit since the tag touches documentation and code comments only.

v0.32.0 — 径向蒙版几何根修

Choose a tag to compare

@skymanbp skymanbp released this 19 Aug 05:07

v0.32.0 —— 径向蒙版几何根修

素材:用户为此专门拍的 12 张受控 Lightroom 导出 + 对成片的像素级测量(XMP 级预言 8/8 命中,两个旋转主体像素级证实)。

① Lightroom 径向蒙版首次被正确读进来。 crs:Top/Left/Bottom/Right 不是外接框,是椭圆自己那个框在像素帧里的旋转后两个对角。旧的天真读法(本项目、以及可搜索范围内每一个第三方实现都在用)把轴比读错了中位 1.84 倍(p90 4.86、max 40.7),195 个分量里有 16 个根本读不出来(解出负半轴)。新解码零自由参数,符号律(Left>Right ⇒ Angle>0)图库 16/16 契合、p=2.5×10⁻⁵,两个渲染主体在像素上对上(_DSC9689 8.33:1 @ +24.35°;_DSC9685 解码倾角 −60.486° 对实测 −60.5°)。crs:Angle 不再扣留,双向映射(正角=顺时针、pixel-space、椭圆中心枢轴——三路独立定案);16 份真实 sidecar 四角字节级往返,含 LR 自己写的 Left>Right 排布。另测出蒙版活在比导出图大 1.032× 的同心帧里——中心也会动,不只是半轴(角落蒙版差 88 px,2799 px 杠杆上定到 3 px)。

② ⚠ 引擎落笔外沿变宽,旧配方的径向渲染会漂。 曝光梯子反推真实蒙版权重(五帧,长宽比 1.03…7.46)定下 d_in = 1−fd_out = 1+f/2(零自由参数律)。本引擎的外沿一直钉在 d=1,而实测 f=0.5 时在 1.25——即过去每一个径向蒙版都小了 29%。曲线形状(三次平滑)本来就是对的,只有两端点错。修完之后,v0.32.0 之前存的配方里的径向会画得略大、略软;版本快照可回溯,蒙版若来自 LR sidecar,重新导入原 sidecar 即可拿回原意图。

③ ⚠ 每张 Sony ARW 渲染位移 (32, 20) px。 块配准实测本项目渲染整体偏 Lightroom 帧 (+31±6, +20±1) px 纯平移:渲染窗口从传感器左上角起算,而相机与 Lightroom 从 DefaultCropOrigin=(32,20) 起算。现已收编(窄射程:仅同尺寸纯平移时移动 ROI,越界拒收不钳位)。渲染窗口对齐 LR 之后,按旧窗口存下的裁剪构图会相对平移那么多。

另:crs:LocalHue 的文件尺度实测为 180(UI +50 ⇒ 文件 0.277778,×180=50.00004),双向换算与域门同步。极性真值表四行以像素证据补齐合约测试(v0.31.2 的导入语义获像素级确认)。recipe schema 零新字段,旧版 exe 不会因蒙版硬拒新 recipe。

仍未测(码内逐条登记触发条件+收口路径):Roundness/Midpoint 像素含义、Feather=100、竖幅/裁剪帧/|Angle|>45°、半轴尺度 1.0325 vs 1.0065 的 n=2 分歧(最坏 2.6%,低于落笔端点 ±5% 帧间散布)。

门:clippy 0 双配置;620(+10) lib / 8 CLI / 129 GUI / 2+2 合约双配置全绿;audit_i18n 全 9 门 0;字体门 801/801;17 项变异检查修前必红(主审抽查带符号半展 abs 变异复现红);16 份真实径向 sidecar 在 AUTOSHOP_LR_PROBE_FIXTURES 门下字节级往返。

v0.31.2 — 证据修复批(Flipped 解绑 + 多蒙版底形)

Choose a tag to compare

@skymanbp skymanbp released this 18 Aug 17:04

v0.31.2(证据修复批) — 三项,素材=用户自有图库的只读取证(E1-verdict + 多蒙版取证)。

crs:Flipped 与反相解绑(主项)。全库 201 个径向普查:crs:Flippedcrs:MaskInverted 完美反相关(155 + 46,两种相同值组合各 0 例;本批在 7 份 M-B sidecar 上独立复算 23/23,且 27/27 线性渐变根本不带 crs:Flipped)。即 Lightroom 把同一个反相位写了两遍。本引擎的 Radial::flippedinverted 按 XOR 合成,两半都读进来等于把一个值和它的补 XOR——导入的每一个 LR 径向都被无条件反相,与文件内容无关;对 LR 不反相的那 155 个是错的。修=导入只认 crs:MaskInverted,写出侧两个属性都从净反相派生,因此只会写出 Lightroom 自己会写的组合——这正是该投影在「LR 渲染器到底读哪个属性」两种读法下都成立的原因。实测(E1-verdict §6):DSC09568 对真实 LR 导出的 tone-matched RMS 0.1099 → 0.0751,蓝通道 0.1901 → 0.0869。我方 flipped 语义不变(仍渲染、仍是 GUI「翻转」勾选),既有 recipe 渲染一像素不变,recipe schema 零改动(不新增字段=不触发 v0.31.0/1 exe 的蒙版硬拒)。已知边界:≤v0.31.1 我方写的带翻转 sidecar 现在读回为不反相——这不是新损失,Lightroom 本来就那样读它,两个方向自此与 Lightroom 一致;往返后净反相精确保留,但承载位从「翻转」并入「反相」勾选。

两处注释旋向改正(只改注释,码不动):render.rs / recipe.rs 都写成「逆时针,y-down 屏幕意义」,实测为顺时针(引擎角 +30 渲出右端朝下;符号检验 5/5,p=0.031,supported 级、未到 proven)。矩阵 R(+θ) 在 y-up 数学系里确是逆时针——旧注释带着 y-up 的读数却声称 y-down。

多蒙版 Correction 取错底形。原选择器按种类选几何(Mask/Gradient 恒优先)且完全无视 crs:MaskBlendModeDSC08960 蒙版 3 与 _DSC9583 Mask 9 都是「径向底形 + 线性减法」,结果留下 LR 用来抠掉的那块、丢掉底形——是意图反转,不是截断。修=优先默认 BlendMode 的组件(全为减法时才落到首个)。另修披露失真:Rotation 注记只对实际导入的几何发(DSC08960 原本报四条,三条描述从未进入 recipe 的径向);BlendMode 保持组件级——它对被丢弃的减法组件是真话,也正是 v0.31.1 为该情形加的披露。实测恢复 3 个蒙版(DSC08960 径向 {3}→{1,3,4},_DSC9583 {0..7} 全入)。登记不修:CLI 零蒙版披露(通道设计缺口)、unknown_component 预占的参数化形状账(披露粒度设计)。

门:clippy 0(双配置);610(+4) lib / 8 CLI / 129 GUI / 2+2 合约双配置全绿;audit_i18n 全 9 门 0;无新 zh 词条(字体门不受影响);6 项变异检查修前必红(主审抽查 first_base.or(first)first 复现红)。

v0.31.1 — 证据修正补丁:锐化 1:1 / Subtract / Roundness

Choose a tag to compare

@skymanbp skymanbp released this 18 Aug 13:55

v0.31.1 — 证据修正补丁

三条被当作既定事实的 Lightroom 假设,经对 GitHub 公开 sidecar 的只读普查证伪并根修。

  • 锐化数量改为 1:1(会改变导入值)。LR「细节 > 锐化 数量」滑杆上限是 150,sidecar 存原值——15 份真实 sidecar 带 crs:Sharpness="150"(两个仓库、两台相机、两代 LR),旧的 0..100 出自第三方滑杆表而非 Adobe。带锐化的 Lightroom 照片重新导入,数值将变为 1:1(旧读法放大 1.5×,例如 Sharpness="40" 过去读成 60,现在读成 40);写回同样 1:1,你在 Autoshop 里看到的锐化 60 现在写成 "60"(过去写成 "40")。旧配方不迁移:recipe 的 sharpening 驱动的是本机 σ 引擎、语义本就不同于 LR,引擎渲染一个像素都不变;旧写法的真问题是「渲的 60 写成 40」的所见非所写。另外,一份普通的 Sharpness="150" 文件过去会被误报为「数值无法解析」,现已消失。
  • 减法(Subtract)蒙版不再整条丢弃MaskBlendMode="1" 恒伴 MaskValue="0",是 LR 的减法编码而非「哑音蒙版」(157 文件 479 实例全量普查,26/26 无反例)。现在保留基础形状并具名披露「混合模式未复现」,那个 0 绝不会被当成强度乘进去。哑音与真部分覆盖度仍照旧拒收。
  • 圆度(Roundness)滑杆不再导致丢蒙版crs:Roundness 是 ±100 整数滑杆,不是 0..1 比例;旧读法域外即整条拒收。现按原值携带、按原值写回,不做未验证的换算,也不改渲染。

另:eval 报告里 sharpening 一行的用户侧口径随之修正,与 v0.31.0 的 147 张基线该行不可比(其余行不受影响)。

v0.31.0 — R25 收尾闭合轮:Lightroom 差距全量清账

Choose a tag to compare

@skymanbp skymanbp released this 18 Aug 12:07

⚠ 升级前请先读:三类互不相同的前向不兼容

本轮 EditRecipe 数据模型有三处变化,旧版 exe 的反应各不相同,不能混为一谈:

变化 结构 v0.30.0 及更早的 exe 会怎样
EditRecipe 顶层 +29 字段(Texture、裁剪后暗角六、胶片噪点三、Detail 八轴、手动 CA 两、Auto CA、Defringe 六、passthroughschema_era deny_unknown_fields 硬拒整个 recipe.json——v0.31.0 存的任何显影,旧版都打不开(与 v0.29→v0.30 的 coord_era 同类)
LocalAdjustment +4 条局部点曲线 deny_unknown_fields 带蒙版的 recipe 被硬拒;无蒙版的照片字节不变(与 v0.29 的 LocalHue/Sharpness 同类)
MaskGeometry::Radial +2midpoint / mask_version 内部标签枚举, deny_unknown_fields 静默丢弃再写回=旧版会不声不响地把这两个值从你的文件里抹掉。这是本轮首次出现的第三类,最隐蔽

连带recipe.json 的结构指纹随之改变,R21 的「已删版本登记簿」会把历史上已删的版本一次性以新号重新保档(高水位臂不动=同一个号永不复活)。

建议:升级后不要再用旧版 exe 打开新版存过的照片。


本轮做了什么

R25=收尾闭合轮:把 Lightroom 差距一次清账。 八个包(P0-P6 七个实现提交 + 一个轮末对抗复审修复批)。

真正的头等大事不是「补齐 Lightroom 滑杆」,而是一个缺陷

你 Lightroom 库里的每一个蒙版,此前在导入时都被整条丢弃。

两道门,任一命中即丢整条 Correction:crs:Angle 存在(Lightroom 给每个径向都写,未旋转时写 "0")、crs:MaskBlendMode 不是我方文件写的(160 份取证 sidecar 里 1048 个蒙版组件全部带)。这和「INERT_LOCAL 非零硬拒」「未知 crs:Local* 硬拒」等共六道门是同一个根因:导入侧「不认识就整条丢、只给一个整数计数」,而导出侧从 R22 起早就是具名的 MaskLoss{name, reason}——这个不对称本身就是根因

修完之后,在参考库上实测:导入 0 个 → 导入 31 个 / 拒收 11 个(7 份 sidecar、42 条 Correction,导入+拒收==总数 每份成立)。仍然拒收的是画笔 / AI / 深度蒙版(Mask/PaintMask/ImageMask/AggregateMask/Ellipse)——Lightroom 靠 digest 自行重算,第三方拿不到像素,界面上会照实这么说。

新增控件

  • 纹理 Texture(全局,渲染)——与蒙版里的纹理是同一个算子、同一个半径式(位级孪生测试钉死:全覆盖蒙版的 texture ≡ 全局 texture)。
  • 效果新分区:裁剪后暗角六键 + 胶片噪点三键(携带不渲染)。
  • 细节扩充:锐化半径 / 细节 / 边缘蒙版,降噪细节 / 对比,彩色降噪三键(携带不渲染)。
  • 镜头扩充:手动色差 红/青 · 蓝/黄(渲染)、自动色差校正开关、去边 Defringe 六键(携带不渲染)。
  • 变换 / 校准只读段:透视 Upright 八键 + 相机配置文件 + 相机校准七键,原样带进带出、Autoshop 从不解读——所以只显示值,故意不给滑杆
  • 蒙版:每个蒙版有了自己的四条点曲线(主 / 红 / 绿 / 蓝);径向的 crs:Midpoint / crs:Version 读写往返。

「携带不渲染」不是偷懒,是一条明写的裁决:这些算子(Adobe 的胶片颗粒生成器、三种暗角 Style、锐化的 halo 抑制曲线、色度降噪、去边的色相刻度……)都未公开。近似它们=把我们编的算子塞在你和你的照片之间。所以每一条这样的控件自己身上就写着「本机不渲染,仅随 XMP 带出」,保存时也会列出当前生效的整份清单。24 条全局成员逐条带着理由钉在代码里。


可感行为变更(会改变你已有照片的观感/文件)

  1. 带 Lightroom 蒙版的老照片重开,会突然多出蒙版并改变渲染。 这是上面那个缺陷修好的直接结果(与 v0.28.0「蒙版三项上引擎」同类)。
  2. crs:Texture 的照片渲染改变(参考库 160 份里 7 份,最大 +26 那张最明显)——此前该值被静默丢弃。
  3. 带局部点曲线的照片渲染改变(参考库 19/160,共 43 条曲线)。
  4. 每份写出的 sidecar 现在恒含 crs:Texture,即使为 0 → 与旧版相比字节必然不同。
  5. 导入横幅换了说法:从「N unsupported Lightroom correction(s) not applied」改成「已导入 N 个 Lightroom 蒙版,其中 M 项未建模」并点名是哪几项(旋转角度 / 混合模式 / 未建模的滑杆 / 局部点曲线 …)。
  6. 旋转损失现在报角度:「旋转 37° 未写入 XMP(crs:Angle 的符号与旋转基准未经实测)」,而不是含糊地说「有旋转」。crs:Angle 仍然不写出——在读不懂的刻度上断言方向,不如让 Lightroom 用它自己的默认值。
  7. 「暗角」改名「镜头暗角」(与新的「裁剪后暗角」消歧)。
  8. i18n 里在案的承诺「De-fringe in a later batch / 去紫边留待后续批次」已删除——这一批就是它。
  9. Settings 多一条只读披露:当前解析到的 segmentation sidecar 脚本路径 + 为什么它只能用环境变量设置(它会被当作程序执行)。这把 v0.28.0 的「留 R23」正式结案为一次安全裁决,而不是欠账。

接受成本(轮末对抗复审后的裁决,明写在此)

轮末 Opus 5 独立对抗复审判定 BLOCK,抓到一个根因、两处 HIGH(都在真实 sidecar 上对 v0.30.0 做了前后实证):「配方没见过的键,被读成了用户主动清空」

  • 无损导入 + 旧版形状的无蒙版 recipe,存盘会静默删光整个 Lightroom 蒙版块(2/7 份参考文件的 12/42 条被毁,且注记为空——「导入修得越好,文件越没保护」)。
  • v0.30.0 的 recipe 一存盘,会剥掉 Grain / 裁剪后暗角 / 锐化半径,把 crs:Texture="-20" 归零(3/7 份真实照片中招,零披露)。

已在 464008a 一次修完(守门判据换成「底片本来就有蒙版块」;新增 schema_era 时代戳 + 27 键的按键豁免门——旧照片上你真拖过的值仍然会写出,因为那才是声明)。随之而来的两项成本已裁决并登记:

  • 在 Autoshop 里删光蒙版,不再把删除传播到 sidecar。 要删请在 Lightroom 侧删。本轮的主题就是数据保全高于删除手势。
  • 重新发布一个你已经编辑过的蒙版块,会按我方 writer 确定性重铸 MaskName / MaskSyncID

台账口径更正

  • 「803 字形子集」是历史标签。实测 NotoSansSC-autoshop.ttf751 字形 / 739 码点,五字体 cmap 并集 2396 码点;本版字体门 801/801。
  • v0.28.0 登记的「BYTES_PER_PIXEL=24 既往偏低 ~17%」以第一手算账关闭:三时刻并列核算=恰 24 B/px,当年那是复审者的主张而非实测。常数不动、零行为变更,算账写进了测试。

AI 评测重新基线

147 张 RAW+xmp 对照集全量重跑,147/147 零失败,总分歧 14.2%。最大系统性偏差:whites +22.55、blacks −14.18、noise_reduction +11.71(AI 恒加降噪、用户不加)、highlights +11.69、vibrance +10.80、contrast −7.61;主曲线 RMSE 6.1/255。有意思的是一个补偿模式——AI 在曲线里打对比(S 强度 13.7 vs 用户 3.7),同时在 contrast 滑杆上收着打。色温平均偏冷 163K。分数自 v0.29.0 提示词全档重写后已不可跨版本比较,这一份就是新的正式基线

评测里还有一行是上面那个缺陷的独立实证:用户侧蒙版「0.00(+2.35 被我方导入器拒收)」——平均每张照片 2.35 个你的蒙版进不来,正是本版修掉的那个数字。


门线

603 lib + 8 CLI + 129 GUI + 2 + 2 合约测试全绿(双配置);clippy --all-targets --bins --features gui 0 警告;audit_i18n 0;字体覆盖 801/801。

仍然开着的(诚实边界)

  • crs:Angle符号与旋转基准未经实测——库内实测值域已取到 −43.945287 … +44.792686(43/160 非零),但角度写回臂要等一次 Lightroom 已知角度实验。
  • 蒙版 Hue / Sharpness 的 Lightroom 数值尺度未实测;Sharpness 0..100 的假设需要一份 >100 的真实样本才能闭。
  • Defringe 的渲染近似(乙案)留档备用,本版是携带终态
  • 90° 手动旋转推到 v0.32 首项,完整设计骨架已入库(docs/ROADMAP.md)。

v0.30.0 — R24: the data-model round (triage finale)

Choose a tag to compare

@skymanbp skymanbp released this 18 Aug 02:09

Round 3 of 3 of the seventeen-item feedback triage — all seventeen items are now closed at the code level. Full ledger: docs/ROADMAP.md 当前状态 first entry.

What's new

  • Version names & provenance (#8): name your snapshots, see which variant each came from and whether it was saved by you or auto-archived; '+ Save as version' lives on the variant card. A name dies with its number and is never inherited (contract-tested).
  • Apply to Original (#7): copy a fitted variant's develop onto the Original card — pixels stay, source card stays, one Ctrl+Z undoes.
  • One owner for the strip's active slot (#1): every develop writer (Ctrl+S, Analyze, reverse-fit, CLI match, web save, batch paste) now states what it knows through one primitive — a reverse-fit no longer reopens as '▣ Original'.
  • Five-tier control registry + delivery root (#15b/M8): what renders vs what exports is now a compile-enforced fact with derived disclosure in all three directions; the ./out folder is a real setting (Settings → Delivery folder) with read-only-library warnings.
  • Portrait RAWs render upright (#17, the real fix): rawler hard-codes orientation to Normal upstream ('// TODO fixme' in its source), so every portrait ARW/CR3/NEF was sideways in thumbnails, canvas and exports since v0.11 — DNG being the lone exception. Fixed via the EXIF tag directly; existing portrait edits migrate automatically (coordinates rotate losslessly on first load, disclosed by toast; raster masks are disclosed, not silently turned).
  • The joint ladder is final: recalibrated on six real same-frame pairs from an actual library. The pair that produced a 'completely nonsense' fit now raises the joint warning and caps at floor confidence (it used to read 0.578 and stay silent); the cropped-reference warning now also caps confidence at 0.5 (a measured number: framing alone can manufacture ±23 saturation).

BREAKING (app-internal): a v0.29 exe cannot read recipe.json files saved by v0.30 (new coord_era field under the established deny_unknown_fields forward posture). XMP sidecars are unaffected.

Also: AI Denoise now disables itself with a localized explanation when the python sidecar isn't shipped (instead of failing in English after the click); error messages no longer leak internal Rust symbol paths; Analyze shares Ctrl+S's refusal semantics on an unresolved variants.json (deliberate consistency).

Gates: clippy 0 (both configs); 543 lib + 8 CLI + 114 GUI + 2+2 contract tests green (both configs); audit_i18n 0.

v0.29.0 — R23: the AI overhaul round

Choose a tag to compare

@skymanbp skymanbp released this 17 Aug 21:17

R23 of the seventeen-item feedback triage (round 2 of 3). Full ledger: docs/ROADMAP.md 当前状态 first entry.

What's new

  • The model knows every tool (#12): a compiler-enforced control registry drives the schema, the prompt catalogue and the eval ruler from one source. HSL replies with short axes are repaired instead of discarded. Local masks gain hue rotation and signed sharpness.
  • Style library, visible (#6): build/inspect it from the AI panel; the proposal disclosure now names which library and which neighbour shots fed it, and survives judge revisions.
  • Strength slider (#5): one 0-1 dial through all six restraint gates. Default 0.65; 0.5 restores the calibrated guardrail NUMBERS bit-for-bit (the old restraint wording is the ≤0.4 band — no single setting reproduces an old release in full). White-point protection is now a floor the soft caps can never shave, at any strength.
  • Deep thinking (#13): scene → per-family tool plan → intended look → recipe → self-critique, with multi-round visual review (2 rounds balanced / 3 committed). Off = request bytes identical to v0.28.0. Batch and eval never iterate.
  • Reverse-fit overhaul (#3/#16): honest confidence (one calibrated ladder, named constants), any same-frame rendition as reference, and a second independent reading over 8 joint value-range buckets that finally exposes the 'nonsense fit' in numbers (report + confidence cap + one fail-open terminal veto). Opt-in deep fit judges BEFORE saving and may buy one guided retry from a closed action list — the reviewer's text can never set a slider.

Behaviour notes

  • Recipes whose masks use the new hue/sharpness fields are rejected by older exes (forward-compat contract; mask-free recipes are byte-identical).
  • Deleted-version snapshots stay deleted: a schema-drifted registry arm re-archives once under NEW numbers, never resurrecting an old one.
  • Strength above 70% raises the visual-review ceiling to 3 rounds (worst case 17 API calls) — same ceiling as Deep thinking, either one alone does it; every tooltip says so.
  • Eval scores are not comparable across R23 (the proposer prose changed at every strength); the 147-photo re-baseline is pending.

Gates: clippy 0 (both configs); 518 lib + 8 CLI + 99 GUI + 2 contract tests green (both configs); audit_i18n 0.