UX goal (spikerj): the gallery must show FINISHED products — beautiful singles and stack RESULTS — never 23 bracket frames + 1 composite. Clicking a stack shows its source frames, and its details list every processing step taken (teaching platform transparency).
Design decisions:
ONE upload button (no separate stack-upload): multi-select already groups a pick into a burst via sessionId; NEW server-side EXIF auto-grouping (SubSecDateTimeOriginal deltas ≤ configurable gap, same camera serial) coalesces single-file uploads into bursts too.
Sub-second capture time becomes first-class (currently second-granularity; SubSec only inside RawExifJson) + backfill tool for existing photos.
Stacked/Touchup saves carry artAssetId; the SERVER snapshots provenance onto the new Photograph (sourcePhotographIds + ordered stage/method/model steps from ArtAssetStageRuns) and back-points each source frame (stackedIntoPhotographId). Also inherits representative gear/exposure metadata from the first source frame (addresses the practical half of #755).
Gallery list gains collapse mode: source frames of completed stacks are hidden by default; unstacked bursts render as ONE cluster tile with a frame-count badge (expand on click); stack results carry a stack badge.
New GET /photos/{id}/provenance → steps + source frames; lightbox gains a "How this was made" transparency panel (reuses the art-stage-timeline pattern).
Backend + frontend PRs to follow.
UX goal (spikerj): the gallery must show FINISHED products — beautiful singles and stack RESULTS — never 23 bracket frames + 1 composite. Clicking a stack shows its source frames, and its details list every processing step taken (teaching platform transparency).
Design decisions:
- ONE upload button (no separate stack-upload): multi-select already groups a pick into a burst via sessionId; NEW server-side EXIF auto-grouping (SubSecDateTimeOriginal deltas ≤ configurable gap, same camera serial) coalesces single-file uploads into bursts too.
- Sub-second capture time becomes first-class (currently second-granularity; SubSec only inside RawExifJson) + backfill tool for existing photos.
- Stacked/Touchup saves carry artAssetId; the SERVER snapshots provenance onto the new Photograph (sourcePhotographIds + ordered stage/method/model steps from ArtAssetStageRuns) and back-points each source frame (stackedIntoPhotographId). Also inherits representative gear/exposure metadata from the first source frame (addresses the practical half of #755).
- Gallery list gains collapse mode: source frames of completed stacks are hidden by default; unstacked bursts render as ONE cluster tile with a frame-count badge (expand on click); stack results carry a stack badge.
- New GET /photos/{id}/provenance → steps + source frames; lightbox gains a "How this was made" transparency panel (reuses the art-stage-timeline pattern).
Backend + frontend PRs to follow.
Implementation up: spikersoft-backend PR #446 + spikersoft-angular PR #510 (contract-matched, both suites fully green). Backfill DRY RUN against prod validated: 11 photographs — your OM ORFs carry NO SubSecTimeOriginal in EXIF, so precise time falls back to whole seconds (burst detection still works: the 10-frame bracket spans 2 consecutive seconds, well inside the 2s gap); 0 regroupings needed because the existing burst already has its upload session — correct idempotent behavior. Real backfill run scheduled for after merge+deploy.
Implementation up: spikersoft-backend PR #446 + spikersoft-angular PR #510 (contract-matched, both suites fully green). Backfill DRY RUN against prod validated: 11 photographs — your OM ORFs carry NO SubSecTimeOriginal in EXIF, so precise time falls back to whole seconds (burst detection still works: the 10-frame bracket spans 2 consecutive seconds, well inside the 2s gap); 0 regroupings needed because the existing burst already has its upload session — correct idempotent behavior. Real backfill run scheduled for after merge+deploy.
#446 + #510 merged and deployed (API converged, PhotographProcessor worker running new image — EXIF auto-grouping live for future uploads). Real backfill executed: 11/11 photographs gained TakenAtPrecise (whole-second fallback — ORFs carry no SubSec), 0 regroupings needed (correct: the existing burst already has its upload session). Follow-up PRs for the user-reported deletion gap: backend #447 + angular #511 (owner soft-delete; deleting a stacked result un-consumes its source frames). Remaining to close this ticket: merge #447/#511 + user walkthrough of the new gallery (burst tile, stack badge, provenance panel). #755 can be commented/closed alongside — stacked saves now inherit gear/exposure metadata from their first source frame.
#446 + #510 merged and deployed (API converged, PhotographProcessor worker running new image — EXIF auto-grouping live for future uploads). Real backfill executed: 11/11 photographs gained TakenAtPrecise (whole-second fallback — ORFs carry no SubSec), 0 regroupings needed (correct: the existing burst already has its upload session). Follow-up PRs for the user-reported deletion gap: backend #447 + angular #511 (owner soft-delete; deleting a stacked result un-consumes its source frames). Remaining to close this ticket: merge #447/#511 + user walkthrough of the new gallery (burst tile, stack badge, provenance panel). #755 can be commented/closed alongside — stacked saves now inherit gear/exposure metadata from their first source frame.
All merged: backend #446/#447 (deployed) + angular #510/#511 (deploy in the current master pipeline). Burst auto-grouping live in the worker, backfill run (11/11), collapse gallery + provenance panel + owner deletion complete. Operator has been exercising the new gallery/touch-up daily. Closing.
All merged: backend #446/#447 (deployed) + angular #510/#511 (deploy in the current master pipeline). Burst auto-grouping live in the worker, backfill run (11/11), collapse gallery + provenance panel + owner deletion complete. Operator has been exercising the new gallery/touch-up daily. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
UX goal (spikerj): the gallery must show FINISHED products — beautiful singles and stack RESULTS — never 23 bracket frames + 1 composite. Clicking a stack shows its source frames, and its details list every processing step taken (teaching platform transparency).
Design decisions:
Backend + frontend PRs to follow.
Implementation up: spikersoft-backend PR #446 + spikersoft-angular PR #510 (contract-matched, both suites fully green). Backfill DRY RUN against prod validated: 11 photographs — your OM ORFs carry NO SubSecTimeOriginal in EXIF, so precise time falls back to whole seconds (burst detection still works: the 10-frame bracket spans 2 consecutive seconds, well inside the 2s gap); 0 regroupings needed because the existing burst already has its upload session — correct idempotent behavior. Real backfill run scheduled for after merge+deploy.
#446 + #510 merged and deployed (API converged, PhotographProcessor worker running new image — EXIF auto-grouping live for future uploads). Real backfill executed: 11/11 photographs gained TakenAtPrecise (whole-second fallback — ORFs carry no SubSec), 0 regroupings needed (correct: the existing burst already has its upload session). Follow-up PRs for the user-reported deletion gap: backend #447 + angular #511 (owner soft-delete; deleting a stacked result un-consumes its source frames). Remaining to close this ticket: merge #447/#511 + user walkthrough of the new gallery (burst tile, stack badge, provenance panel). #755 can be commented/closed alongside — stacked saves now inherit gear/exposure metadata from their first source frame.
All merged: backend #446/#447 (deployed) + angular #510/#511 (deploy in the current master pipeline). Burst auto-grouping live in the worker, backfill run (11/11), collapse gallery + provenance panel + owner deletion complete. Operator has been exercising the new gallery/touch-up daily. Closing.